Browse Source

Add cowboy_http:x_www_form_urlencoded/2

This was initially an internal function, it has been made public
due to popular demand as it can sometimes be needed.
Loïc Hoguin 13 years ago
parent
commit
a7264a1af3
2 changed files with 33 additions and 37 deletions
  1. 27 1
      src/cowboy_http.erl
  2. 6 36
      src/cowboy_http_req.erl

+ 27 - 1
src/cowboy_http.erl

@@ -24,7 +24,7 @@
 
 %% Interpretation.
 -export([connection_to_atom/1, urldecode/1, urldecode/2, urlencode/1,
-	urlencode/2]).
+	urlencode/2, x_www_form_urlencoded/2]).
 
 -type method() :: 'OPTIONS' | 'GET' | 'HEAD'
 	| 'POST' | 'PUT' | 'DELETE' | 'TRACE' | binary().
@@ -800,6 +800,16 @@ tohexu(C) when C < 17 -> $A + C - 10.
 tohexl(C) when C < 10 -> $0 + C;
 tohexl(C) when C < 17 -> $a + C - 10.
 
+-spec x_www_form_urlencoded(binary(), fun((binary()) -> binary())) ->
+		list({binary(), binary() | true}).
+x_www_form_urlencoded(<<>>, _URLDecode) ->
+	[];
+x_www_form_urlencoded(Qs, URLDecode) ->
+	Tokens = binary:split(Qs, <<"&">>, [global, trim]),
+	[case binary:split(Token, <<"=">>) of
+		[Token] -> {URLDecode(Token), true};
+		[Name, Value] -> {URLDecode(Name), URLDecode(Value)}
+	end || Token <- Tokens].
 
 %% Tests.
 
@@ -967,6 +977,22 @@ digits_test_() ->
 	],
 	[{V, fun() -> R = digits(V) end} || {V, R} <- Tests].
 
+x_www_form_urlencoded_test_() ->
+	%% {Qs, Result}
+	Tests = [
+		{<<"">>, []},
+		{<<"a=b">>, [{<<"a">>, <<"b">>}]},
+		{<<"aaa=bbb">>, [{<<"aaa">>, <<"bbb">>}]},
+		{<<"a&b">>, [{<<"a">>, true}, {<<"b">>, true}]},
+		{<<"a=b&c&d=e">>, [{<<"a">>, <<"b">>},
+			{<<"c">>, true}, {<<"d">>, <<"e">>}]},
+		{<<"a=b=c=d=e&f=g">>, [{<<"a">>, <<"b=c=d=e">>}, {<<"f">>, <<"g">>}]},
+		{<<"a+b=c+d">>, [{<<"a b">>, <<"c d">>}]}
+	],
+	URLDecode = fun urldecode/1,
+	[{Qs, fun() -> R = x_www_form_urlencoded(
+		Qs, URLDecode) end} || {Qs, R} <- Tests].
+
 urldecode_test_() ->
 	U = fun urldecode/2,
 	[?_assertEqual(<<" ">>, U(<<"%20">>, crash)),

+ 6 - 36
src/cowboy_http_req.erl

@@ -51,7 +51,6 @@
 ]). %% Misc API.
 
 -include("include/http.hrl").
--include_lib("eunit/include/eunit.hrl").
 
 %% Request API.
 
@@ -151,7 +150,8 @@ qs_val(Name, Req) when is_binary(Name) ->
 	-> {binary() | true | Default, #http_req{}} when Default::any().
 qs_val(Name, Req=#http_req{raw_qs=RawQs, qs_vals=undefined,
 		urldecode={URLDecFun, URLDecArg}}, Default) when is_binary(Name) ->
-	QsVals = parse_qs(RawQs, fun(Bin) -> URLDecFun(Bin, URLDecArg) end),
+	QsVals = cowboy_http:x_www_form_urlencoded(
+		RawQs, fun(Bin) -> URLDecFun(Bin, URLDecArg) end),
 	qs_val(Name, Req#http_req{qs_vals=QsVals}, Default);
 qs_val(Name, Req, Default) ->
 	case lists:keyfind(Name, 1, Req#http_req.qs_vals) of
@@ -163,7 +163,8 @@ qs_val(Name, Req, Default) ->
 -spec qs_vals(#http_req{}) -> {list({binary(), binary() | true}), #http_req{}}.
 qs_vals(Req=#http_req{raw_qs=RawQs, qs_vals=undefined,
 		urldecode={URLDecFun, URLDecArg}}) ->
-	QsVals = parse_qs(RawQs, fun(Bin) -> URLDecFun(Bin, URLDecArg) end),
+	QsVals = cowboy_http:x_www_form_urlencoded(
+		RawQs, fun(Bin) -> URLDecFun(Bin, URLDecArg) end),
 	qs_vals(Req#http_req{qs_vals=QsVals});
 qs_vals(Req=#http_req{qs_vals=QsVals}) ->
 	{QsVals, Req}.
@@ -405,7 +406,8 @@ body(Length, Req=#http_req{socket=Socket, transport=Transport,
 -spec body_qs(#http_req{}) -> {list({binary(), binary() | true}), #http_req{}}.
 body_qs(Req=#http_req{urldecode={URLDecFun, URLDecArg}}) ->
 	{ok, Body, Req2} = body(Req),
-	{parse_qs(Body, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), Req2}.
+	{cowboy_http:x_www_form_urlencoded(
+		Body, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), Req2}.
 
 %% Multipart Request API.
 
@@ -641,17 +643,6 @@ transport(#http_req{transport=Transport, socket=Socket}) ->
 
 %% Internal.
 
--spec parse_qs(binary(), fun((binary()) -> binary())) ->
-		list({binary(), binary() | true}).
-parse_qs(<<>>, _URLDecode) ->
-	[];
-parse_qs(Qs, URLDecode) ->
-	Tokens = binary:split(Qs, <<"&">>, [global, trim]),
-	[case binary:split(Token, <<"=">>) of
-		[Token] -> {URLDecode(Token), true};
-		[Name, Value] -> {URLDecode(Name), URLDecode(Value)}
-	end || Token <- Tokens].
-
 -spec response_connection(cowboy_http:headers(), keepalive | close)
 	-> keepalive | close.
 response_connection([], Connection) ->
@@ -813,24 +804,3 @@ header_to_binary('Cookie') -> <<"Cookie">>;
 header_to_binary('Keep-Alive') -> <<"Keep-Alive">>;
 header_to_binary('Proxy-Connection') -> <<"Proxy-Connection">>;
 header_to_binary(B) when is_binary(B) -> B.
-
-%% Tests.
-
--ifdef(TEST).
-
-parse_qs_test_() ->
-	%% {Qs, Result}
-	Tests = [
-		{<<"">>, []},
-		{<<"a=b">>, [{<<"a">>, <<"b">>}]},
-		{<<"aaa=bbb">>, [{<<"aaa">>, <<"bbb">>}]},
-		{<<"a&b">>, [{<<"a">>, true}, {<<"b">>, true}]},
-		{<<"a=b&c&d=e">>, [{<<"a">>, <<"b">>},
-			{<<"c">>, true}, {<<"d">>, <<"e">>}]},
-		{<<"a=b=c=d=e&f=g">>, [{<<"a">>, <<"b=c=d=e">>}, {<<"f">>, <<"g">>}]},
-		{<<"a+b=c+d">>, [{<<"a b">>, <<"c d">>}]}
-	],
-	URLDecode = fun cowboy_http:urldecode/1,
-	[{Qs, fun() -> R = parse_qs(Qs, URLDecode) end} || {Qs, R} <- Tests].
-
--endif.