aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2018-12-31 17:08:59 +0100
committerLoïc Hoguin <[email protected]>2018-12-31 17:08:59 +0100
commit630bd475e6aa4b9fdde01272236d08305034cb48 (patch)
tree096c732caef432e2dd56fbd4d50a2d949428f5c0 /src
parent32779615616fe3ae052eef94d838ecc9180045a7 (diff)
downloadgun-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.erl69
-rw-r--r--src/gun_http.erl9
-rw-r--r--src/gun_http2.erl11
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]}.