aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/inets/src/http_client/httpc_request.erl67
-rw-r--r--lib/inets/test/httpc_SUITE.erl29
2 files changed, 61 insertions, 35 deletions
diff --git a/lib/inets/src/http_client/httpc_request.erl b/lib/inets/src/http_client/httpc_request.erl
index 89872a3831..641b6559de 100644
--- a/lib/inets/src/http_client/httpc_request.erl
+++ b/lib/inets/src/http_client/httpc_request.erl
@@ -190,35 +190,11 @@ is_client_closing(Headers) ->
%%%========================================================================
post_data(Method, Headers, {ContentType, Body}, HeadersAsIs)
when (Method =:= post)
- orelse (Method =:= put)
- orelse (Method =:= patch)
- orelse (Method =:= delete) ->
-
- NewBody = case Headers#http_request_h.expect of
- "100-continue" ->
- "";
- _ ->
- Body
- end,
-
- NewHeaders = case HeadersAsIs of
- [] ->
- Headers#http_request_h{
- 'content-type' = ContentType,
- 'content-length' = case body_length(Body) of
- undefined ->
- % on upload streaming the caller must give a
- % value to the Content-Length header
- % (or use chunked Transfer-Encoding)
- Headers#http_request_h.'content-length';
- Len when is_list(Len) ->
- Len
- end
- };
- _ ->
- HeadersAsIs
- end,
-
+ orelse (Method =:= put)
+ orelse (Method =:= patch)
+ orelse (Method =:= delete) ->
+ NewBody = update_body(Headers, Body),
+ NewHeaders = update_headers(Headers, ContentType, Body, HeadersAsIs),
{NewHeaders, NewBody};
post_data(_, Headers, _, []) ->
@@ -226,14 +202,39 @@ post_data(_, Headers, _, []) ->
post_data(_, _, _, HeadersAsIs = [_|_]) ->
{HeadersAsIs, ""}.
+update_body(Headers, Body) ->
+ case Headers#http_request_h.expect of
+ "100-continue" ->
+ "";
+ _ ->
+ Body
+ end.
+
+update_headers(Headers, ContentType, Body, []) ->
+ case Body of
+ [] ->
+ Headers#http_request_h{'content-length' = "0"};
+ <<>> ->
+ Headers#http_request_h{'content-length' = "0"};
+ {Fun, _Acc} when is_function(Fun, 1) ->
+ %% A client MUST NOT generate a 100-continue expectation in a request
+ %% that does not include a message body. This implies that either the
+ %% Content-Length or the Transfer-Encoding header MUST be present.
+ %% DO NOT send content-type when Body is empty.
+ Headers#http_request_h{'content-type' = ContentType};
+ _ ->
+ Headers#http_request_h{
+ 'content-length' = body_length(Body),
+ 'content-type' = ContentType}
+ end;
+update_headers(_, _, _, HeadersAsIs) ->
+ HeadersAsIs.
+
body_length(Body) when is_binary(Body) ->
integer_to_list(size(Body));
body_length(Body) when is_list(Body) ->
- integer_to_list(length(Body));
-
-body_length({DataFun, _Acc}) when is_function(DataFun, 1) ->
- undefined.
+ integer_to_list(length(Body)).
method(Method) ->
http_util:to_upper(atom_to_list(Method)).
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 1116fdb1b6..cd14476f9d 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -151,6 +151,7 @@ only_simulated() ->
relaxed,
multipart_chunks,
get_space,
+ delete_no_body,
stream_fun_server_close
].
@@ -1375,7 +1376,16 @@ unix_domain_socket(Config) when is_list(Config) ->
= httpc:request(put, {URL, [], [], ""}, [], []),
{ok, {{_,200,_}, [_ | _], _}}
= httpc:request(get, {URL, []}, [], []).
-
+%%-------------------------------------------------------------------------
+delete_no_body(doc) ->
+ ["Test that a DELETE request without Body does not send a Content-Type header - Solves ERL-536"];
+delete_no_body(Config) when is_list(Config) ->
+ URL = url(group_name(Config), "/delete_no_body.html", Config),
+ %% Simulated server replies 500 if 'Content-Type' header is present
+ {ok, {{_,200,_}, _, _}} =
+ httpc:request(delete, {URL, []}, [], []),
+ {ok, {{_,500,_}, _, _}} =
+ httpc:request(delete, {URL, [], "text/plain", "TEST"}, [], []).
%%--------------------------------------------------------------------
@@ -1882,6 +1892,13 @@ auth_header([{"authorization", Value} | _]) ->
auth_header([_ | Tail]) ->
auth_header(Tail).
+content_type_header([]) ->
+ not_found;
+content_type_header([{"content-type", Value}|_]) ->
+ {ok, string:strip(Value)};
+content_type_header([_|T]) ->
+ content_type_header(T).
+
handle_auth("Basic " ++ UserInfo, Challange, DefaultResponse) ->
case string:tokens(base64:decode_to_string(UserInfo), ":") of
["alladin", "sesame"] = Auth ->
@@ -2312,7 +2329,15 @@ handle_uri(_,"/http_1_1_send_oct_and_connection_close.html",_,_,Socket,_) ->
"X-Socket-Stat-Send-Oct: " ++ integer_to_list(get_stat(Socket, send_oct)) ++ "\r\n" ++
"Connection: close\r\n" ++
"\r\n";
-
+handle_uri(_,"/delete_no_body.html", _,Headers,_, DefaultResponse) ->
+ Error = "HTTP/1.1 500 Internal Server Error\r\n" ++
+ "Content-Length:0\r\n\r\n",
+ case content_type_header(Headers) of
+ {ok, _} ->
+ Error;
+ not_found ->
+ DefaultResponse
+ end;
handle_uri(_,_,_,_,_,DefaultResponse) ->
DefaultResponse.