aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2011-10-06 12:40:04 +0200
committerLoïc Hoguin <[email protected]>2011-10-06 12:40:04 +0200
commit8e835bce9fc28f5ddfd3a0818d5ec0e776182b27 (patch)
tree06374f6e1c47ea9f85b2ed76c88e63c3fad2827d
parent237b468f42c57d603c6dfcd99c98aaeacec6ba92 (diff)
downloadcowboy-8e835bce9fc28f5ddfd3a0818d5ec0e776182b27.tar.gz
cowboy-8e835bce9fc28f5ddfd3a0818d5ec0e776182b27.tar.bz2
cowboy-8e835bce9fc28f5ddfd3a0818d5ec0e776182b27.zip
Close the connection when the application sends Connection: close
Now Cowboy checks headers sent to the client for the 'Connection' header value, parses it, and checks whether it contains a 'close' or 'keep-alive' value. It makes sure to close or keep the connection alive depending on the value found there, if any. Also change chunked replies to not close the connection by default unless the application requests it.
-rw-r--r--src/cowboy_http_req.erl30
-rw-r--r--test/http_SUITE.erl2
2 files changed, 27 insertions, 5 deletions
diff --git a/src/cowboy_http_req.erl b/src/cowboy_http_req.erl
index 66f2da4..a1a37bd 100644
--- a/src/cowboy_http_req.erl
+++ b/src/cowboy_http_req.erl
@@ -318,6 +318,7 @@ body_qs(Req) ->
reply(Code, Headers, Body, Req=#http_req{socket=Socket,
transport=Transport, connection=Connection,
method=Method, resp_state=waiting}) ->
+ RespConn = response_connection(Headers, Connection),
Head = response_head(Code, Headers, [
{<<"Connection">>, atom_to_connection(Connection)},
{<<"Content-Length">>,
@@ -329,22 +330,23 @@ reply(Code, Headers, Body, Req=#http_req{socket=Socket,
'HEAD' -> Transport:send(Socket, Head);
_ -> Transport:send(Socket, [Head, Body])
end,
- {ok, Req#http_req{resp_state=done}}.
+ {ok, Req#http_req{connection=RespConn, resp_state=done}}.
%% @doc Initiate the sending of a chunked reply to the client.
%% @see cowboy_http_req:chunk/2
-spec chunked_reply(http_status(), http_headers(), #http_req{})
-> {ok, #http_req{}}.
chunked_reply(Code, Headers, Req=#http_req{socket=Socket, transport=Transport,
- resp_state=waiting}) ->
+ connection=Connection, resp_state=waiting}) ->
+ RespConn = response_connection(Headers, Connection),
Head = response_head(Code, Headers, [
- {<<"Connection">>, <<"close">>},
+ {<<"Connection">>, atom_to_connection(Connection)},
{<<"Transfer-Encoding">>, <<"chunked">>},
{<<"Date">>, cowboy_clock:rfc1123()},
{<<"Server">>, <<"Cowboy">>}
]),
Transport:send(Socket, Head),
- {ok, Req#http_req{resp_state=chunks}}.
+ {ok, Req#http_req{connection=RespConn, resp_state=chunks}}.
%% @doc Send a chunk of data.
%%
@@ -381,6 +383,26 @@ parse_qs(Qs) ->
[Name, Value] -> {quoted:from_url(Name), quoted:from_url(Value)}
end || Token <- Tokens].
+-spec response_connection(http_headers(), keepalive | close)
+ -> keepalive | close.
+response_connection([], Connection) ->
+ Connection;
+response_connection([{Name, Value}|Tail], Connection) ->
+ case Name of
+ 'Connection' -> response_connection_parse(Value);
+ Name ->
+ Name2 = cowboy_bstr:to_lower(Name),
+ case Name2 of
+ <<"connection">> -> response_connection_parse(Value);
+ _Any -> response_connection(Tail, Connection)
+ end
+ end.
+
+-spec response_connection_parse(binary()) -> keepalive | close.
+response_connection_parse(ReplyConn) ->
+ Tokens = cowboy_http:parse_tokens_list(ReplyConn),
+ cowboy_http:connection_to_atom(Tokens).
+
-spec response_head(http_status(), http_headers(), http_headers()) -> iolist().
response_head(Code, Headers, DefaultHeaders) ->
StatusLine = <<"HTTP/1.1 ", (status(Code))/binary, "\r\n">>,
diff --git a/test/http_SUITE.erl b/test/http_SUITE.erl
index 8bfebaa..cb70ff3 100644
--- a/test/http_SUITE.erl
+++ b/test/http_SUITE.erl
@@ -117,7 +117,7 @@ headers_dupe(Config) ->
{ok, Data} = gen_tcp:recv(Socket, 0, 6000),
{_Start, _Length} = binary:match(Data, <<"Connection: close">>),
nomatch = binary:match(Data, <<"Connection: keep-alive">>),
- ok = gen_tcp:close(Socket).
+ {error, closed} = gen_tcp:recv(Socket, 0, 1000).
headers_huge(Config) ->
Cookie = lists:flatten(["whatever_man_biiiiiiiiiiiig_cookie_me_want_77="