Merge pull request #248 from mochi/follow-up-247

v3.1.0
diff --git a/CHANGES.md b/CHANGES.md
index 16d14f7..e851ce3 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,10 @@
+Version 3.1.0 released 2022-08-21
+
+* Leading and trailing whitespace in header values are now trimmed
+  for better RFC 7230 compliance.
+  https://github.com/mochi/mochiweb/pull/247
+  https://github.com/mochi/mochiweb/pull/248
+
 Version 3.0.0 released 2022-05-09
 
 * rebar3 is now the preferred build tool (finally)
diff --git a/src/mochiweb.app.src b/src/mochiweb.app.src
index 6baf6bf..425e220 100644
--- a/src/mochiweb.app.src
+++ b/src/mochiweb.app.src
@@ -1,7 +1,7 @@
 %% This is generated from src/mochiweb.app.src
 {application, mochiweb,
  [{description, "MochiMedia Web Server"},
-  {vsn, "3.0.0"},
+  {vsn, "3.1.0"},
   {modules, []},
   {registered, []},
   {env, []},
diff --git a/src/mochiweb_headers.erl b/src/mochiweb_headers.erl
index d9bc3af..afb8a1f 100644
--- a/src/mochiweb_headers.erl
+++ b/src/mochiweb_headers.erl
@@ -216,7 +216,7 @@
     reversed_tokens(trim_and_reverse(V, false), [], []).
 
 trim_leading_and_trailing_ws(S) ->
-    re:replace(S, "^[ \\t]*|[ \\t]*$", "", [global, {return, list}]).
+    trim_and_reverse(trim_and_reverse(S, false), false).
 
 trim_and_reverse([S | Rest], Reversed) when S=:=$ ; S=:=$\n; S=:=$\t ->
     trim_and_reverse(Rest, Reversed);
@@ -367,6 +367,13 @@
        to_list(H)),
     ok.
 
+whitespace_headers_test() ->
+    %% Check RFC 7230 whitespace compliance
+    H = ?MODULE:make([{"X-Auth-Roles", "      test, test2,test3,       test4,    test5     ,        test6     "}]),
+    ?assertEqual(
+       [{"X-Auth-Roles", "test, test2,test3,       test4,    test5     ,        test6"}],
+       to_list(H)).
+
 headers_test() ->
     H = ?MODULE:make([{hdr, foo}, {"Hdr", "bar"}, {'Hdr', 2}]),
     [{hdr, "foo, bar, 2"}] = ?MODULE:to_list(H),