diff options
author | Micael Karlberg <[email protected]> | 2011-03-07 14:52:30 +0100 |
---|---|---|
committer | Micael Karlberg <[email protected]> | 2011-03-07 14:52:30 +0100 |
commit | db29f9ede14ff5b8d747230fcad8ffa1b157f1e1 (patch) | |
tree | 0512f7a95f5425aa4afdb5dc8eddf2f303eae12b | |
parent | 546d0fd69519682e92b6493b6d092e4591ae5010 (diff) | |
download | otp-db29f9ede14ff5b8d747230fcad8ffa1b157f1e1.tar.gz otp-db29f9ede14ff5b8d747230fcad8ffa1b157f1e1.tar.bz2 otp-db29f9ede14ff5b8d747230fcad8ffa1b157f1e1.zip |
Adding missing "send loop" for raw sending.
Also fixed some of the documentation (types).
-rw-r--r-- | lib/inets/doc/src/httpc.xml | 52 | ||||
-rw-r--r-- | lib/inets/doc/src/notes.xml | 85 | ||||
-rw-r--r-- | lib/inets/src/http_client/httpc.erl | 85 | ||||
-rw-r--r-- | lib/inets/src/http_client/httpc_handler.erl | 18 | ||||
-rw-r--r-- | lib/inets/src/http_client/httpc_request.erl | 52 | ||||
-rw-r--r-- | lib/inets/test/httpc_SUITE.erl | 229 |
6 files changed, 269 insertions, 252 deletions
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml index 6dcf2d6d17..12f4fa535e 100644 --- a/lib/inets/doc/src/httpc.xml +++ b/lib/inets/doc/src/httpc.xml @@ -76,25 +76,29 @@ socket_opt() = See the Options used by gen_tcp(3) and <p>For more information about HTTP see rfc 2616</p> <code type="none"><![CDATA[ -method() = head | get | put | post | trace | options | delete -request() = {url(), headers()} | - {url(), headers(), content_type(), body()} -url() = string() - Syntax according to the URI definition in rfc 2396, ex: "http://www.erlang.org" -status_line() = {http_version(), status_code(), reason_phrase()} -http_version() = string() ex: "HTTP/1.1" -status_code() = integer() -reason_phrase() = string() -content_type() = string() -headers() = [header()] -header() = {field(), value()} -field() = string() -value() = string() -body() = string() | binary() | - {fun(acc()) -> send_fun_result(), acc()} | - {chunkify, fun(acc()) -> send_fun_result(), acc()} -send_fun_result() = eof | {ok, iolist(), acc()} -acc() = term() -filename() = string() +method() = head | get | put | post | trace | options | delete +request() = {url(), headers()} | + {url(), headers(), content_type(), body()} +url() = string() - Syntax according to the URI definition in rfc 2396, ex: "http://www.erlang.org" +status_line() = {http_version(), status_code(), reason_phrase()} +http_version() = string() ex: "HTTP/1.1" +status_code() = integer() +reason_phrase() = string() +content_type() = string() +headers() = [header()] +header() = {field(), value()} +field() = string() +value() = string() +body() = string() | + binary() | + {fun(accumulator()) -> body_processing_result(), + accumulator()} | + {chunkify, + fun(accumulator()) -> body_processing_result(), + accumulator()} +body_processing_result() = eof | {ok, iolist(), accumulator()} +accumulator() = term() +filename() = string() ]]></code> </section> @@ -146,8 +150,9 @@ ssl_options() = {verify, code()} | <fsummary>Sends a get HTTP-request</fsummary> <type> <v>Url = url() </v> - <v>Result = {status_line(), headers(), body()} | - {status_code(), body()} | request_id() </v> + <v>Result = {status_line(), headers(), Body} | + {status_code(), Body} | request_id() </v> + <v>Body = string() | binary()</v> <v>Profile = profile()</v> <v>Reason = term() </v> </type> @@ -195,8 +200,9 @@ ssl_options() = {verify, code()} | <v>Function = atom() </v> <v>Args = list() </v> <v>body_format() = string | binary </v> - <v>Result = {status_line(), headers(), body()} | - {status_code(), body()} | request_id() </v> + <v>Result = {status_line(), headers(), Body} | + {status_code(), Body} | request_id() </v> + <v>Body = string() | binary()</v> <v>Profile = profile() </v> <v>Reason = {connect_failed, term()} | {send_failed, term()} | term() </v> diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 11b0af4310..8c0d683a90 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> @@ -32,50 +32,80 @@ <file>notes.xml</file> </header> - <section><title>Inets 5.5.1</title> + <section><title>Inets 5.6</title> - <section><title>Fixed Bugs and Malfunctions</title> + <section><title>Improvements and New Features</title> +<!-- + <p>-</p> +--> <list> <item> - <p> Fix format_man_pages so it handles all man sections - and remove warnings/errors in various man pages. </p> - <p> - Own Id: OTP-8600</p> + <p>[httpc] Add support for upload body streaming (PUT and POST).</p> + <p>For more info, + see the definition of the <c>Body</c> argument of the + <seealso marker="httpc#request2">request/4,5</seealso> + function. </p> + <p>Filipe David Manana</p> + <p>Own Id: OTP-9094</p> </item> + </list> + </section> + + <section><title>Fixed Bugs and Malfunctions</title> + <p>-</p> + +<!-- + <list> <item> - <p> - [httpc] Pipelined and queued requests not processed when - connection closed remotelly.</p> - <p> - Own Id: OTP-8906</p> + <p>[httpc] Pipelined and queued requests not processed when + connection closed remotelly.</p> + <p>Own Id: OTP-8906</p> </item> </list> +--> </section> + </section> <!-- 5.6 --> + + + <section><title>Inets 5.5.1</title> + <section><title>Improvements and New Features</title> <list> <item> - <p> - Miscellaneous inet6 related problems.</p> - <p> - Own Id: OTP-8927</p> + <p>Miscellaneous inet6 related problems.</p> + <p>Own Id: OTP-8927</p> </item> <item> - <p> - Updated http-server to make sure URLs in error-messages - are URL-encoded. Added support in http-client to use - URL-encoding. Also added the missing include directory - for the inets application.</p> - <p> - Own Id: OTP-8940 Aux Id: seq11735 </p> + <p>Updated http-server to make sure URLs in error-messages + are URL-encoded. Added support in http-client to use + URL-encoding. Also added the missing include directory + for the inets application.</p> + <p>Own Id: OTP-8940, Aux Id: seq11735 </p> </item> </list> </section> -</section> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> Fix format_man_pages so it handles all man sections + and remove warnings/errors in various man pages. </p> + <p>Own Id: OTP-8600</p> + </item> + <item> + <p>[httpc] Pipelined and queued requests not processed when + connection closed remotelly.</p> + <p>Own Id: OTP-8906</p> + </item> + </list> + </section> + + </section> <!-- 5.5.1 --> + -<section><title>Inets 5.5</title> + <section><title>Inets 5.5</title> <section><title>Fixed Bugs and Malfunctions</title> <list> @@ -120,9 +150,10 @@ </list> </section> -</section> + </section> <!-- 5.5 --> + -<section><title>Inets 5.4</title> + <section><title>Inets 5.4</title> <section><title>Improvements and New Features</title> <!-- diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index 7490bb0e46..c7f8a02a0b 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -432,32 +432,41 @@ handle_request(Method, Url, Headers0, ContentType, Body0, HTTPOptions0, Options0, Profile) -> - Started = http_util:timestamp(), + Started = http_util:timestamp(), NewHeaders0 = [{http_util:to_lower(Key), Val} || {Key, Val} <- Headers0], - {NewHeaders, Body} = case Body0 of - {chunkify, BodyFun, Acc} -> - NewHeaders1 = lists:keystore("transfer-encoding", 1, - NewHeaders0, {"transfer-encoding", "chunked"}), - {NewHeaders1, {chunkify_fun(BodyFun), Acc}}; - _ -> - {NewHeaders0, Body0} - end, - try begin + ?hcrt("begin processing", [{started, Started}, + {new_headers, NewHeaders0}]), + + {NewHeaders, Body} = + case Body0 of + {chunkify, ProcessBody, Acc} + when is_function(ProcessBody, 1) -> + NewHeaders1 = ensure_chunked_encoding(NewHeaders0), + Body1 = {mk_chunkify_fun(ProcessBody), Acc}, + {NewHeaders1, Body1}; + {ProcessBody, _} + when is_function(ProcessBody, 1) -> + {NewHeaders0, Body0}; + _ when is_list(Body0) orelse is_binary(Body0) -> + {NewHeaders0, Body0}; + _ -> + throw({error, {bad_body, Body0}}) + end, + HTTPOptions = http_options(HTTPOptions0), Options = request_options(Options0), Sync = proplists:get_value(sync, Options), Stream = proplists:get_value(stream, Options), Host2 = header_host(Scheme, Host, Port), HeadersRecord = header_record(NewHeaders, Host2, HTTPOptions), - Receiver = proplists:get_value(receiver, Options), - SocketOpts = proplists:get_value(socket_opts, Options), - UrlEncodeBool = HTTPOptions#http_options.url_encode, - MaybeEscPath = url_encode(Path, UrlEncodeBool), - MaybeEscQuery = url_encode(Query, UrlEncodeBool), - AbsUri = url_encode(Url, UrlEncodeBool), + Receiver = proplists:get_value(receiver, Options), + SocketOpts = proplists:get_value(socket_opts, Options), + MaybeEscPath = maybe_encode_uri(HTTPOptions, Path), + MaybeEscQuery = maybe_encode_uri(HTTPOptions, Query), + AbsUri = maybe_encode_uri(HTTPOptions, Url), Request = #request{from = Receiver, scheme = Scheme, @@ -474,51 +483,67 @@ handle_request(Method, Url, headers_as_is = headers_as_is(Headers0, Options), socket_opts = SocketOpts, started = Started}, + case httpc_manager:request(Request, profile_name(Profile)) of {ok, RequestId} -> handle_answer(RequestId, Sync, Options); {error, Reason} -> + ?hcrd("request failed", [{reason, Reason}]), {error, Reason} end end catch error:{noproc, _} -> + ?hcrl("noproc", [{profile, Profile}]), {error, {not_started, Profile}}; throw:Error -> + ?hcrl("throw", [{error, Error}]), Error end. -url_encode(URI, true) -> +ensure_chunked_encoding(Hdrs) -> + Key = "transfer-encoding", + lists:keystore(Key, 1, Hdrs, {Key, "chunked"}). + +maybe_encode_uri(#http_options{url_encode = true}, URI) -> http_uri:encode(URI); -url_encode(URI, false) -> +maybe_encode_uri(_, URI) -> URI. -chunkify_fun(BodyFun) -> - fun(eof_body_fun) -> - eof; - (Acc) -> - case BodyFun(Acc) of - eof -> - {ok, <<"0\r\n\r\n">>, eof_body_fun}; - {ok, Data, NewAcc} -> - Bin = iolist_to_binary(Data), - Chunk = [hex_size(Bin), "\r\n", Bin, "\r\n"], - {ok, iolist_to_binary(Chunk), NewAcc} - end +mk_chunkify_fun(ProcessBody) -> + fun(eof_body) -> + eof; + (Acc) -> + case ProcessBody(Acc) of + eof -> + {ok, <<"0\r\n\r\n">>, eof_body}; + {ok, Data, NewAcc} -> + {ok, mk_chunk_bin(Data), NewAcc} + end end. +mk_chunk_bin(Data) -> + Bin = iolist_to_binary(Data), + iolist_to_binary([hex_size(Bin), "\r\n", Bin, "\r\n"]). + hex_size(Bin) -> hd(io_lib:format("~.16B", [size(Bin)])). + handle_answer(RequestId, false, _) -> {ok, RequestId}; handle_answer(RequestId, true, Options) -> receive {http, {RequestId, saved_to_file}} -> + ?hcrt("received saved-to-file", [{request_id, RequestId}]), {ok, saved_to_file}; {http, {RequestId, {_,_,_} = Result}} -> + ?hcrt("received answer", [{request_id, RequestId}, + {result, Result}]), return_answer(Options, Result); {http, {RequestId, {error, Reason}}} -> + ?hcrt("received error", [{request_id, RequestId}, + {reason, Reason}]), {error, Reason} end. diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index cb6f3e2841..5e22400fe0 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1724,9 +1724,27 @@ handle_verbose(_) -> %% ok. +send_raw(#session{socket = Socket, socket_type = SocketType}, + {ProcessBody, Acc}) when is_function(ProcessBody, 1) -> + ?hcrt("send raw", [{acc, Acc}]), + send_raw(SocketType, Socket, ProcessBody, Acc); send_raw(#session{socket = Socket, socket_type = SocketType}, Body) -> http_transport:send(SocketType, Socket, Body). +send_raw(SocketType, Socket, ProcessBody, Acc) -> + case ProcessBody(Acc) of + eof -> + ok; + {ok, Data, NewAcc} -> + DataBin = iolist_to_binary(Data), + ?hcrd("send", [{data, DataBin}]), + case http_transport:send(SocketType, Socket, DataBin) of + ok -> + send_raw(SocketType, Socket, ProcessBody, NewAcc); + Error -> + Error + end + end. call(Msg, Pid) -> diff --git a/lib/inets/src/http_client/httpc_request.erl b/lib/inets/src/http_client/httpc_request.erl index 5386d1eb4a..0d602adb11 100644 --- a/lib/inets/src/http_client/httpc_request.erl +++ b/lib/inets/src/http_client/httpc_request.erl @@ -79,41 +79,43 @@ send(SendAddr, Socket, SocketType, {settings, HttpOptions}, {userinfo, UserInfo}]), - TmpHeaders = handle_user_info(UserInfo, Headers), + TmpHdrs = handle_user_info(UserInfo, Headers), - {TmpHeaders2, Body} = - post_data(Method, TmpHeaders, Content, HeadersAsIs), + {TmpHdrs2, Body} = post_data(Method, TmpHdrs, Content, HeadersAsIs), - {NewHeaders, Uri} = case Address of - SendAddr -> - {TmpHeaders2, Path ++ Query}; - _Proxy -> - TmpHeaders3 = - handle_proxy(HttpOptions, TmpHeaders2), - {TmpHeaders3, AbsUri} - end, - - FinalHeaders = case NewHeaders of - HeaderList when is_list(HeaderList) -> - http_headers(HeaderList, []); - _ -> - http_request:http_headers(NewHeaders) - end, + {NewHeaders, Uri} = + case Address of + SendAddr -> + {TmpHdrs2, Path ++ Query}; + _Proxy -> + TmpHdrs3 = handle_proxy(HttpOptions, TmpHdrs2), + {TmpHdrs3, AbsUri} + end, + + FinalHeaders = + case NewHeaders of + HeaderList when is_list(HeaderList) -> + http_headers(HeaderList, []); + _ -> + http_request:http_headers(NewHeaders) + end, Version = HttpOptions#http_options.version, do_send_body(SocketType, Socket, Method, Uri, Version, FinalHeaders, Body). -do_send_body(SocketType, Socket, Method, Uri, Version, Headers, {DataFun, Acc}) - when is_function(DataFun, 1) -> +do_send_body(SocketType, Socket, Method, Uri, Version, Headers, + {ProcessBody, Acc}) when is_function(ProcessBody, 1) -> + ?hcrt("send", [{acc, Acc}]), case do_send_body(SocketType, Socket, Method, Uri, Version, Headers, []) of ok -> - data_fun_loop(SocketType, Socket, DataFun, Acc); + do_send_body(SocketType, Socket, ProcessBody, Acc); Error -> Error end; do_send_body(SocketType, Socket, Method, Uri, Version, Headers, Body) -> + ?hcrt("create message", [{body, Body}]), Message = [method(Method), " ", Uri, " ", version(Version), ?CRLF, headers(Headers, Version), ?CRLF, Body], @@ -121,16 +123,16 @@ do_send_body(SocketType, Socket, Method, Uri, Version, Headers, Body) -> http_transport:send(SocketType, Socket, lists:append(Message)). -data_fun_loop(SocketType, Socket, DataFun, Acc) -> - case DataFun(Acc) of +do_send_body(SocketType, Socket, ProcessBody, Acc) -> + case ProcessBody(Acc) of eof -> ok; {ok, Data, NewAcc} -> DataBin = iolist_to_binary(Data), - ?hcrd("send", [{message, DataBin}]), + ?hcrd("send", [{data, DataBin}]), case http_transport:send(SocketType, Socket, DataBin) of ok -> - data_fun_loop(SocketType, Socket, DataFun, NewAcc); + do_send_body(SocketType, Socket, ProcessBody, NewAcc); Error -> Error end diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 41737a0d74..c83ccf14df 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -59,168 +59,93 @@ %% or a skip tuple if the platform is not supported. %%-------------------------------------------------------------------- -<<<<<<< variant A suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [proxy_options, proxy_head, proxy_get, proxy_trace, - proxy_post, proxy_put, proxy_delete, proxy_auth, - proxy_headers, proxy_emulate_lower_versions, - http_options, http_head, http_get, http_post, - http_dummy_pipe, http_inets_pipe, http_trace, - http_async, http_save_to_file, http_save_to_file_async, - http_headers, http_headers_dummy, http_bad_response, - ssl_head, ossl_head, essl_head, ssl_get, ossl_get, - essl_get, ssl_trace, ossl_trace, essl_trace, - http_redirect, http_redirect_loop, - http_internal_server_error, http_userinfo, http_cookie, - http_server_does_not_exist, http_invalid_http, - http_emulate_lower_versions, http_relaxed, - page_does_not_exist, proxy_page_does_not_exist, - proxy_https_not_supported, http_stream, - http_stream_once, proxy_stream, parse_url, options, - ipv6, headers_as_is, {group, tickets}]. - -groups() -> - [{tickets, [], - [hexed_query_otp_6191, empty_body_otp_6243, - empty_response_header_otp_6830, - transfer_encoding_otp_6807, proxy_not_modified_otp_6821, - no_content_204_otp_6982, missing_CR_otp_7304, - {group, otp_7883}, {group, otp_8154}, {group, otp_8106}, - otp_8056, otp_8352, otp_8371, otp_8739]}, - {otp_7883, [], [otp_7883_1, otp_7883_2]}, - {otp_8154, [], [otp_8154_1]}, - {otp_8106, [], - [otp_8106_pid, otp_8106_fun, otp_8106_mfa]}]. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - ->>>>>>> variant B -all(doc) -> - ["Test the http client in the intes application."]; -all(suite) -> [ proxy_options, proxy_head, proxy_get, - proxy_trace, - proxy_post, + proxy_trace, + proxy_post, proxy_put, - proxy_delete, + proxy_delete, proxy_auth, - proxy_headers, + proxy_headers, proxy_emulate_lower_versions, http_options, http_head, http_get, http_post, - http_post_streaming, - http_dummy_pipe, - http_inets_pipe, + http_post_streaming, + http_dummy_pipe, + http_inets_pipe, http_trace, - http_async, - http_save_to_file, + http_async, + http_save_to_file, http_save_to_file_async, - http_headers, - http_headers_dummy, + http_headers, + http_headers_dummy, http_bad_response, ssl_head, ossl_head, essl_head, ssl_get, - ossl_get, + ossl_get, essl_get, ssl_trace, ossl_trace, - essl_trace, + essl_trace, http_redirect, http_redirect_loop, - http_internal_server_error, - http_userinfo, - http_cookie, - http_server_does_not_exist, + http_internal_server_error, + http_userinfo, http_cookie, + http_server_does_not_exist, http_invalid_http, - http_emulate_lower_versions, - http_relaxed, + http_emulate_lower_versions, + http_relaxed, page_does_not_exist, - proxy_page_does_not_exist, - proxy_https_not_supported, + proxy_page_does_not_exist, + proxy_https_not_supported, http_stream, - http_stream_once, - proxy_stream, - parse_url, + http_stream_once, + proxy_stream, + parse_url, options, - ipv6, - headers_as_is, - tickets + ipv6, + headers_as_is, + {group, tickets} ]. - -####### Ancestor -all(doc) -> - ["Test the http client in the intes application."]; -all(suite) -> - [ - proxy_options, - proxy_head, - proxy_get, - proxy_trace, - proxy_post, - proxy_put, - proxy_delete, - proxy_auth, - proxy_headers, - proxy_emulate_lower_versions, - http_options, - http_head, - http_get, - http_post, - http_dummy_pipe, - http_inets_pipe, - http_trace, - http_async, - http_save_to_file, - http_save_to_file_async, - http_headers, - http_headers_dummy, - http_bad_response, - ssl_head, - ossl_head, - essl_head, - ssl_get, - ossl_get, - essl_get, - ssl_trace, - ossl_trace, - essl_trace, - http_redirect, - http_redirect_loop, - http_internal_server_error, - http_userinfo, - http_cookie, - http_server_does_not_exist, - http_invalid_http, - http_emulate_lower_versions, - http_relaxed, - page_does_not_exist, - proxy_page_does_not_exist, - proxy_https_not_supported, - http_stream, - http_stream_once, - proxy_stream, - parse_url, - options, - ipv6, - headers_as_is, - tickets - ]. - -======= end + +groups() -> + [{tickets, [], [hexed_query_otp_6191, + empty_body_otp_6243, + empty_response_header_otp_6830, + transfer_encoding_otp_6807, + proxy_not_modified_otp_6821, + no_content_204_otp_6982, + missing_CR_otp_7304, + {group, otp_7883}, + {group, otp_8154}, + {group, otp_8106}, + otp_8056, + otp_8352, + otp_8371, + otp_8739]}, + {otp_7883, [], [otp_7883_1, + otp_7883_2]}, + {otp_8154, [], [otp_8154_1]}, + {otp_8106, [], [otp_8106_pid, + otp_8106_fun, + otp_8106_mfa]}]. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + + %%-------------------------------------------------------------------- %% Function: init_per_suite(Config) -> Config %% Config - [tuple()] @@ -259,6 +184,7 @@ init_per_suite(Config) -> {local_port, ?IP_PORT}, {local_ssl_port, ?SSL_PORT} | Config]. + %%-------------------------------------------------------------------- %% Function: end_per_suite(Config) -> _ %% Config - [tuple()] @@ -272,6 +198,7 @@ end_per_suite(Config) -> application:stop(ssl), ok. + %%-------------------------------------------------------------------- %% Function: init_per_testcase(Case, Config) -> Config %% Case - atom() @@ -517,9 +444,9 @@ http_post(Config) when is_list(Config) -> %%------------------------------------------------------------------------- http_post_streaming(doc) -> - ["Test streaming http post request against local server. We" - " only care about the client side of the the post. The server" - " script will not actually use the post data."]; + ["Test streaming http post request against local server. " + "We only care about the client side of the the post. " + "The server script will not actually use the post data."]; http_post_streaming(suite) -> []; http_post_streaming(Config) when is_list(Config) -> @@ -536,24 +463,32 @@ http_post_streaming(Config) when is_list(Config) -> end, %% Cgi-script expects the body length to be 100 BodyFun = fun(0) -> - eof; - (LenLeft) -> - {ok, lists:duplicate(10, "1"), LenLeft - 10} - end, - + io:format("~w:http_post_streaming_fun -> " + "zero~n", [?MODULE]), + eof; + (LenLeft) -> + io:format("~w:http_post_streaming_fun -> " + "LenLeft: ~p~n", [?MODULE, LenLeft]), + {ok, lists:duplicate(10, "1"), LenLeft - 10} + end, + {ok, {{_,200,_}, [_ | _], [_ | _]}} = - httpc:request(post, {URL, - [{"expect", "100-continue"}, {"content-length", "100"}], - "text/plain", {BodyFun, 100}}, [], []), - + httpc:request(post, {URL, + [{"expect", "100-continue"}, + {"content-length", "100"}], + "text/plain", {BodyFun, 100}}, [], []), + {ok, {{_,504,_}, [_ | _], []}} = - httpc:request(post, {URL, - [{"expect", "100-continue"}, {"content-length", "10"}], - "text/plain", {BodyFun, 10}}, [], []); + httpc:request(post, {URL, + [{"expect", "100-continue"}, + {"content-length", "10"}], + "text/plain", {BodyFun, 10}}, [], []); + _ -> {skip, "Failed to start local http-server"} end. + %%------------------------------------------------------------------------- http_emulate_lower_versions(doc) -> ["Perform request as 0.9 and 1.0 clients."]; @@ -2733,7 +2668,7 @@ otp_8739_dummy_server_init(Parent) -> Parent ! {port, Port}, otp_8739_dummy_server_main(Parent, ListenSocket). -otp_8739_dummy_server_main(Parent, ListenSocket) -> +otp_8739_dummy_server_main(_Parent, ListenSocket) -> case gen_tcp:accept(ListenSocket) of {ok, Sock} -> %% Ignore the request, and simply wait for the socket to close |