diff options
Diffstat (limited to 'src/cowboy_req.erl')
-rw-r--r-- | src/cowboy_req.erl | 132 |
1 files changed, 87 insertions, 45 deletions
diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl index 17ae0de..dddf92e 100644 --- a/src/cowboy_req.erl +++ b/src/cowboy_req.erl @@ -42,7 +42,7 @@ -module(cowboy_req). %% Request API. --export([new/14]). +-export([new/13]). -export([method/1]). -export([version/1]). -export([peer/1]). @@ -104,10 +104,9 @@ -export([ensure_response/2]). %% Private setter/getter API. +-export([get/2]). +-export([set/2]). -export([set_bindings/4]). --export([get_resp_state/1]). --export([get_buffer/1]). --export([get_connection/1]). %% Misc API. -export([compact/1]). @@ -157,8 +156,7 @@ resp_body = <<>> :: iodata() | {non_neg_integer(), resp_body_fun()}, %% Functions. - onresponse = undefined :: undefined | cowboy_protocol:onresponse_fun(), - urldecode :: {fun((binary(), T) -> binary()), T} + onresponse = undefined :: undefined | cowboy_protocol:onresponse_fun() }). -opaque req() :: #http_req{}. @@ -176,16 +174,15 @@ -spec new(inet:socket(), module(), binary(), binary(), binary(), binary(), cowboy_http:version(), cowboy_http:headers(), binary(), inet:port_number() | undefined, binary(), boolean(), - undefined | cowboy_protocol:onresponse_fun(), - undefined | {fun(), atom()}) + undefined | cowboy_protocol:onresponse_fun()) -> req(). new(Socket, Transport, Method, Path, Query, Fragment, Version, Headers, Host, Port, Buffer, CanKeepalive, - OnResponse, URLDecode) -> + OnResponse) -> Req = #http_req{socket=Socket, transport=Transport, pid=self(), method=Method, path=Path, qs=Query, fragment=Fragment, version=Version, headers=Headers, host=Host, port=Port, buffer=Buffer, - onresponse=OnResponse, urldecode=URLDecode}, + onresponse=OnResponse}, case CanKeepalive of false -> Req#http_req{connection=close}; @@ -289,10 +286,9 @@ qs_val(Name, Req) when is_binary(Name) -> %% missing. -spec qs_val(binary(), Req, Default) -> {binary() | true | Default, Req} when Req::req(), Default::any(). -qs_val(Name, Req=#http_req{qs=RawQs, qs_vals=undefined, - urldecode={URLDecFun, URLDecArg}}, Default) when is_binary(Name) -> - QsVals = cowboy_http:x_www_form_urlencoded( - RawQs, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), +qs_val(Name, Req=#http_req{qs=RawQs, qs_vals=undefined}, Default) + when is_binary(Name) -> + QsVals = cowboy_http:x_www_form_urlencoded(RawQs), 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 @@ -302,10 +298,8 @@ qs_val(Name, Req, Default) -> %% @doc Return the full list of query string values. -spec qs_vals(Req) -> {list({binary(), binary() | true}), Req} when Req::req(). -qs_vals(Req=#http_req{qs=RawQs, qs_vals=undefined, - urldecode={URLDecFun, URLDecArg}}) -> - QsVals = cowboy_http:x_www_form_urlencoded( - RawQs, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), +qs_vals(Req=#http_req{qs=RawQs, qs_vals=undefined}) -> + QsVals = cowboy_http:x_www_form_urlencoded(RawQs), qs_vals(Req#http_req{qs_vals=QsVals}); qs_vals(Req=#http_req{qs_vals=QsVals}) -> {QsVals, Req}. @@ -739,17 +733,16 @@ skip_body(Req) -> {error, Reason} -> {error, Reason} end. -%% @doc Return the full body sent with the reqest, parsed as an +%% @doc Return the full body sent with the request, parsed as an %% application/x-www-form-urlencoded string. Essentially a POST query string. %% @todo We need an option to limit the size of the body for QS too. -spec body_qs(Req) -> {ok, [{binary(), binary() | true}], Req} | {error, atom()} when Req::req(). -body_qs(Req=#http_req{urldecode={URLDecFun, URLDecArg}}) -> +body_qs(Req) -> case body(Req) of {ok, Body, Req2} -> - {ok, cowboy_http:x_www_form_urlencoded( - Body, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), Req2}; + {ok, cowboy_http:x_www_form_urlencoded(Body), Req2}; {error, Reason} -> {error, Reason} end. @@ -993,27 +986,78 @@ ensure_response(#http_req{socket=Socket, transport=Transport, %% Private setter/getter API. %% @private +-spec get(atom(), req()) -> any(); ([atom()], req()) -> any(). +get(List, Req) when is_list(List) -> + [g(Atom, Req) || Atom <- List]; +get(Atom, Req) when is_atom(Atom) -> + g(Atom, Req). + +g(bindings, #http_req{bindings=Ret}) -> Ret; +g(body_state, #http_req{body_state=Ret}) -> Ret; +g(buffer, #http_req{buffer=Ret}) -> Ret; +g(connection, #http_req{connection=Ret}) -> Ret; +g(cookies, #http_req{cookies=Ret}) -> Ret; +g(fragment, #http_req{fragment=Ret}) -> Ret; +g(headers, #http_req{headers=Ret}) -> Ret; +g(host, #http_req{host=Ret}) -> Ret; +g(host_info, #http_req{host_info=Ret}) -> Ret; +g(meta, #http_req{meta=Ret}) -> Ret; +g(method, #http_req{method=Ret}) -> Ret; +g(multipart, #http_req{multipart=Ret}) -> Ret; +g(onresponse, #http_req{onresponse=Ret}) -> Ret; +g(p_headers, #http_req{p_headers=Ret}) -> Ret; +g(path, #http_req{path=Ret}) -> Ret; +g(path_info, #http_req{path_info=Ret}) -> Ret; +g(peer, #http_req{peer=Ret}) -> Ret; +g(pid, #http_req{pid=Ret}) -> Ret; +g(port, #http_req{port=Ret}) -> Ret; +g(qs, #http_req{qs=Ret}) -> Ret; +g(qs_vals, #http_req{qs_vals=Ret}) -> Ret; +g(resp_body, #http_req{resp_body=Ret}) -> Ret; +g(resp_headers, #http_req{resp_headers=Ret}) -> Ret; +g(resp_state, #http_req{resp_state=Ret}) -> Ret; +g(socket, #http_req{socket=Ret}) -> Ret; +g(transport, #http_req{transport=Ret}) -> Ret; +g(version, #http_req{version=Ret}) -> Ret. + +%% @private +-spec set([{atom(), any()}], Req) -> Req when Req::req(). +set([], Req) -> Req; +set([{bindings, Val}|Tail], Req) -> set(Tail, Req#http_req{bindings=Val}); +set([{body_state, Val}|Tail], Req) -> set(Tail, Req#http_req{body_state=Val}); +set([{buffer, Val}|Tail], Req) -> set(Tail, Req#http_req{buffer=Val}); +set([{connection, Val}|Tail], Req) -> set(Tail, Req#http_req{connection=Val}); +set([{cookies, Val}|Tail], Req) -> set(Tail, Req#http_req{cookies=Val}); +set([{fragment, Val}|Tail], Req) -> set(Tail, Req#http_req{fragment=Val}); +set([{headers, Val}|Tail], Req) -> set(Tail, Req#http_req{headers=Val}); +set([{host, Val}|Tail], Req) -> set(Tail, Req#http_req{host=Val}); +set([{host_info, Val}|Tail], Req) -> set(Tail, Req#http_req{host_info=Val}); +set([{meta, Val}|Tail], Req) -> set(Tail, Req#http_req{meta=Val}); +set([{method, Val}|Tail], Req) -> set(Tail, Req#http_req{method=Val}); +set([{multipart, Val}|Tail], Req) -> set(Tail, Req#http_req{multipart=Val}); +set([{onresponse, Val}|Tail], Req) -> set(Tail, Req#http_req{onresponse=Val}); +set([{p_headers, Val}|Tail], Req) -> set(Tail, Req#http_req{p_headers=Val}); +set([{path, Val}|Tail], Req) -> set(Tail, Req#http_req{path=Val}); +set([{path_info, Val}|Tail], Req) -> set(Tail, Req#http_req{path_info=Val}); +set([{peer, Val}|Tail], Req) -> set(Tail, Req#http_req{peer=Val}); +set([{pid, Val}|Tail], Req) -> set(Tail, Req#http_req{pid=Val}); +set([{port, Val}|Tail], Req) -> set(Tail, Req#http_req{port=Val}); +set([{qs, Val}|Tail], Req) -> set(Tail, Req#http_req{qs=Val}); +set([{qs_vals, Val}|Tail], Req) -> set(Tail, Req#http_req{qs_vals=Val}); +set([{resp_body, Val}|Tail], Req) -> set(Tail, Req#http_req{resp_body=Val}); +set([{resp_headers, Val}|Tail], Req) -> set(Tail, Req#http_req{resp_headers=Val}); +set([{resp_state, Val}|Tail], Req) -> set(Tail, Req#http_req{resp_state=Val}); +set([{socket, Val}|Tail], Req) -> set(Tail, Req#http_req{socket=Val}); +set([{transport, Val}|Tail], Req) -> set(Tail, Req#http_req{transport=Val}); +set([{version, Val}|Tail], Req) -> set(Tail, Req#http_req{version=Val}). + +%% @private -spec set_bindings(cowboy_dispatcher:tokens(), cowboy_dispatcher:tokens(), cowboy_dispatcher:bindings(), Req) -> Req when Req::req(). set_bindings(HostInfo, PathInfo, Bindings, Req) -> Req#http_req{host_info=HostInfo, path_info=PathInfo, bindings=Bindings}. -%% @private --spec get_resp_state(req()) -> locked | waiting | chunks | done. -get_resp_state(#http_req{resp_state=RespState}) -> - RespState. - -%% @private --spec get_buffer(req()) -> binary(). -get_buffer(#http_req{buffer=Buffer}) -> - Buffer. - -%% @private --spec get_connection(req()) -> keepalive | close. -get_connection(#http_req{connection=Connection}) -> - Connection. - %% Misc API. %% @doc Compact the request data by removing all non-system information. @@ -1090,15 +1134,13 @@ response_connection([], Connection) -> Connection; response_connection([{Name, Value}|Tail], Connection) -> case Name of - <<"connection">> -> response_connection_parse(Value); - _ -> response_connection(Tail, Connection) + <<"connection">> -> + Tokens = parse_connection_before(Value, []), + connection_to_atom(Tokens); + _ -> + response_connection(Tail, Connection) end. --spec response_connection_parse(binary()) -> keepalive | close. -response_connection_parse(ReplyConn) -> - Tokens = cowboy_http:nonempty_list(ReplyConn, fun cowboy_http:token/2), - connection_to_atom(Tokens). - -spec response_merge_headers(cowboy_http:headers(), cowboy_http:headers(), cowboy_http:headers()) -> cowboy_http:headers(). response_merge_headers(Headers, RespHeaders, DefaultHeaders) -> @@ -1184,7 +1226,7 @@ parse_connection_after(<< C, Rest/bits >>, Acc) %% @doc Walk through a tokens list and return whether %% the connection is keepalive or closed. %% -%% We don't match on <<"keep-alive">> since it is the default value. +%% We don't match on "keep-alive" since it is the default value. -spec connection_to_atom([binary()]) -> keepalive | close. connection_to_atom([]) -> keepalive; |