From 8d5f8db90a10a8ca16f8f17bcb076ff4b93e9c63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Sun, 16 Sep 2012 03:51:07 +0200 Subject: Improve consistency of return types for cowboy_req API The signature of parse_header, body_qs, multipart_data and the set_resp_* functions has changed. See the cowboy_req module edoc for more details. --- examples/echo_post/src/toppage_handler.erl | 2 +- src/cowboy_protocol.erl | 2 +- src/cowboy_req.erl | 105 +++++++++++++++++------------ src/cowboy_rest.erl | 66 +++++++++--------- src/cowboy_websocket.erl | 4 +- test/http_SUITE.erl | 4 +- test/http_handler_multipart.erl | 22 +++--- test/http_handler_set_resp.erl | 12 ++-- test/http_handler_stream_body.erl | 2 +- 9 files changed, 116 insertions(+), 103 deletions(-) diff --git a/examples/echo_post/src/toppage_handler.erl b/examples/echo_post/src/toppage_handler.erl index 38fcbce..f8659c9 100644 --- a/examples/echo_post/src/toppage_handler.erl +++ b/examples/echo_post/src/toppage_handler.erl @@ -17,7 +17,7 @@ handle(Req, State) -> {ok, Req4, State}. maybe_echo('POST', true, Req) -> - {PostVals, Req2} = cowboy_req:body_qs(Req), + {ok, PostVals, Req2} = cowboy_req:body_qs(Req), Echo = proplists:get_value(<<"echo">>, PostVals), echo(Echo, Req2); maybe_echo('POST', false, Req) -> diff --git a/src/cowboy_protocol.erl b/src/cowboy_protocol.erl index a1dbb07..04b42a5 100644 --- a/src/cowboy_protocol.erl +++ b/src/cowboy_protocol.erl @@ -212,7 +212,7 @@ header({http_header, _I, 'Connection', _R, Connection}, req_keepalive=Keepalive, max_keepalive=MaxKeepalive}) when Keepalive < MaxKeepalive -> Req2 = Req#http_req{headers=[{'Connection', Connection}|Headers]}, - {ConnTokens, Req3} + {ok, ConnTokens, Req3} = cowboy_req:parse_header('Connection', Req2), ConnAtom = cowboy_http:connection_to_atom(ConnTokens), parse_header(Req3#http_req{connection=ConnAtom}, State); diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl index 07acbe5..7bc8ad6 100644 --- a/src/cowboy_req.erl +++ b/src/cowboy_req.erl @@ -15,10 +15,30 @@ %% @doc HTTP request manipulation API. %% -%% Almost all functions in this module return a new Req variable. -%% It should always be used instead of the one used in your function call -%% because it keeps the state of the request. It also allows Cowboy to do -%% some lazy evaluation and cache results where possible. +%% The functions in this module try to follow this pattern for their +%% return types: +%%
+%%
access:
+%%
{Value, Req}
+%%
action:
+%%
{Result, Req} | {Result, Value, Req} | {error, atom()}
+%%
modification:
+%%
Req
+%%
question (has_* or is_*):
+%%
boolean()
+%%
+%% +%% Exceptions include chunk/2 which always returns 'ok', +%% to_list/1 which returns a list of key/values, +%% and transport/1 which returns {ok, Transport, Socket}. +%% +%% Also note that all body reading functions perform actions, as Cowboy +%% doesn't read the request body until they are called. +%% +%% Whenever Req is returned, it should always be kept in place of +%% the one given as argument in your function call, because it keeps +%% track of the request and response state. Doing so allows Cowboy to do +%% some lazy evaluation and cache results when possible. -module(cowboy_req). %% Request API. @@ -277,12 +297,12 @@ headers(Req) -> %% returned is used as a return value. %% @see parse_header/3 -spec parse_header(cowboy_http:header(), Req) - -> {any(), Req} | {undefined, binary(), Req} + -> {ok, any(), Req} | {undefined, binary(), Req} | {error, badarg} when Req::req(). parse_header(Name, Req=#http_req{p_headers=PHeaders}) -> case lists:keyfind(Name, 1, PHeaders) of false -> parse_header(Name, Req, parse_header_default(Name)); - {Name, Value} -> {Value, Req} + {Name, Value} -> {ok, Value, Req} end. %% @doc Default values for semantic header parsing. @@ -295,7 +315,7 @@ parse_header_default(_Name) -> undefined. %% %% When the header is unknown, the value is returned directly without parsing. -spec parse_header(cowboy_http:header(), Req, any()) - -> {any(), Req} | {undefined, binary(), Req} + -> {ok, any(), Req} | {undefined, binary(), Req} | {error, badarg} when Req::req(). parse_header(Name, Req, Default) when Name =:= 'Accept' -> parse_header(Name, Req, Default, @@ -365,23 +385,15 @@ parse_header(Name, Req, Default) -> {undefined, Value, Req2}. parse_header(Name, Req=#http_req{p_headers=PHeaders}, Default, Fun) -> - case lists:keyfind(Name, 1, PHeaders) of - {Name, P} -> - {P, Req}; - false -> - parse_header_no_cache(Name, Req, Default, Fun) - end. - -parse_header_no_cache(Name, Req=#http_req{p_headers=PHeaders}, Default, Fun) -> case header(Name, Req) of {undefined, Req2} -> - {Default, Req2#http_req{p_headers=[{Name, Default}|PHeaders]}}; + {ok, Default, Req2#http_req{p_headers=[{Name, Default}|PHeaders]}}; {Value, Req2} -> case Fun(Value) of {error, badarg} -> {error, badarg}; P -> - {P, Req2#http_req{p_headers=[{Name, P}|PHeaders]}} + {ok, P, Req2#http_req{p_headers=[{Name, P}|PHeaders]}} end end. @@ -464,8 +476,11 @@ has_body(Req) -> -spec body_length(Req) -> {undefined | non_neg_integer(), Req} when Req::req(). body_length(Req) -> case lists:keymember('Transfer-Encoding', 1, Req#http_req.headers) of - true -> {undefined, Req}; - false -> parse_header('Content-Length', Req, 0) + true -> + {undefined, Req}; + false -> + {ok, Length, Req2} = parse_header('Content-Length', Req, 0), + {Length, Req2} end. %% @doc Initialize body streaming and set custom decoding functions. @@ -505,21 +520,19 @@ init_stream(TransferDecode, TransferState, ContentDecode, Req) -> stream_body(Req=#http_req{body_state=waiting, version=Version, transport=Transport, socket=Socket}) -> case parse_header(<<"Expect">>, Req) of - {[<<"100-continue">>], Req1} -> + {ok, [<<"100-continue">>], Req1} -> HTTPVer = cowboy_http:version_to_binary(Version), Transport:send(Socket, << HTTPVer/binary, " ", (status(100))/binary, "\r\n\r\n" >>); - {undefined, Req1} -> - ok; - {undefined, _, Req1} -> + {ok, undefined, Req1} -> ok end, case parse_header('Transfer-Encoding', Req1) of - {[<<"chunked">>], Req2} -> + {ok, [<<"chunked">>], Req2} -> stream_body(Req2#http_req{body_state= {stream, fun cowboy_http:te_chunked/2, {0, 0}, fun cowboy_http:ce_identity/1}}); - {[<<"identity">>], Req2} -> + {ok, [<<"identity">>], Req2} -> {Length, Req3} = body_length(Req2), case Length of 0 -> @@ -635,11 +648,17 @@ skip_body(Req) -> %% @doc Return the full body sent with the reqest, 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) -> {list({binary(), binary() | true}), Req} when Req::req(). +-spec body_qs(Req) + -> {ok, [{binary(), binary() | true}], Req} | {error, atom()} + when Req::req(). body_qs(Req=#http_req{urldecode={URLDecFun, URLDecArg}}) -> - {ok, Body, Req2} = body(Req), - {cowboy_http:x_www_form_urlencoded( - Body, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), Req2}. + case body(Req) of + {ok, Body, Req2} -> + {ok, cowboy_http:x_www_form_urlencoded( + Body, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), Req2}; + {error, Reason} -> + {error, Reason} + end. %% Multipart Request API. @@ -653,13 +672,13 @@ body_qs(Req=#http_req{urldecode={URLDecFun, URLDecArg}}) -> %% If the request Content-Type is not a multipart one, {error, badarg} %% is returned. -spec multipart_data(Req) - -> {{headers, cowboy_http:headers()} | {body, binary()} - | end_of_part | eof, Req} when Req::req(). + -> {headers, cowboy_http:headers(), Req} | {body, binary(), Req} + | {end_of_part | eof, Req} when Req::req(). multipart_data(Req=#http_req{body_state=waiting}) -> - {{<<"multipart">>, _SubType, Params}, Req2} = + {ok, {<<"multipart">>, _SubType, Params}, Req2} = parse_header('Content-Type', Req), {_, Boundary} = lists:keyfind(<<"boundary">>, 1, Params), - {Length, Req3} = parse_header('Content-Length', Req2), + {ok, Length, Req3} = parse_header('Content-Length', Req2), multipart_data(Req3, Length, {more, cowboy_multipart:parser(Boundary)}); multipart_data(Req=#http_req{multipart={Length, Cont}}) -> multipart_data(Req, Length, Cont()); @@ -668,9 +687,9 @@ multipart_data(Req=#http_req{body_state=done}) -> %% @todo Typespecs. multipart_data(Req, Length, {headers, Headers, Cont}) -> - {{headers, Headers}, Req#http_req{multipart={Length, Cont}}}; + {headers, Headers, Req#http_req{multipart={Length, Cont}}}; multipart_data(Req, Length, {body, Data, Cont}) -> - {{body, Data}, Req#http_req{multipart={Length, Cont}}}; + {body, Data, Req#http_req{multipart={Length, Cont}}}; multipart_data(Req, Length, {end_of_part, Cont}) -> {end_of_part, Req#http_req{multipart={Length, Cont}}}; multipart_data(Req, 0, eof) -> @@ -697,33 +716,33 @@ multipart_skip(Req) -> case multipart_data(Req) of {end_of_part, Req2} -> {ok, Req2}; {eof, Req2} -> {ok, Req2}; - {_Other, Req2} -> multipart_skip(Req2) + {_, _, Req2} -> multipart_skip(Req2) end. %% Response API. %% @doc Add a cookie header to the response. -spec set_resp_cookie(binary(), binary(), - [cowboy_cookies:cookie_option()], Req) -> {ok, Req} when Req::req(). + [cowboy_cookies:cookie_option()], Req) -> Req when Req::req(). set_resp_cookie(Name, Value, Options, Req) -> {HeaderName, HeaderValue} = cowboy_cookies:cookie(Name, Value, Options), set_resp_header(HeaderName, HeaderValue, Req). %% @doc Add a header to the response. -spec set_resp_header(cowboy_http:header(), iodata(), Req) - -> {ok, Req} when Req::req(). + -> Req when Req::req(). set_resp_header(Name, Value, Req=#http_req{resp_headers=RespHeaders}) -> NameBin = header_to_binary(Name), - {ok, Req#http_req{resp_headers=[{NameBin, Value}|RespHeaders]}}. + Req#http_req{resp_headers=[{NameBin, Value}|RespHeaders]}. %% @doc Add a body to the response. %% %% The body set here is ignored if the response is later sent using %% anything other than reply/2 or reply/3. The response body is expected %% to be a binary or an iolist. --spec set_resp_body(iodata(), Req) -> {ok, Req} when Req::req(). +-spec set_resp_body(iodata(), Req) -> Req when Req::req(). set_resp_body(Body, Req) -> - {ok, Req#http_req{resp_body=Body}}. + Req#http_req{resp_body=Body}. %% @doc Add a body function to the response. %% @@ -740,9 +759,9 @@ set_resp_body(Body, Req) -> %% %% @see cowboy_req:transport/1. -spec set_resp_body_fun(non_neg_integer(), - fun(() -> {sent, non_neg_integer()}), Req) -> {ok, Req} when Req::req(). + fun(() -> {sent, non_neg_integer()}), Req) -> Req when Req::req(). set_resp_body_fun(StreamLen, StreamFun, Req) -> - {ok, Req#http_req{resp_body={StreamLen, StreamFun}}}. + Req#http_req{resp_body={StreamLen, StreamFun}}. %% @doc Return whether the given header has been set for the response. -spec has_resp_header(cowboy_http:header(), req()) -> boolean(). diff --git a/src/cowboy_rest.erl b/src/cowboy_rest.erl index d2aa127..a6c3672 100644 --- a/src/cowboy_rest.erl +++ b/src/cowboy_rest.erl @@ -126,7 +126,7 @@ allowed_methods(Req, State=#state{method=Method}) -> end. method_not_allowed(Req, State, Methods) -> - {ok, Req2} = cowboy_req:set_resp_header( + Req2 = cowboy_req:set_resp_header( <<"Allow">>, method_not_allowed_build(Methods, []), Req), respond(Req2, State, 405). @@ -153,7 +153,7 @@ is_authorized(Req, State) -> {true, Req2, HandlerState} -> forbidden(Req2, State#state{handler_state=HandlerState}); {{false, AuthHead}, Req2, HandlerState} -> - {ok, Req3} = cowboy_req:set_resp_header( + Req3 = cowboy_req:set_resp_header( <<"Www-Authenticate">>, AuthHead, Req2), respond(Req3, State#state{handler_state=HandlerState}, 401) end. @@ -211,7 +211,7 @@ content_types_provided(Req, State) -> CTP2 = [normalize_content_types(P) || P <- CTP], State2 = State#state{ handler_state=HandlerState, content_types_p=CTP2}, - {Accept, Req3} = cowboy_req:parse_header('Accept', Req2), + {ok, Accept, Req3} = cowboy_req:parse_header('Accept', Req2), case Accept of undefined -> {PMT, _Fun} = HeadCTP = hd(CTP2), @@ -305,7 +305,7 @@ languages_provided(Req, State) -> not_acceptable(Req2, State#state{handler_state=HandlerState}); {LP, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState, languages_p=LP}, - {AcceptLanguage, Req3} = + {ok, AcceptLanguage, Req3} = cowboy_req:parse_header('Accept-Language', Req2), case AcceptLanguage of undefined -> @@ -352,8 +352,7 @@ match_language(Req, State, Accept, [Provided|Tail], end. set_language(Req, State=#state{language_a=Language}) -> - {ok, Req2} = cowboy_req:set_resp_header( - <<"Content-Language">>, Language, Req), + Req2 = cowboy_req:set_resp_header(<<"Content-Language">>, Language, Req), charsets_provided(cowboy_req:set_meta(language, Language, Req2), State). %% charsets_provided should return a list of binary values indicating @@ -368,7 +367,7 @@ charsets_provided(Req, State) -> not_acceptable(Req2, State#state{handler_state=HandlerState}); {CP, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState, charsets_p=CP}, - {AcceptCharset, Req3} = + {ok, AcceptCharset, Req3} = cowboy_req:parse_header('Accept-Charset', Req2), case AcceptCharset of undefined -> @@ -417,8 +416,7 @@ set_content_type(Req, State=#state{ undefined -> ContentType; Charset -> [ContentType, <<"; charset=">>, Charset] end, - {ok, Req2} = cowboy_req:set_resp_header( - <<"Content-Type">>, ContentType2, Req), + Req2 = cowboy_req:set_resp_header(<<"Content-Type">>, ContentType2, Req), encodings_provided(cowboy_req:set_meta(charset, Charset, Req2), State). set_content_type_build_params([], []) -> @@ -472,7 +470,7 @@ variances(Req, State=#state{content_types_p=CTP, [] -> resource_exists(Req3, State2); [[<<", ">>, H]|Variances5] -> - {ok, Req4} = cowboy_req:set_resp_header( + Req4 = cowboy_req:set_resp_header( <<"Variances">>, [H|Variances5], Req3), resource_exists(Req4, State2) end. @@ -483,11 +481,11 @@ resource_exists(Req, State) -> if_match_exists(Req, State) -> case cowboy_req:parse_header('If-Match', Req) of - {undefined, Req2} -> + {ok, undefined, Req2} -> if_unmodified_since_exists(Req2, State); - {'*', Req2} -> + {ok, '*', Req2} -> if_unmodified_since_exists(Req2, State); - {ETagsList, Req2} -> + {ok, ETagsList, Req2} -> if_match(Req2, State, ETagsList) end. @@ -507,12 +505,12 @@ if_match_musnt_exist(Req, State) -> if_unmodified_since_exists(Req, State) -> case cowboy_req:parse_header('If-Unmodified-Since', Req) of - {undefined, Req2} -> + {ok, undefined, Req2} -> if_none_match_exists(Req2, State); - {{error, badarg}, Req2} -> - if_none_match_exists(Req2, State); - {IfUnmodifiedSince, Req2} -> - if_unmodified_since(Req2, State, IfUnmodifiedSince) + {ok, IfUnmodifiedSince, Req2} -> + if_unmodified_since(Req2, State, IfUnmodifiedSince); + {error, badarg} -> + if_none_match_exists(Req, State) end. %% If LastModified is the atom 'no_call', we continue. @@ -525,11 +523,11 @@ if_unmodified_since(Req, State, IfUnmodifiedSince) -> if_none_match_exists(Req, State) -> case cowboy_req:parse_header('If-None-Match', Req) of - {undefined, Req2} -> + {ok, undefined, Req2} -> if_modified_since_exists(Req2, State); - {'*', Req2} -> + {ok, '*', Req2} -> precondition_is_head_get(Req2, State); - {EtagsList, Req2} -> + {ok, EtagsList, Req2} -> if_none_match(Req2, State, EtagsList) end. @@ -553,12 +551,12 @@ precondition_is_head_get(Req, State) -> if_modified_since_exists(Req, State) -> case cowboy_req:parse_header('If-Modified-Since', Req) of - {undefined, Req2} -> - method(Req2, State); - {{error, badarg}, Req2} -> + {ok, undefined, Req2} -> method(Req2, State); - {IfModifiedSince, Req2} -> - if_modified_since_now(Req2, State, IfModifiedSince) + {ok, IfModifiedSince, Req2} -> + if_modified_since_now(Req2, State, IfModifiedSince); + {error, badarg} -> + method(Req, State) end. if_modified_since_now(Req, State, IfModifiedSince) -> @@ -598,7 +596,7 @@ is_put_to_missing_resource(Req, State) -> moved_permanently(Req, State, OnFalse) -> case call(Req, State, moved_permanently) of {{true, Location}, Req2, HandlerState} -> - {ok, Req3} = cowboy_req:set_resp_header( + Req3 = cowboy_req:set_resp_header( <<"Location">>, Location, Req2), respond(Req3, State#state{handler_state=HandlerState}, 301); {false, Req2, HandlerState} -> @@ -619,7 +617,7 @@ previously_existed(Req, State) -> moved_temporarily(Req, State) -> case call(Req, State, moved_temporarily) of {{true, Location}, Req2, HandlerState} -> - {ok, Req3} = cowboy_req:set_resp_header( + Req3 = cowboy_req:set_resp_header( <<"Location">>, Location, Req2), respond(Req3, State#state{handler_state=HandlerState}, 307); {false, Req2, HandlerState} -> @@ -672,7 +670,7 @@ create_path(Req, State) -> {Path, Req2, HandlerState} -> {HostURL, Req3} = cowboy_req:host_url(Req2), State2 = State#state{handler_state=HandlerState}, - {ok, Req4} = cowboy_req:set_resp_header( + Req4 = cowboy_req:set_resp_header( <<"Location">>, << HostURL/binary, Path/binary >>, Req3), put_resource(cowboy_req:set_meta(put_path, Path, Req4), State2, 303) @@ -716,7 +714,7 @@ put_resource(Req, State, OnTrue) -> {CTA, Req2, HandlerState} -> CTA2 = [normalize_content_types(P) || P <- CTA], State2 = State#state{handler_state=HandlerState}, - {ContentType, Req3} + {ok, ContentType, Req3} = cowboy_req:parse_header('Content-Type', Req2), choose_content_type(Req3, State2, OnTrue, ContentType, CTA2) end. @@ -768,7 +766,7 @@ set_resp_body(Req, State=#state{content_type_a={_Type, Fun}}) -> Req4 = Req3; LastModified -> LastModifiedStr = httpd_util:rfc1123_date(LastModified), - {ok, Req4} = cowboy_req:set_resp_header( + Req4 = cowboy_req:set_resp_header( <<"Last-Modified">>, LastModifiedStr, Req3) end, {Req5, State4} = set_resp_expires(Req4, State3), @@ -777,7 +775,7 @@ set_resp_body(Req, State=#state{content_type_a={_Type, Fun}}) -> terminate(Req6, State4#state{handler_state=HandlerState}); {Body, Req6, HandlerState} -> State5 = State4#state{handler_state=HandlerState}, - {ok, Req7} = case Body of + Req7 = case Body of {stream, Len, Fun1} -> cowboy_req:set_resp_body_fun(Len, Fun1, Req6); _Contents -> @@ -797,7 +795,7 @@ set_resp_etag(Req, State) -> undefined -> {Req2, State2}; Etag -> - {ok, Req3} = cowboy_req:set_resp_header( + Req3 = cowboy_req:set_resp_header( <<"ETag">>, encode_etag(Etag), Req2), {Req3, State2} end. @@ -813,7 +811,7 @@ set_resp_expires(Req, State) -> {Req2, State2}; Expires -> ExpiresStr = httpd_util:rfc1123_date(Expires), - {ok, Req3} = cowboy_req:set_resp_header( + Req3 = cowboy_req:set_resp_header( <<"Expires">>, ExpiresStr, Req2), {Req3, State2} end. diff --git a/src/cowboy_websocket.erl b/src/cowboy_websocket.erl index 7382344..a6f2be3 100644 --- a/src/cowboy_websocket.erl +++ b/src/cowboy_websocket.erl @@ -71,11 +71,11 @@ upgrade(ListenerPid, Handler, Opts, Req) -> -spec websocket_upgrade(#state{}, Req) -> {ok, #state{}, Req} when Req::cowboy_req:req(). websocket_upgrade(State, Req) -> - {ConnTokens, Req2} + {ok, ConnTokens, Req2} = cowboy_req:parse_header('Connection', Req), true = lists:member(<<"upgrade">>, ConnTokens), %% @todo Should probably send a 426 if the Upgrade header is missing. - {[<<"websocket">>], Req3} = cowboy_req:parse_header('Upgrade', Req2), + {ok, [<<"websocket">>], Req3} = cowboy_req:parse_header('Upgrade', Req2), {Version, Req4} = cowboy_req:header(<<"Sec-Websocket-Version">>, Req3), websocket_upgrade(Version, State, Req4). diff --git a/test/http_SUITE.erl b/test/http_SUITE.erl index 6bed436..1140cf9 100644 --- a/test/http_SUITE.erl +++ b/test/http_SUITE.erl @@ -599,9 +599,7 @@ onrequest_reply(Config) -> onrequest_hook(Req) -> case cowboy_req:qs_val(<<"reply">>, Req) of {undefined, Req2} -> - {ok, Req3} = cowboy_req:set_resp_header( - 'Server', <<"Serenity">>, Req2), - Req3; + cowboy_req:set_resp_header('Server', <<"Serenity">>, Req2); {_, Req2} -> {ok, Req3} = cowboy_req:reply( 200, [], <<"replied!">>, Req2), diff --git a/test/http_handler_multipart.erl b/test/http_handler_multipart.erl index ad5d27e..850574f 100644 --- a/test/http_handler_multipart.erl +++ b/test/http_handler_multipart.erl @@ -8,22 +8,22 @@ init({_Transport, http}, Req, []) -> {ok, Req, {}}. handle(Req, State) -> - {Result, Req2} = acc_multipart(Req, []), + {Result, Req2} = acc_multipart(Req), {ok, Req3} = cowboy_req:reply(200, [], term_to_binary(Result), Req2), {ok, Req3, State}. terminate(_Req, _State) -> ok. -acc_multipart(Req, Acc) -> - {Result, Req2} = cowboy_req:multipart_data(Req), - acc_multipart(Req2, Acc, Result). +acc_multipart(Req) -> + acc_multipart(cowboy_req:multipart_data(Req), []). -acc_multipart(Req, Acc, {headers, Headers}) -> - acc_multipart(Req, [{Headers, []}|Acc]); -acc_multipart(Req, [{Headers, BodyAcc}|Acc], {body, Data}) -> - acc_multipart(Req, [{Headers, [Data|BodyAcc]}|Acc]); -acc_multipart(Req, [{Headers, BodyAcc}|Acc], end_of_part) -> - acc_multipart(Req, [{Headers, list_to_binary(lists:reverse(BodyAcc))}|Acc]); -acc_multipart(Req, Acc, eof) -> +acc_multipart({headers, Headers, Req}, Acc) -> + acc_multipart(cowboy_req:multipart_data(Req), [{Headers, []}|Acc]); +acc_multipart({body, Data, Req}, [{Headers, BodyAcc}|Acc]) -> + acc_multipart(cowboy_req:multipart_data(Req), [{Headers, [Data|BodyAcc]}|Acc]); +acc_multipart({end_of_part, Req}, [{Headers, BodyAcc}|Acc]) -> + acc_multipart(cowboy_req:multipart_data(Req), + [{Headers, list_to_binary(lists:reverse(BodyAcc))}|Acc]); +acc_multipart({eof, Req}, Acc) -> {lists:reverse(Acc), Req}. diff --git a/test/http_handler_set_resp.erl b/test/http_handler_set_resp.erl index db22168..806bca8 100644 --- a/test/http_handler_set_resp.erl +++ b/test/http_handler_set_resp.erl @@ -7,14 +7,12 @@ init({_Transport, http}, Req, Opts) -> Headers = proplists:get_value(headers, Opts, []), Body = proplists:get_value(body, Opts, <<"http_handler_set_resp">>), - {ok, Req2} = lists:foldl(fun({Name, Value}, {ok, R}) -> + Req2 = lists:foldl(fun({Name, Value}, R) -> cowboy_req:set_resp_header(Name, Value, R) - end, {ok, Req}, Headers), - {ok, Req3} = cowboy_req:set_resp_body(Body, Req2), - {ok, Req4} = cowboy_req:set_resp_header( - <<"X-Cowboy-Test">>, <<"ok">>, Req3), - {ok, Req5} = cowboy_req:set_resp_cookie( - <<"cake">>, <<"lie">>, [], Req4), + end, Req, Headers), + Req3 = cowboy_req:set_resp_body(Body, Req2), + Req4 = cowboy_req:set_resp_header(<<"X-Cowboy-Test">>, <<"ok">>, Req3), + Req5 = cowboy_req:set_resp_cookie(<<"cake">>, <<"lie">>, [], Req4), {ok, Req5, undefined}. handle(Req, State) -> diff --git a/test/http_handler_stream_body.erl b/test/http_handler_stream_body.erl index 13221eb..feb4f78 100644 --- a/test/http_handler_stream_body.erl +++ b/test/http_handler_stream_body.erl @@ -16,7 +16,7 @@ handle(Req, State=#state{headers=_Headers, body=Body, reply=set_resp}) -> {ok, Transport, Socket} = cowboy_req:transport(Req), SFun = fun() -> Transport:send(Socket, Body), sent end, SLen = iolist_size(Body), - {ok, Req2} = cowboy_req:set_resp_body_fun(SLen, SFun, Req), + Req2 = cowboy_req:set_resp_body_fun(SLen, SFun, Req), {ok, Req3} = cowboy_req:reply(200, Req2), {ok, Req3, State}. -- cgit v1.2.3