diff options
author | Loïc Hoguin <[email protected]> | 2018-12-31 17:08:59 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2018-12-31 17:08:59 +0100 |
commit | 630bd475e6aa4b9fdde01272236d08305034cb48 (patch) | |
tree | 096c732caef432e2dd56fbd4d50a2d949428f5c0 /src | |
parent | 32779615616fe3ae052eef94d838ecc9180045a7 (diff) | |
download | gun-630bd475e6aa4b9fdde01272236d08305034cb48.tar.gz gun-630bd475e6aa4b9fdde01272236d08305034cb48.tar.bz2 gun-630bd475e6aa4b9fdde01272236d08305034cb48.zip |
Separate request/4,5,6 into headers/4,5 and request/5,6
This cleaner separation gets rid of the implicit body check
that was causing issues for many users. Now the body is
either given explicitly or it is expected via future
gun:data/3 calls.
Diffstat (limited to 'src')
-rw-r--r-- | src/gun.erl | 69 | ||||
-rw-r--r-- | src/gun_http.erl | 9 | ||||
-rw-r--r-- | src/gun_http2.erl | 11 |
3 files changed, 51 insertions, 38 deletions
diff --git a/src/gun.erl b/src/gun.erl index 1e83979..10ae2a7 100644 --- a/src/gun.erl +++ b/src/gun.erl @@ -49,7 +49,10 @@ -export([put/3]). -export([put/4]). -export([put/5]). --export([request/4]). + +%% Generic requests interface. +-export([headers/4]). +-export([headers/5]). -export([request/5]). -export([request/6]). @@ -316,11 +319,11 @@ shutdown(ServerPid) -> -spec delete(pid(), iodata()) -> reference(). delete(ServerPid, Path) -> - request(ServerPid, <<"DELETE">>, Path, []). + request(ServerPid, <<"DELETE">>, Path, [], <<>>). -spec delete(pid(), iodata(), headers()) -> reference(). delete(ServerPid, Path, Headers) -> - request(ServerPid, <<"DELETE">>, Path, Headers). + request(ServerPid, <<"DELETE">>, Path, Headers, <<>>). -spec delete(pid(), iodata(), headers(), req_opts()) -> reference(). delete(ServerPid, Path, Headers, ReqOpts) -> @@ -328,11 +331,11 @@ delete(ServerPid, Path, Headers, ReqOpts) -> -spec get(pid(), iodata()) -> reference(). get(ServerPid, Path) -> - request(ServerPid, <<"GET">>, Path, []). + request(ServerPid, <<"GET">>, Path, [], <<>>). -spec get(pid(), iodata(), headers()) -> reference(). get(ServerPid, Path, Headers) -> - request(ServerPid, <<"GET">>, Path, Headers). + request(ServerPid, <<"GET">>, Path, Headers, <<>>). -spec get(pid(), iodata(), headers(), req_opts()) -> reference(). get(ServerPid, Path, Headers, ReqOpts) -> @@ -340,11 +343,11 @@ get(ServerPid, Path, Headers, ReqOpts) -> -spec head(pid(), iodata()) -> reference(). head(ServerPid, Path) -> - request(ServerPid, <<"HEAD">>, Path, []). + request(ServerPid, <<"HEAD">>, Path, [], <<>>). -spec head(pid(), iodata(), headers()) -> reference(). head(ServerPid, Path, Headers) -> - request(ServerPid, <<"HEAD">>, Path, Headers). + request(ServerPid, <<"HEAD">>, Path, Headers, <<>>). -spec head(pid(), iodata(), headers(), req_opts()) -> reference(). head(ServerPid, Path, Headers, ReqOpts) -> @@ -352,11 +355,11 @@ head(ServerPid, Path, Headers, ReqOpts) -> -spec options(pid(), iodata()) -> reference(). options(ServerPid, Path) -> - request(ServerPid, <<"OPTIONS">>, Path, []). + request(ServerPid, <<"OPTIONS">>, Path, [], <<>>). -spec options(pid(), iodata(), headers()) -> reference(). options(ServerPid, Path, Headers) -> - request(ServerPid, <<"OPTIONS">>, Path, Headers). + request(ServerPid, <<"OPTIONS">>, Path, Headers, <<>>). -spec options(pid(), iodata(), headers(), req_opts()) -> reference(). options(ServerPid, Path, Headers, ReqOpts) -> @@ -364,9 +367,11 @@ options(ServerPid, Path, Headers, ReqOpts) -> -spec patch(pid(), iodata(), headers()) -> reference(). patch(ServerPid, Path, Headers) -> - request(ServerPid, <<"PATCH">>, Path, Headers). + headers(ServerPid, <<"PATCH">>, Path, Headers). --spec patch(pid(), iodata(), headers(), iodata()) -> reference(). +-spec patch(pid(), iodata(), headers(), iodata() | req_opts()) -> reference(). +patch(ServerPid, Path, Headers, ReqOpts) when is_map(ReqOpts) -> + headers(ServerPid, <<"PATCH">>, Path, Headers, ReqOpts); patch(ServerPid, Path, Headers, Body) -> request(ServerPid, <<"PATCH">>, Path, Headers, Body). @@ -376,9 +381,11 @@ patch(ServerPid, Path, Headers, Body, ReqOpts) -> -spec post(pid(), iodata(), headers()) -> reference(). post(ServerPid, Path, Headers) -> - request(ServerPid, <<"POST">>, Path, Headers). + headers(ServerPid, <<"POST">>, Path, Headers). --spec post(pid(), iodata(), headers(), iodata()) -> reference(). +-spec post(pid(), iodata(), headers(), iodata() | req_opts()) -> reference(). +post(ServerPid, Path, Headers, ReqOpts) when is_map(ReqOpts) -> + headers(ServerPid, <<"POST">>, Path, Headers, ReqOpts); post(ServerPid, Path, Headers, Body) -> request(ServerPid, <<"POST">>, Path, Headers, Body). @@ -388,9 +395,11 @@ post(ServerPid, Path, Headers, Body, ReqOpts) -> -spec put(pid(), iodata(), headers()) -> reference(). put(ServerPid, Path, Headers) -> - request(ServerPid, <<"PUT">>, Path, Headers). + headers(ServerPid, <<"PUT">>, Path, Headers). --spec put(pid(), iodata(), headers(), iodata()) -> reference(). +-spec put(pid(), iodata(), headers(), iodata() | req_opts()) -> reference(). +put(ServerPid, Path, Headers, ReqOpts) when is_map(ReqOpts) -> + headers(ServerPid, <<"PUT">>, Path, Headers, ReqOpts); put(ServerPid, Path, Headers, Body) -> request(ServerPid, <<"PUT">>, Path, Headers, Body). @@ -398,9 +407,19 @@ put(ServerPid, Path, Headers, Body) -> put(ServerPid, Path, Headers, Body, ReqOpts) -> request(ServerPid, <<"PUT">>, Path, Headers, Body, ReqOpts). --spec request(pid(), iodata(), iodata(), headers()) -> reference(). -request(ServerPid, Method, Path, Headers) -> - request(ServerPid, Method, Path, Headers, <<>>, #{}). +%% Generic requests interface. + +-spec headers(pid(), iodata(), iodata(), headers()) -> reference(). +headers(ServerPid, Method, Path, Headers) -> + headers(ServerPid, Method, Path, Headers, #{}). + +%% @todo Accept header names as maps. +-spec headers(pid(), iodata(), iodata(), headers(), req_opts()) -> reference(). +headers(ServerPid, Method, Path, Headers, ReqOpts) -> + StreamRef = make_ref(), + ReplyTo = maps:get(reply_to, ReqOpts, self()), + gen_statem:cast(ServerPid, {headers, ReplyTo, StreamRef, Method, Path, Headers}), + StreamRef. -spec request(pid(), iodata(), iodata(), headers(), iodata()) -> reference(). request(ServerPid, Method, Path, Headers, Body) -> @@ -729,15 +748,17 @@ connected(info, keepalive, State=#state{protocol=Protocol, protocol_state=ProtoS ProtoState2 = Protocol:keepalive(ProtoState), {keep_state, keepalive_timeout(State#state{protocol_state=ProtoState2})}; %% Public HTTP interface. +connected(cast, {headers, ReplyTo, StreamRef, Method, Path, Headers}, + State=#state{origin_host=Host, origin_port=Port, + protocol=Protocol, protocol_state=ProtoState}) -> + ProtoState2 = Protocol:headers(ProtoState, + StreamRef, ReplyTo, Method, Host, Port, Path, Headers), + {keep_state, State#state{protocol_state=ProtoState2}}; connected(cast, {request, ReplyTo, StreamRef, Method, Path, Headers, Body}, State=#state{origin_host=Host, origin_port=Port, protocol=Protocol, protocol_state=ProtoState}) -> - ProtoState2 = case Body of - <<>> -> Protocol:request(ProtoState, - StreamRef, ReplyTo, Method, Host, Port, Path, Headers); - _ -> Protocol:request(ProtoState, - StreamRef, ReplyTo, Method, Host, Port, Path, Headers, Body) - end, + ProtoState2 = Protocol:request(ProtoState, + StreamRef, ReplyTo, Method, Host, Port, Path, Headers, Body), {keep_state, State#state{protocol_state=ProtoState2}}; %% @todo Do we want to reject ReplyTo if it's not the process %% who initiated the connection? For both data and cancel. diff --git a/src/gun_http.erl b/src/gun_http.erl index 57f72c7..5229a6d 100644 --- a/src/gun_http.erl +++ b/src/gun_http.erl @@ -20,7 +20,7 @@ -export([handle/2]). -export([close/2]). -export([keepalive/1]). --export([request/8]). +-export([headers/8]). -export([request/9]). -export([data/5]). -export([connect/5]). @@ -330,7 +330,7 @@ keepalive(State=#http_state{socket=Socket, transport=Transport, out=head}) -> keepalive(State) -> State. -request(State=#http_state{socket=Socket, transport=Transport, version=Version, +headers(State=#http_state{socket=Socket, transport=Transport, version=Version, out=head}, StreamRef, ReplyTo, Method, Host, Port, Path, Headers) -> Host2 = case Host of {local, _SocketPath} -> <<>>; @@ -509,10 +509,7 @@ request_io_from_headers(Headers) -> {_, Length} -> {body, cow_http_hd:parse_content_length(Length)}; _ -> - case lists:keymember(<<"content-type">>, 1, Headers) of - true -> body_chunked; - false -> head - end + body_chunked end. response_io_from_headers(<<"HEAD">>, _, _, _) -> diff --git a/src/gun_http2.erl b/src/gun_http2.erl index 6538083..f5cf834 100644 --- a/src/gun_http2.erl +++ b/src/gun_http2.erl @@ -20,7 +20,7 @@ -export([handle/2]). -export([close/2]). -export([keepalive/1]). --export([request/8]). +-export([headers/8]). -export([request/9]). -export([data/5]). -export([cancel/3]). @@ -240,19 +240,14 @@ keepalive(State=#http2_state{socket=Socket, transport=Transport}) -> Transport:send(Socket, cow_http2:ping(0)), State. -request(State=#http2_state{socket=Socket, transport=Transport, +headers(State=#http2_state{socket=Socket, transport=Transport, http2_machine=HTTP2Machine0, streams=Streams}, StreamRef, ReplyTo, Method, Host, Port, Path, Headers0) -> - IsFin0 = case (false =/= lists:keyfind(<<"content-type">>, 1, Headers0)) - orelse (false =/= lists:keyfind(<<"content-length">>, 1, Headers0)) of - true -> nofin; - false -> fin - end, {ok, StreamID, HTTP2Machine1} = cow_http2_machine:init_stream( iolist_to_binary(Method), HTTP2Machine0), {ok, PseudoHeaders, Headers} = prepare_headers(State, Method, Host, Port, Path, Headers0), {ok, IsFin, HeaderBlock, HTTP2Machine} = cow_http2_machine:prepare_headers( - StreamID, HTTP2Machine1, IsFin0, PseudoHeaders, Headers), + StreamID, HTTP2Machine1, nofin, PseudoHeaders, Headers), Transport:send(Socket, cow_http2:headers(StreamID, IsFin, HeaderBlock)), Stream = #stream{id=StreamID, ref=StreamRef, reply_to=ReplyTo}, State#http2_state{http2_machine=HTTP2Machine, streams=[Stream|Streams]}. |