aboutsummaryrefslogtreecommitdiffstats
path: root/src/cowboy_http_req.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/cowboy_http_req.erl')
-rw-r--r--src/cowboy_http_req.erl79
1 files changed, 47 insertions, 32 deletions
diff --git a/src/cowboy_http_req.erl b/src/cowboy_http_req.erl
index 539c7f0..3a3dd2f 100644
--- a/src/cowboy_http_req.erl
+++ b/src/cowboy_http_req.erl
@@ -191,47 +191,62 @@ headers(Req) ->
%% returned is used as a return value.
%% @see parse_header/3
-spec parse_header(http_header(), #http_req{})
- -> {tokens, [binary()], #http_req{}}
- | {undefined, binary(), #http_req{}}
- | {error, badarg}.
-parse_header('Connection', Req) ->
- parse_header('Connection', Req, []);
-parse_header(Name, Req) ->
- parse_header(Name, Req, undefined).
+ -> {any(), #http_req{}} | {error, badarg}.
+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}
+ end.
+
+%% @doc Default values for semantic header parsing.
+-spec parse_header_default(http_header()) -> any().
+parse_header_default('Accept') -> [];
+parse_header_default('Accept-Charset') -> [];
+parse_header_default('Accept-Encoding') -> [];
+parse_header_default('Connection') -> [];
+parse_header_default(_Name) -> undefined.
%% @doc Semantically parse headers.
%%
-%% When the header is known, a named tuple is returned containing
-%% {Type, P, Req} with Type being the type of value found in P.
-%% For example, the header 'Connection' is a list of tokens, therefore
-%% the value returned will be a list of binary values and Type will be
-%% 'tokens'.
-%%
-%% When the header is known but not found, the tuple {Type, Default, Req}
-%% is returned instead.
-%%
-%% When the header is unknown, the value is returned directly as an
-%% 'undefined' tagged tuple.
+%% When the header is unknown, the value is returned directly without parsing.
-spec parse_header(http_header(), #http_req{}, any())
- -> {tokens, [binary()], #http_req{}}
- | {undefined, binary(), #http_req{}}
- | {error, badarg}.
-parse_header(Name, Req=#http_req{p_headers=PHeaders}, Default)
- when Name =:= 'Connection' ->
+ -> {any(), #http_req{}} | {error, badarg}.
+parse_header(Name, Req, Default) when Name =:= 'Accept' ->
+ parse_header(Name, Req, Default,
+ fun (Value) ->
+ cowboy_http:list(Value, fun cowboy_http:media_range/2)
+ end);
+parse_header(Name, Req, Default) when Name =:= 'Accept-Charset' ->
+ parse_header(Name, Req, Default,
+ fun (Value) ->
+ cowboy_http:nonempty_list(Value, fun cowboy_http:charset/2)
+ end);
+parse_header(Name, Req, Default) when Name =:= 'Accept-Encoding' ->
+ parse_header(Name, Req, Default,
+ fun (Value) ->
+ cowboy_http:list(Value, fun cowboy_http:token_ci/2)
+ end);
+parse_header(Name, Req, Default) when Name =:= 'Connection' ->
+ parse_header(Name, Req, Default,
+ fun (Value) ->
+ cowboy_http:nonempty_list(Value, fun cowboy_http:token_ci/2)
+ end);
+parse_header(Name, Req, Default) ->
+ {Value, Req2} = header(Name, Req, Default),
+ {undefined, Value, Req2}.
+
+parse_header(Name, Req=#http_req{p_headers=PHeaders}, Default, Fun) ->
case header(Name, Req) of
- {undefined, Req2} -> {tokens, Default, Req2};
+ {undefined, Req2} ->
+ {Default, Req2#http_req{p_headers=[{Name, Default}|PHeaders]}};
{Value, Req2} ->
- case cowboy_http:nonempty_list(Value, fun cowboy_http:token_ci/2) of
+ case Fun(Value) of
{error, badarg} ->
{error, badarg};
P ->
- {tokens, P, Req2#http_req{
- p_headers=[{Name, P}|PHeaders]}}
+ {P, Req2#http_req{p_headers=[{Name, P}|PHeaders]}}
end
- end;
-parse_header(Name, Req, Default) ->
- {Value, Req2} = header(Name, Req, Default),
- {undefined, Value, Req2}.
+ end.
%% @equiv cookie(Name, Req, undefined)
-spec cookie(binary(), #http_req{})
@@ -368,7 +383,7 @@ chunked_reply(Status, Headers, Req=#http_req{socket=Socket, transport=Transport,
%% @doc Send a chunk of data.
%%
%% A chunked reply must have been initiated before calling this function.
--spec chunk(iodata(), #http_req{}) -> ok.
+-spec chunk(iodata(), #http_req{}) -> ok | {error, atom()}.
chunk(_Data, #http_req{socket=_Socket, transport=_Transport, method='HEAD'}) ->
ok;
chunk(Data, #http_req{socket=Socket, transport=Transport, resp_state=chunks}) ->