aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets')
-rw-r--r--lib/inets/doc/src/http_server.xml31
-rw-r--r--lib/inets/doc/src/http_uri.xml10
-rw-r--r--lib/inets/doc/src/httpc.xml10
-rw-r--r--lib/inets/doc/src/httpd.xml245
-rw-r--r--lib/inets/doc/src/notes.xml131
-rw-r--r--lib/inets/doc/src/tftp.xml21
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl26
-rw-r--r--lib/inets/src/http_lib/http_chunk.erl21
-rw-r--r--lib/inets/src/http_lib/http_response.erl2
-rw-r--r--lib/inets/src/http_server/Makefile2
-rw-r--r--lib/inets/src/http_server/httpd_custom_api.erl3
-rw-r--r--lib/inets/src/http_server/httpd_example.erl10
-rw-r--r--lib/inets/src/http_server/httpd_request_handler.erl15
-rw-r--r--lib/inets/src/http_server/httpd_response.erl27
-rw-r--r--lib/inets/src/http_server/httpd_util.erl16
-rw-r--r--lib/inets/src/http_server/mod_esi.erl47
-rw-r--r--lib/inets/src/inets_app/inets.app.src1
-rw-r--r--lib/inets/test/http_format_SUITE.erl16
-rw-r--r--lib/inets/test/httpc_SUITE.erl21
-rw-r--r--lib/inets/test/httpd_1_1.erl11
-rw-r--r--lib/inets/test/httpd_SUITE.erl9
-rw-r--r--lib/inets/test/httpd_SUITE_data/Makefile.src5
-rw-r--r--lib/inets/test/httpd_test_lib.erl16
-rw-r--r--lib/inets/vsn.mk2
24 files changed, 391 insertions, 307 deletions
diff --git a/lib/inets/doc/src/http_server.xml b/lib/inets/doc/src/http_server.xml
index 4b6d64fc8f..aeda961714 100644
--- a/lib/inets/doc/src/http_server.xml
+++ b/lib/inets/doc/src/http_server.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -21,18 +21,8 @@
limitations under the License.
</legalnotice>
-
<title>HTTP server</title>
- <prepared>Ingela Anderton Andin</prepared>
- <responsible></responsible>
- <docno></docno>
- <approved></approved>
- <checked></checked>
- <date></date>
- <rev></rev>
<file>http_server.xml</file>
-
- <marker id="intro"></marker>
</header>
<section>
@@ -65,12 +55,9 @@
<p>As of <c>Inets</c> 5.0 the HTTP server is an easy to
start/stop and customize web server providing the most basic
- web server functionality. Depending on your needs, there
- are also other Erlang-based web servers that can be of interest
- such as <url href=" http://yaws.hyber.org ">Yaws</url>, which,
- for example, has its own
- markup support to generate HTML and supports certain buzzword
- technologies, such as SOAP.</p>
+ web server functionality. Inets is designed for embedded systems
+ and if you want a full-fledged web server there are exists other
+ erlang open source alternatives.</p>
<p>Almost all server functionality has been implemented using an
especially crafted server API, which is described in the Erlang Web
@@ -356,9 +343,9 @@ UserName:Password</pre>
</taglist>
<section>
- <title>CGI Version 1.1,
- <url href="http://www.ietf.org/rfc/rfc3875.txt">RFC 3875</url></title>
- <p>The module <c>mod_cgi</c> enables execution of CGI scripts
+ <title>CGI Version 1.1, RFC 3875</title>
+ <p>The module <c>mod_cgi</c> enables execution of
+ <url href="http://www.ietf.org/rfc/rfc3875.txt">CGI scripts</url>
on the server. A file matching the definition of a
ScriptAlias config directive is treated as a CGI script. A CGI
script is executed by the server and its output is returned to
@@ -541,7 +528,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
<title>mod_action - Filetype/Method-Based Script Execution</title>
<p>This module runs CGI scripts whenever a file of a
certain type or HTTP method (see
- <url href="http://tools.ietf.org/html/rfc1945">RFC 1945</url>RFC 1945)
+ <url href="http://tools.ietf.org/html/rfc1945">RFC 1945</url>)
is requested.
</p>
<p>Uses the following Erlang Web Server API interaction data:
@@ -568,7 +555,7 @@ http://your.server.org/eval?httpd_example:print(atom_to_list(apply(erlang,halt,[
<taglist>
<tag><c>{real_name, PathData}</c></tag>
<item><c>PathData</c> is the argument used for API function
- <seealso marker="mod_alias:path/3">mod_alias:path/3</seealso>.</item>
+ <seealso marker="mod_alias#path/3">mod_alias:path/3</seealso>.</item>
</taglist>
</section>
diff --git a/lib/inets/doc/src/http_uri.xml b/lib/inets/doc/src/http_uri.xml
index 64e6c7a6cc..8e0301c520 100644
--- a/lib/inets/doc/src/http_uri.xml
+++ b/lib/inets/doc/src/http_uri.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2012</year><year>2013</year>
+ <year>2012</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -142,14 +142,14 @@
<p>If the fragment option is <c>true</c>, the URI fragment is returned as
part of the parsing result, otherwise it is ignored.</p>
- <p>Scheme validation fun is to be defined as follows:
+ <p>Scheme validation fun is to be defined as follows:</p>
- <code>
+ <code>
fun(SchemeStr :: string()) ->
valid | {error, Reason :: term()}.
- </code>
+ </code>
- It is called before scheme string gets converted into scheme atom and
+ <p>It is called before scheme string gets converted into scheme atom and
thus possible atom leak could be prevented</p>
<marker id="encode"></marker>
diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index 31e44f405c..ca9b268a03 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -554,8 +554,8 @@
<v>IpDesc = string()</v>
<d>Example: "134.138" or "[FEDC:BA98"
(all IP addresses starting with 134.138 or FEDC:BA98),
- "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP address).</d>
- <d><c>proxy</c> defaults to <c>{undefined, []}</c>,
+ "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP address).
+ <c>proxy</c> defaults to <c>{undefined, []}</c>,
that is, no proxy is configured and
<c>https_proxy</c> defaults to the value of <c>proxy</c>.</d>
<v>MaxSessions = integer()</v>
@@ -597,8 +597,8 @@
for details.</d>
<v>socket_opts() = [socket_opt()]</v>
<d>The options are appended to the socket options used by the
- client.</d>
- <d>These are the default values when a new request handler
+ client.
+ These are the default values when a new request handler
is started (for the initial connect). They are passed directly
to the underlying transport (<c>gen_tcp</c> or <c>SSL</c>)
<em>without</em> verification.</d>
diff --git a/lib/inets/doc/src/httpd.xml b/lib/inets/doc/src/httpd.xml
index 0fc3cb1ce7..62b92b8356 100644
--- a/lib/inets/doc/src/httpd.xml
+++ b/lib/inets/doc/src/httpd.xml
@@ -30,13 +30,14 @@
<file>httpd.sgml</file>
</header>
<module>httpd</module>
- <modulesummary>An implementation of an HTTP
- 1.1 compliant web server, as defined in <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>
+ <modulesummary>
+ HTTP server API
</modulesummary>
<description>
- <p>This module provides the HTTP server start options, some administrative
- functions, and specifies the Erlang web server callback
- API.</p>
+ <p>An implementation of an HTTP 1.1 compliant web server, as defined in
+ <url href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</url>.
+ Provides web server start options, administrative functions, and
+ an Erlang callback API.</p>
</description>
<section>
@@ -78,8 +79,7 @@
list.</p>
<taglist>
- <marker id="prop_proplist_file"></marker>
- <tag>{proplist_file, path()}</tag>
+ <tag><marker id="prop_proplist_file"></marker>{proplist_file, path()}</tag>
<item>
<p>If this property is defined, <c>Inets</c> expects to find
all other properties defined in this file. The
@@ -87,8 +87,7 @@
properties.</p>
</item>
- <marker id="prop_file"></marker>
- <tag>{file, path()}</tag>
+ <tag><marker id="prop_file"></marker>{file, path()}</tag>
<item>
<p>If this property is defined, <c>Inets</c> expects to find all
other properties defined in this file, which uses Apache-like
@@ -121,8 +120,7 @@
<marker id="props_mand"></marker>
<p><em>Mandatory Properties</em></p>
<taglist>
- <marker id="prop_port"></marker>
- <tag>{port, integer()} </tag>
+ <tag><marker id="prop_port"></marker>{port, integer()} </tag>
<item>
<p>The port that the HTTP server listen to.
If zero is specified as port, an arbitrary available port
@@ -130,22 +128,19 @@
determine which port was picked.</p>
</item>
- <marker id="prop_server_name"></marker>
- <tag>{server_name, string()}</tag>
+ <tag><marker id="prop_server_name"></marker>{server_name, string()}</tag>
<item>
<p>The name of your server, normally a fully qualified domain name.</p>
</item>
- <marker id="prop_server_root"></marker>
- <tag>{server_root, path()}</tag>
+ <tag><marker id="prop_server_root"></marker>{server_root, path()}</tag>
<item>
<p>Defines the home directory of the server, where log files, and so on,
can be stored. Relative paths specified in other properties refer
to this directory.</p>
</item>
- <marker id="prop_doc_root"></marker>
- <tag>{document_root, path()}</tag>
+ <tag> <marker id="prop_doc_root"></marker>{document_root, path()}</tag>
<item>
<p>Defines the top directory for the documents that
are available on the HTTP server.</p>
@@ -155,15 +150,13 @@
<marker id="props_comm"></marker>
<p><em>Communication Properties</em></p>
<taglist>
- <marker id="prop_bind_address"></marker>
- <tag>{bind_address, ip_address() | hostname() | any}</tag>
+ <tag><marker id="prop_bind_address"></marker>{bind_address, ip_address() | hostname() | any}</tag>
<item>
<p>Default is <c>any</c>. <c>any</c> is denoted <em>*</em>
in the Apache-like configuration file.</p>
</item>
- <marker id="profile"></marker>
- <tag>{profile, atom()}</tag>
+ <tag><marker id="profile"></marker>{profile, atom()}</tag>
<item>
<p>Used together with <seealso marker="#prop_bind_address"><c>bind_address</c></seealso>
and <seealso marker="#prop_port"><c>port</c></seealso> to uniquely identify
@@ -176,8 +169,7 @@
</p>
</item>
- <marker id="prop_socket_type"></marker>
- <tag>{socket_type, ip_comm | {ip_comm, Config::proplist()} | {essl, Config::proplist()}}</tag>
+ <tag><marker id="prop_socket_type"></marker>{socket_type, ip_comm | {ip_comm, Config::proplist()} | {essl, Config::proplist()}}</tag>
<item>
<p>For <c>ip_comm</c> configuration options, see
<seealso marker="kernel:gen_tcp#listen-2">gen_tcp:listen/2</seealso>, some options
@@ -187,15 +179,13 @@
<p>Default is <c>ip_comm</c>.</p>
</item>
- <marker id="prop_ipfamily"></marker>
- <tag>{ipfamily, inet | inet6}</tag>
+ <tag><marker id="prop_ipfamily"></marker>{ipfamily, inet | inet6}</tag>
<item>
<p>Default is <c>inet</c>, legacy option <c>inet6fb4</c> no longer makes sense and will be translated
to inet.</p>
</item>
- <marker id="prop_minimum_bytes_per_second"></marker>
- <tag>{minimum_bytes_per_second, integer()}</tag>
+ <tag><marker id="prop_minimum_bytes_per_second"></marker>{minimum_bytes_per_second, integer()}</tag>
<item>
<p>If given, sets a minimum of bytes per second value for connections.</p>
<p>If the value is unreached, the socket closes for that connection.</p>
@@ -206,8 +196,7 @@
<marker id="props_api_modules"></marker>
<p><em>Erlang Web Server API Modules</em> </p>
<taglist>
- <marker id="prop_modules"></marker>
- <tag>{modules, [atom()]} </tag>
+ <tag><marker id="prop_modules"></marker>{modules, [atom()]} </tag>
<item>
<p>Defines which modules the HTTP server uses when handling
requests. Default is <c>[mod_alias, mod_auth, mod_esi,
@@ -224,60 +213,52 @@
<p><em>Limit properties</em> </p>
<taglist>
- <marker id="prop_customize"></marker>
- <tag>{customize, atom()}</tag>
+ <tag><marker id="prop_customize"></marker>{customize, atom()}</tag>
<item>
<p>A callback module to customize the inets HTTP servers behaviour
see <seealso marker="httpd_custom_api"> httpd_custom_api</seealso> </p>
</item>
- <marker id="prop_disable_chunked_encoding"></marker>
- <tag>{disable_chunked_transfer_encoding_send, boolean()}</tag>
+ <tag><marker id="prop_disable_chunked_encoding"></marker>{disable_chunked_transfer_encoding_send, boolean()}</tag>
<item>
<p>Allows you to disable chunked
transfer-encoding when sending a response to an HTTP/1.1
client. Default is <c>false</c>.</p>
</item>
- <marker id="prop_keep_alive"></marker>
- <tag>{keep_alive, boolean()}</tag>
+ <tag><marker id="prop_keep_alive"></marker>{keep_alive, boolean()}</tag>
<item>
<p>Instructs the server whether to use persistent
connections when the client claims to be HTTP/1.1
compliant. Default is <c>true</c>.</p>
</item>
- <marker id="prop_keep_alive_timeout"></marker>
- <tag>{keep_alive_timeout, integer()}</tag>
+ <tag><marker id="prop_keep_alive_timeout"></marker>{keep_alive_timeout, integer()}</tag>
<item>
<p>The number of seconds the server waits for a
subsequent request from the client before closing the
connection. Default is <c>150</c>.</p>
</item>
- <marker id="prop_max_body_size"></marker>
- <tag>{max_body_size, integer()}</tag>
+ <tag><marker id="prop_max_body_size"></marker>{max_body_size, integer()}</tag>
<item>
<p>Limits the size of the message body of an HTTP request.
Default is no limit.</p>
</item>
- <marker id="prop_max_clients"></marker>
- <tag>{max_clients, integer()}</tag>
+ <tag><marker id="prop_max_clients"></marker>{max_clients, integer()}</tag>
<item>
<p>Limits the number of simultaneous requests that can be
supported. Default is <c>150</c>.</p>
</item>
- <marker id="prop_max_header_size"></marker>
- <tag>{max_header_size, integer()}</tag>
+ <tag><marker id="prop_max_header_size"></marker>{max_header_size, integer()}</tag>
<item>
<p>Limits the size of the message header of an HTTP request.
Default is <c>10240</c>.</p>
</item>
- <marker id="prop_max_content_length"></marker>
- <tag>{max_content_length, integer()}</tag>
+ <tag><marker id="prop_max_content_length"></marker>{max_content_length, integer()}</tag>
<item>
<p>Maximum content-length in an incoming request, in bytes. Requests
with content larger than this are answered with status 413.
@@ -285,15 +266,13 @@
</p>
</item>
- <marker id="prop_max_uri"></marker>
- <tag>{max_uri_size, integer()}</tag>
+ <tag><marker id="prop_max_uri"></marker>{max_uri_size, integer()}</tag>
<item>
<p>Limits the size of the HTTP request URI.
Default is no limit.</p>
</item>
- <marker id="prop_max_keep_alive_req"></marker>
- <tag>{max_keep_alive_request, integer()}</tag>
+ <tag><marker id="prop_max_keep_alive_req"></marker>{max_keep_alive_request, integer()}</tag>
<item>
<p>The number of requests that a client can do on one
connection. When the server has responded to the number of
@@ -306,8 +285,7 @@
<marker id="props_admin"></marker>
<p><em>Administrative Properties</em></p>
<taglist>
- <marker id="prop_mime_types"></marker>
- <tag>{mime_types, [{MimeType, Extension}] | path()}</tag>
+ <tag><marker id="prop_mime_types"></marker>{mime_types, [{MimeType, Extension}] | path()}</tag>
<item>
<p><c>MimeType = string()</c> and <c>Extension = string()</c>.
Files delivered to the client are MIME typed according to RFC
@@ -323,24 +301,21 @@ text/plain asc txt</pre>
<p>Default is [{"html","text/html"},{"htm","text/html"}].</p>
</item>
- <marker id="prop_mime_type"></marker>
- <tag>{mime_type, string()}</tag>
+ <tag><marker id="prop_mime_type"></marker>{mime_type, string()}</tag>
<item>
<p>When the server is asked to provide a document type that
cannot be determined by the MIME Type Settings, the server
uses this default type.</p>
</item>
- <marker id="prop_server_admin"></marker>
- <tag>{server_admin, string()}</tag>
+ <tag><marker id="prop_server_admin"></marker>{server_admin, string()}</tag>
<item>
<p>Defines the email-address of the server
administrator to be included in any error messages returned by
the server.</p>
</item>
- <marker id="prop_server_tokens"></marker>
- <tag>{server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}</tag>
+ <tag><marker id="prop_server_tokens"></marker>{server_tokens, none|prod|major|minor|minimal|os|full|{private, string()}}</tag>
<item>
<p>Defines the look of the value of the server header.</p>
<p>Example: Assuming the version of <c>Inets</c> is 5.8.1,
@@ -367,8 +342,7 @@ text/plain asc txt</pre>
<p>By default, the value is as before, that is, <c>minimal</c>.</p>
</item>
- <marker id="prop_log_format"></marker>
- <tag>{log_format, common | combined}</tag>
+ <tag><marker id="prop_log_format"></marker>{log_format, common | combined}</tag>
<item>
<p>Defines if access logs are to be written according to the <c>common</c>
log format or the extended common log format.
@@ -411,8 +385,7 @@ text/plain asc txt</pre>
</p>
</item>
- <marker id="prop_elog_format"></marker>
- <tag>{error_log_format, pretty | compact}</tag>
+ <tag><marker id="prop_elog_format"></marker>{error_log_format, pretty | compact}</tag>
<item>
<p>Default is <c>pretty</c>. If the error log is meant to be read
directly by a human, <c>pretty</c> is the best option.</p>
@@ -434,60 +407,57 @@ text/plain asc txt</pre>
<marker id="props_alias"></marker>
<p><em>URL Aliasing Properties - Requires mod_alias</em></p>
<taglist>
- <marker id="prop_alias"></marker>
- <tag>{alias, {Alias, RealName}}</tag>
+ <tag><marker id="prop_alias"></marker>{alias, {Alias, RealName}}</tag>
<item>
<p><c>Alias = string()</c> and <c>RealName = string()</c>.
<c>alias</c> allows documents to be stored in the local file
system instead of the <c>document_root</c> location. URLs with a path
beginning with url-path is mapped to local files beginning with
- directory-filename, for example:
+ directory-filename, for example:</p>
<code>{alias, {"/image", "/ftp/pub/image"}}</code>
- Access to http://your.server.org/image/foo.gif would refer to
+ <p>Access to http://your.server.org/image/foo.gif would refer to
the file /ftp/pub/image/foo.gif.</p>
</item>
- <marker id="prop_re_write"></marker>
- <tag>{re_write, {Re, Replacement}}</tag>
+ <tag><marker id="prop_re_write"></marker>{re_write, {Re, Replacement}}</tag>
<item>
<p><c>Re = string()</c> and <c>Replacement = string()</c>.
<c>re_write</c> allows documents to be stored in the local file
system instead of the <c>document_root</c> location. URLs are rewritten
by <c>re:replace/3</c> to produce a path in the local file-system,
- for example:
+ for example:</p>
<code>{re_write, {"^/[~]([^/]+)(.*)$", "/home/\\1/public\\2"}}</code>
- Access to http://your.server.org/~bob/foo.gif would refer to
+ <p>Access to http://your.server.org/~bob/foo.gif would refer to
the file /home/bob/public/foo.gif.
In an Apache-like configuration file, <c>Re</c> is separated
from <c>Replacement</c> with one single space, and as expected
backslashes do not need to be backslash escaped, the
- same example would become:
+ same example would become:</p>
<code>ReWrite ^/[~]([^/]+)(.*)$ /home/\1/public\2</code>
- Beware of trailing space in <c>Replacement</c> to be used.
+ <p>Beware of trailing space in <c>Replacement</c> to be used.
If you must have a space in <c>Re</c>, use, for example, the character
encoding <c>\040</c>, see
<seealso marker="stdlib:re">re(3)</seealso>.</p>
</item>
- <marker id="prop_dir_idx"></marker>
- <tag>{directory_index, [string()]}</tag>
+ <tag><marker id="prop_dir_idx"></marker>{directory_index, [string()]}</tag>
<item>
<p><c>directory_index</c> specifies a list of resources to look for
if a client requests a directory using a <c>/</c> at the end of the
directory name. <c>file</c> depicts the name of a file in the
directory. Several files can be given, in which case the server
- returns the first it finds, for example:
+ returns the first it finds, for example:</p>
<code>{directory_index, ["index.hml", "welcome.html"]}</code>
- Access to http://your.server.org/docs/ would return
+ <p>Access to http://your.server.org/docs/ would return
http://your.server.org/docs/index.html or
http://your.server.org/docs/welcome.html if index.html does not
exist.</p>
@@ -497,38 +467,35 @@ text/plain asc txt</pre>
<marker id="props_cgi"></marker>
<p><em>CGI Properties - Requires mod_cgi</em></p>
<taglist>
- <marker id="prop_script_alias"></marker>
- <tag>{script_alias, {Alias, RealName}}</tag>
+ <tag><marker id="prop_script_alias"></marker>{script_alias, {Alias, RealName}}</tag>
<item>
<p><c>Alias = string()</c> and <c>RealName = string()</c>.
Have the same behavior as property <c>alias</c>, except that
they also mark the target directory as containing CGI
scripts. URLs with a path beginning with url-path are mapped to
- scripts beginning with directory-filename, for example:
+ scripts beginning with directory-filename, for example:</p>
<code>{script_alias, {"/cgi-bin/", "/web/cgi-bin/"}}</code>
- Access to http://your.server.org/cgi-bin/foo would cause
+ <p>Access to http://your.server.org/cgi-bin/foo would cause
the server to run the script /web/cgi-bin/foo.</p>
</item>
- <marker id="prop_script_re_write"></marker>
- <tag>{script_re_write, {Re, Replacement}}</tag>
+ <tag><marker id="prop_script_re_write"></marker>{script_re_write, {Re, Replacement}}</tag>
<item>
<p><c>Re = string()</c> and <c>Replacement = string()</c>.
Have the same behavior as property <c>re_write</c>, except that
they also mark the target directory as containing CGI
scripts. URLs with a path beginning with url-path are mapped to
- scripts beginning with directory-filename, for example:
+ scripts beginning with directory-filename, for example:</p>
<code>{script_re_write, {"^/cgi-bin/(\\d+)/", "/web/\\1/cgi-bin/"}}</code>
- Access to http://your.server.org/cgi-bin/17/foo would cause
+ <p>Access to http://your.server.org/cgi-bin/17/foo would cause
the server to run the script /web/17/cgi-bin/foo.</p>
</item>
- <marker id="prop_script_nocache"></marker>
- <tag>{script_nocache, boolean()}</tag>
+ <tag><marker id="prop_script_nocache"></marker>{script_nocache, boolean()}</tag>
<item>
<p>If <c>script_nocache</c> is set to <c>true</c>, the HTTP server by
default adds the header fields necessary to prevent proxies from
@@ -536,8 +503,7 @@ text/plain asc txt</pre>
Default to <c>false</c>.</p>
</item>
- <marker id="prop_script_timeout"></marker>
- <tag>{script_timeout, integer()}</tag>
+ <tag><marker id="prop_script_timeout"></marker>{script_timeout, integer()}</tag>
<item>
<p>The time in seconds the web server waits between each
chunk of data from the script. If the CGI script does not deliver
@@ -545,8 +511,7 @@ text/plain asc txt</pre>
closed. Default is <c>15</c>.</p>
</item>
- <marker id="prop_action"></marker>
- <tag>{action, {MimeType, CgiScript}} - requires mod_action</tag>
+ <tag><marker id="prop_action"></marker>{action, {MimeType, CgiScript}} - requires mod_action</tag>
<item>
<p><c>MimeType = string()</c> and <c>CgiScript = string()</c>.
<c>action</c> adds an action activating a CGI script
@@ -559,8 +524,7 @@ text/plain asc txt</pre>
<code>{action, {"text/plain", "/cgi-bin/log_and_deliver_text"}}</code>
</item>
- <marker id="prop_script"></marker>
- <tag>{script, {Method, CgiScript}} - requires mod_action</tag>
+ <tag><marker id="prop_script"></marker>{script, {Method, CgiScript}} - requires mod_action</tag>
<item>
<p><c>Method = string()</c> and <c>CgiScript = string()</c>.
<c>script</c> adds an action activating a CGI script
@@ -579,17 +543,16 @@ text/plain asc txt</pre>
<marker id="props_esi"></marker>
<p><em>ESI Properties - Requires mod_esi</em></p>
<taglist>
- <marker id="prop_esi_alias"></marker>
- <tag>{erl_script_alias, {URLPath, [AllowedModule]}}</tag>
+ <tag><marker id="prop_esi_alias"></marker>{erl_script_alias, {URLPath, [AllowedModule]}}</tag>
<item>
<p><c>URLPath = string()</c> and <c>AllowedModule = atom()</c>.
<c>erl_script_alias</c> marks all URLs matching url-path as erl
scheme scripts. A matching URL is mapped into a specific module
- and function, for example:
+ and function, for example:</p>
<code>{erl_script_alias, {"/cgi-bin/example", [httpd_example]}}</code>
- A request to
+ <p>A request to
http://your.server.org/cgi-bin/example/httpd_example:yahoo
would refer to httpd_example:yahoo/3 or, if that does not exist,
httpd_example:yahoo/2 and
@@ -597,8 +560,7 @@ text/plain asc txt</pre>
not be allowed to execute.</p>
</item>
- <marker id="prop_esi_nocache"></marker>
- <tag>{erl_script_nocache, boolean()}</tag>
+ <tag><marker id="prop_esi_nocache"></marker>{erl_script_nocache, boolean()}</tag>
<item>
<p>If <c>erl_script_nocache</c> is set to <c>true</c>, the server adds
HTTP header fields preventing proxies from caching the
@@ -607,8 +569,7 @@ text/plain asc txt</pre>
Default is <c>false</c>.</p>
</item>
- <marker id="prop_esi_timeout"></marker>
- <tag>{erl_script_timeout, integer()}</tag>
+ <tag><marker id="prop_esi_timeout"></marker>{erl_script_timeout, integer()}</tag>
<item>
<p>If <c>erl_script_timeout</c> sets the time in seconds the server
waits between each chunk of data to be delivered through
@@ -616,8 +577,7 @@ text/plain asc txt</pre>
for scripts that use the erl scheme.</p>
</item>
- <marker id="prop_esi_timeout"></marker>
- <tag>{eval_script_alias, {URLPath, [AllowedModule]}}</tag>
+ <tag><marker id="prop_esi_timeout"></marker>{eval_script_alias, {URLPath, [AllowedModule]}}</tag>
<item>
<p><c>URLPath = string()</c> and <c>AllowedModule = atom()</c>.
Same as <c>erl_script_alias</c> but for scripts
@@ -629,24 +589,21 @@ text/plain asc txt</pre>
<marker id="props_log"></marker>
<p><em>Log Properties - Requires mod_log</em></p>
<taglist>
- <marker id="prop_elog"></marker>
- <tag>{error_log, path()}</tag>
+ <tag><marker id="prop_elog"></marker>{error_log, path()}</tag>
<item>
<p>Defines the filename of the error log file to be used to log
server errors. If the filename does not begin with a slash (/),
it is assumed to be relative to the <c>server_root</c>.</p>
</item>
- <marker id="prop_slog"></marker>
- <tag>{security_log, path()}</tag>
+ <tag><marker id="prop_slog"></marker>{security_log, path()}</tag>
<item>
<p>Defines the filename of the access log file to be used to
log security events. If the filename does not begin with a slash
(/), it is assumed to be relative to the <c>server_root</c>.</p>
</item>
- <marker id="prop_tlog"></marker>
- <tag>{transfer_log, path()}</tag>
+ <tag><marker id="prop_tlog"></marker>{transfer_log, path()}</tag>
<item>
<p>Defines the filename of the access log file to be used to
log incoming requests. If the filename does not begin with a
@@ -657,8 +614,7 @@ text/plain asc txt</pre>
<marker id="props_dlog"></marker>
<p><em>Disk Log Properties - Requires mod_disk_log</em></p>
<taglist>
- <marker id="prop_dlog_format"></marker>
- <tag>{disk_log_format, internal | external}</tag>
+ <tag><marker id="prop_dlog_format"></marker>{disk_log_format, internal | external}</tag>
<item>
<p>Defines the file format of the log files. See <c>disk_log</c> for
details. If the internal file format is used, the
@@ -668,16 +624,14 @@ text/plain asc txt</pre>
<c>external</c>.</p>
</item>
- <marker id="prop_edlog"></marker>
- <tag>{error_disk_log, path()}</tag>
+ <tag><marker id="prop_edlog"></marker>{error_disk_log, path()}</tag>
<item>
<p>Defines the filename of the (<c>disk_log(3)</c>) error log file
to be used to log server errors. If the filename does not begin
with a slash (/), it is assumed to be relative to the <c>server_root</c>.</p>
</item>
- <marker id="prop_edlog_size"></marker>
- <tag>{error_disk_log_size, {MaxBytes, MaxFiles}}</tag>
+ <tag><marker id="prop_edlog_size"></marker>{error_disk_log_size, {MaxBytes, MaxFiles}}</tag>
<item>
<p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>.
Defines the properties of the (<c>disk_log(3)</c>) error log
@@ -686,8 +640,7 @@ text/plain asc txt</pre>
used before the first file is truncated and reused.</p>
</item>
- <marker id="prop_sdlog"></marker>
- <tag>{security_disk_log, path()}</tag>
+ <tag><marker id="prop_sdlog"></marker>{security_disk_log, path()}</tag>
<item>
<p>Defines the filename of the (<c>disk_log(3)</c>) access log file
logging incoming security events, that is, authenticated
@@ -695,8 +648,7 @@ text/plain asc txt</pre>
is assumed to be relative to the <c>server_root</c>.</p>
</item>
- <marker id="prop_sdlog_size"></marker>
- <tag>{security_disk_log_size, {MaxBytes, MaxFiles}}</tag>
+ <tag><marker id="prop_sdlog_size"></marker>{security_disk_log_size, {MaxBytes, MaxFiles}}</tag>
<item>
<p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>.
Defines the properties of the <c>disk_log(3)</c> access log
@@ -705,8 +657,7 @@ text/plain asc txt</pre>
used before the first file is truncated and reused.</p>
</item>
- <marker id="prop_tdlog"></marker>
- <tag>{transfer_disk_log, path()}</tag>
+ <tag><marker id="prop_tdlog"></marker>{transfer_disk_log, path()}</tag>
<item>
<p>Defines the filename of the (<c>disk_log(3)</c>) access log file
logging incoming requests. If the filename does not begin
@@ -714,8 +665,7 @@ text/plain asc txt</pre>
<c>server_root</c>.</p>
</item>
- <marker id="prop_tdlog_size"></marker>
- <tag>{transfer_disk_log_size, {MaxBytes, MaxFiles}}</tag>
+ <tag><marker id="prop_tdlog_size"></marker>{transfer_disk_log_size, {MaxBytes, MaxFiles}}</tag>
<item>
<p><c>MaxBytes = integer()</c> and <c>MaxFiles = integer()</c>.
Defines the properties of the <c>disk_log(3)</c> access log
@@ -735,32 +685,29 @@ text/plain asc txt</pre>
<p>The properties for directories are as follows:</p>
<taglist>
- <marker id="prop_allow_from"></marker>
- <tag>{allow_from, all | [RegxpHostString]}</tag>
+ <tag><marker id="prop_allow_from"></marker>{allow_from, all | [RegxpHostString]}</tag>
<item>
<p>Defines a set of hosts to be granted access to a
- given directory, for example:
+ given directory, for example:</p>
<code>{allow_from, ["123.34.56.11", "150.100.23"]}</code>
- The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c>
+ <p>The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c>
subnet are allowed access.</p>
</item>
- <marker id="prop_deny_from"></marker>
- <tag>{deny_from, all | [RegxpHostString]}</tag>
+ <tag><marker id="prop_deny_from"></marker>{deny_from, all | [RegxpHostString]}</tag>
<item>
<p>Defines a set of hosts
- to be denied access to a given directory, for example:
+ to be denied access to a given directory, for example:</p>
<code>{deny_from, ["123.34.56.11", "150.100.23"]}</code>
- The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c>
+ <p>The host <c>123.34.56.11</c> and all machines on the <c>150.100.23</c>
subnet are not allowed access.</p>
</item>
- <marker id="prop_auth_type"></marker>
- <tag>{auth_type, plain | dets | mnesia}</tag>
+ <tag><marker id="prop_auth_type"></marker>{auth_type, plain | dets | mnesia}</tag>
<item>
<p>Sets the type of authentication database that is used for the
directory. The key difference between the different methods is
@@ -770,8 +717,7 @@ text/plain asc txt</pre>
configuration files.</p>
</item>
- <marker id="prop_auth_user_file"></marker>
- <tag>{auth_user_file, path()}</tag>
+ <tag><marker id="prop_auth_user_file"></marker>{auth_user_file, path()}</tag>
<item>
<p>Sets the name of a file containing the list of users and
passwords for user authentication. The filename can be either
@@ -795,8 +741,7 @@ text/plain asc txt</pre>
clients can download it.</p>
</item>
- <marker id="prop_auth_group_file"></marker>
- <tag>{auth_group_file, path()}</tag>
+ <tag><marker id="prop_auth_group_file"></marker>{auth_group_file, path()}</tag>
<item>
<p>Sets the name of a file containing the list of user
groups for user authentication. The filename can be either
@@ -818,16 +763,14 @@ text/plain asc txt</pre>
can download it.</p>
</item>
- <marker id="prop_auth_name"></marker>
- <tag>{auth_name, string()}</tag>
+ <tag><marker id="prop_auth_name"></marker>{auth_name, string()}</tag>
<item>
<p>Sets the name of the authorization realm (auth-domain) for
a directory. This string informs the client about which
username and password to use.</p>
</item>
- <marker id="prop_auth_access_passwd"></marker>
- <tag>{auth_access_password, string()}</tag>
+ <tag><marker id="prop_auth_access_passwd"></marker>{auth_access_password, string()}</tag>
<item>
<p>If set to other than "NoPassword", the password is required
for all API calls. If the password is set to "DummyPassword", the
@@ -837,15 +780,13 @@ text/plain asc txt</pre>
text in the configuration file.</p>
</item>
- <marker id="prop_req_user"></marker>
- <tag>{require_user, [string()]}</tag>
+ <tag><marker id="prop_req_user"></marker>{require_user, [string()]}</tag>
<item>
<p>Defines users to grant access to a given
directory using a secret password.</p>
</item>
- <marker id="prop_req_grp"></marker>
- <tag>{require_group, [string()]}</tag>
+ <tag><marker id="prop_req_grp"></marker>{require_group, [string()]}</tag>
<item>
<p>Defines users to grant access to a given
directory using a secret password.</p>
@@ -856,8 +797,7 @@ text/plain asc txt</pre>
<marker id="props_htaccess"></marker>
<p><em>Htaccess Authentication Properties - Requires mod_htaccess</em></p>
<taglist>
- <marker id="prop_access_files"></marker>
- <tag>{access_files, [path()]}</tag>
+ <tag><marker id="prop_access_files"></marker>{access_files, [path()]}</tag>
<item>
<p>Specifies the filenames that are used for
access files. When a request comes, every directory in the path
@@ -877,16 +817,14 @@ text/plain asc txt</pre>
<marker id="props_sdir"></marker>
<p>The properties for the security directories are as follows:</p>
<taglist>
- <marker id="prop_data_file"></marker>
- <tag>{data_file, path()}</tag>
+ <tag><marker id="prop_data_file"></marker>{data_file, path()}</tag>
<item>
<p>Name of the security data file. The filename can either be
absolute or relative to the <c>server_root</c>. This file is used to
store persistent data for module <c>mod_security</c>.</p>
</item>
- <marker id="prop_max_retries"></marker>
- <tag>{max_retries, integer()}</tag>
+ <tag><marker id="prop_max_retries"></marker>{max_retries, integer()}</tag>
<item>
<p>Specifies the maximum number of attempts to authenticate a
user before the user is blocked out. If a user
@@ -898,16 +836,14 @@ text/plain asc txt</pre>
Default is <c>3</c>. Can be set to infinity.</p>
</item>
- <marker id="prop_block_time"></marker>
- <tag>{block_time, integer()}</tag>
+ <tag><marker id="prop_block_time"></marker>{block_time, integer()}</tag>
<item>
<p>Specifies the number of minutes a user is blocked. After
this timehas passed, the user automatically regains access.
Default is <c>60</c>.</p>
</item>
- <marker id="prop_fail_exp_time"></marker>
- <tag>{fail_expire_time, integer()}</tag>
+ <tag><marker id="prop_fail_exp_time"></marker>{fail_expire_time, integer()}</tag>
<item>
<p>Specifies the number of minutes a failed user authentication
is remembered. If a user authenticates after this
@@ -916,8 +852,7 @@ text/plain asc txt</pre>
Default is <c>30</c>.</p>
</item>
- <marker id="prop_auth_timeout"></marker>
- <tag>{auth_timeout, integer()}</tag>
+ <tag><marker id="prop_auth_timeout"></marker>{auth_timeout, integer()}</tag>
<item>
Specifies the number of seconds a successful user
authentication is remembered. After this time has passed, the
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 8c4fdfdf70..c98ec1a9dc 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2002</year><year>2014</year>
+ <year>2002</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,7 +33,72 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 6.0.3</title>
+ <section><title>Inets 6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Replace obs-folds with spaces instead of failing</p>
+ <p>
+ Own Id: OTP-13069</p>
+ </item>
+ <item>
+ <p>
+ Add validation fun for URI scheme to http_uri API</p>
+ <p>
+ Own Id: OTP-13071</p>
+ </item>
+ <item>
+ <p>
+ Handle stream bodies as documented.</p>
+ <p>
+ Own Id: OTP-13093</p>
+ </item>
+ <item>
+ <p>
+ Correct error handling of mod_esi generated chunks. Send
+ warning headers in chunk trailers instead of generating
+ an unexpected additional 500 request response, when
+ problems, such as a timeout occurs.</p>
+ <p>
+ Own Id: OTP-13110</p>
+ </item>
+ <item>
+ <p>
+ HTTP client terminates gracefully when an invalid chunked
+ length header is encountered.</p>
+ <p>
+ Own Id: OTP-13117</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Add default for SNI (Server Name Indication) when running
+ https using the inets HTTP-client.</p>
+ <p>
+ Own Id: OTP-12985</p>
+ </item>
+ <item>
+ <p>
+ Be forgiving to chunked sizes that have trailing
+ whitespaces as prior implementation was. Also some legacy
+ embedded devices does actually have trailing whitespaces
+ even though this in not according to the spec.</p>
+ <p>
+ Own Id: OTP-13116</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 6.0.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -1807,23 +1872,21 @@
<item>
<p>[httpd] - Issues with ESI erl_script_timeout. </p>
- <p>
- <list type="bulleted">
- <item>
- <p>The <c>erl_script_timeout</c> config option is ducumented
- as a number of seconds. But when parsing the config, in the
- new format (not a config file), it was handled as if in
- number of milliseconds. </p>
- </item>
- <item>
- <p>When the erl-script-timeout time was exceeded, the server
- incorrectly marked the answer as sent, thereby leaving
- client hanging (with an incomplete answer).
- This has been changed, so that now the socket will be
- closed. </p>
- </item>
- </list>
- </p>
+ <list type="bulleted">
+ <item>
+ <p>The <c>erl_script_timeout</c> config option is ducumented
+ as a number of seconds. But when parsing the config, in the
+ new format (not a config file), it was handled as if in
+ number of milliseconds. </p>
+ </item>
+ <item>
+ <p>When the erl-script-timeout time was exceeded, the server
+ incorrectly marked the answer as sent, thereby leaving
+ client hanging (with an incomplete answer).
+ This has been changed, so that now the socket will be
+ closed. </p>
+ </item>
+ </list>
<p>Own Id: OTP-8509</p>
</item>
</list>
@@ -1899,20 +1962,19 @@
<item>
<p>[httpc] Several more or less critical fixes:</p>
- <p>
- <list type="bulleted">
- <item>
- <p>Initial call between the httpc manager and request
- handler was synchronous. </p>
- <p>When the manager starts a new request handler,
- this is no longer a synchronous operation. Previously,
- the new request handler made the connection to the
- server and issuing of the first request (the reason
- for starting it) in the gen_server init function.
- If the connection for some reason "took some time",
- the manager hanged, leaving all other activities by
- that manager also hanging. </p>
- </item>
+ <list type="bulleted">
+ <item>
+ <p>Initial call between the httpc manager and request
+ handler was synchronous. </p>
+ <p>When the manager starts a new request handler,
+ this is no longer a synchronous operation. Previously,
+ the new request handler made the connection to the
+ server and issuing of the first request (the reason
+ for starting it) in the gen_server init function.
+ If the connection for some reason "took some time",
+ the manager hanged, leaving all other activities by
+ that manager also hanging. </p>
+ </item>
<!--
<item>
<p>Copying of data between processes</p>
@@ -1923,8 +1985,7 @@
<p>TBD</p>
</item>
-->
- </list>
- </p>
+ </list>
<p>As a side-effect of these changes, some modules was also
renamed, and a new api module,
<seealso marker="httpc">httpc</seealso>, has been introduced
diff --git a/lib/inets/doc/src/tftp.xml b/lib/inets/doc/src/tftp.xml
index 00d9d53376..10398f5088 100644
--- a/lib/inets/doc/src/tftp.xml
+++ b/lib/inets/doc/src/tftp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2006</year><year>2013</year>
+ <year>2006</year><year>2015</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -216,12 +216,9 @@
five times when the time-out expires.</p>
</item>
</taglist>
-
- <marker id="start1"></marker>
</section>
<funcs>
- <marker id="change_config_daemons"></marker>
<func>
<name>change_config(daemons, Options) -> [{Pid, Result}]</name>
<fsummary>Changes configuration for all daemons.
@@ -234,8 +231,6 @@
</type>
<desc>
<p>Changes configuration for all TFTP daemon processes. </p>
-
- <marker id="change_config_servers"></marker>
</desc>
</func>
@@ -251,8 +246,6 @@
</type>
<desc>
<p>Changes configuration for all TFTP server processes.</p>
-
- <marker id="change_config_pid"></marker>
</desc>
</func>
@@ -268,7 +261,6 @@
</type>
<desc>
<p>Changes configuration for a TFTP daemon, server, or client process.</p>
- <marker id="info_daemons"></marker>
</desc>
</func>
@@ -282,8 +274,6 @@
</type>
<desc>
<p>Returns information about all TFTP daemon processes.</p>
-
- <marker id="info_servers"></marker>
</desc>
</func>
@@ -297,8 +287,6 @@
</type>
<desc>
<p>Returns information about all TFTP server processes. </p>
-
- <marker id="info_pid"></marker>
</desc>
</func>
@@ -341,9 +329,7 @@
the regexps of these and the callback module corresponding to
the first match is used, or an error tuple is returned if no
matching regexp is found.</p>
- </desc>
-
- <marker id="write_file"></marker>
+ </desc>
</func>
<func>
@@ -359,8 +345,6 @@
port. When it receives a request for read or write, it spawns
a temporary server process handling the actual transfer
of the (virtual) file.</p>
-
- <marker id="read_file"></marker>
</desc>
</func>
@@ -393,7 +377,6 @@
matching regexp is found.</p>
</desc>
</func>
-
</funcs>
<section>
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 1044cffe6f..d1c52dcc78 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -1113,8 +1113,8 @@ handle_http_body(Body, #state{headers = Headers,
case case_insensitive_header(TransferEnc) of
"chunked" ->
?hcrt("handle_http_body - chunked", []),
- case http_chunk:decode(Body, State#state.max_body_size,
- State#state.max_header_size) of
+ try http_chunk:decode(Body, State#state.max_body_size,
+ State#state.max_header_size) of
{Module, Function, Args} ->
?hcrt("handle_http_body - new mfa",
[{module, Module},
@@ -1139,6 +1139,13 @@ handle_http_body(Body, #state{headers = Headers,
handle_response(State#state{headers = NewHeaders,
body = NewBody2})
end
+ catch throw:{error, Reason} ->
+ NewState =
+ answer_request(Request,
+ httpc_response:error(Request,
+ Reason),
+ State),
+ {stop, normal, NewState}
end;
Enc when Enc =:= "identity"; Enc =:= undefined ->
?hcrt("handle_http_body - identity", []),
@@ -1820,11 +1827,13 @@ host_header(_, URI) ->
tls_upgrade(#state{status =
{ssl_tunnel,
#request{settings =
- #http_options{ssl = {_, TLSOptions} = SocketType},
- address = Address} = Request},
+ #http_options{ssl = {_, TLSOptions0} = SocketType},
+ address = {Host, _} = Address} = Request},
session = #session{socket = TCPSocket} = Session0,
options = Options} = State) ->
+ TLSOptions = maybe_add_sni(Host, TLSOptions0),
+
case ssl:connect(TCPSocket, TLSOptions) of
{ok, TLSSocket} ->
ClientClose = httpc_request:is_client_closing(Request#request.headers),
@@ -1855,6 +1864,15 @@ tls_upgrade(#state{status =
{stop, normal, State#state{request = Request}}
end.
+maybe_add_sni(Host, Options) ->
+ case http_util:is_hostname(Host) andalso
+ not lists:keymember(server_name_indication, 1, Options) of
+ true ->
+ [{server_name_indication, Host} | Options];
+ false ->
+ Options
+ end.
+
%% ---------------------------------------------------------------------
%% Session wrappers
%% ---------------------------------------------------------------------
diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl
index 2f8476a49d..7325f24809 100644
--- a/lib/inets/src/http_lib/http_chunk.erl
+++ b/lib/inets/src/http_lib/http_chunk.erl
@@ -25,7 +25,7 @@
-include("http_internal.hrl").
%% API
--export([decode/3, encode/1, encode_last/0, handle_headers/2]).
+-export([decode/3, encode/1, encode_last/0, encode_last/1, handle_headers/2]).
%% Callback API - used for example if the chunkedbody is received a
%% little at a time on a socket.
-export([decode_size/1, ignore_extensions/1, decode_data/1, decode_trailer/1]).
@@ -85,6 +85,11 @@ encode(Chunk) when is_list(Chunk)->
encode_last() ->
<<$0, ?CR, ?LF, ?CR, ?LF >>.
+encode_last([]) ->
+ encode_last();
+encode_last(Trailers0) ->
+ Trailers = list_to_binary(encode_trailers(Trailers0)),
+ <<$0, ?CR, ?LF, Trailers/binary>>.
%%-------------------------------------------------------------------------
%% handle_headers(HeaderRecord, ChunkedHeaders) -> NewHeaderRecord
@@ -147,7 +152,7 @@ decode_size(Data = <<?CR, ?LF, ChunkRest/binary>>, HexList, AccHeaderSize,
{MaxBodySize, Body,
AccLength,
MaxHeaderSize}) ->
- try http_util:hexlist_to_integer(lists:reverse(HexList)) of
+ try http_util:hexlist_to_integer(lists:reverse(string:strip(HexList, left))) of
0 -> % Last chunk, there was no data
ignore_extensions(Data, remaing_size(MaxHeaderSize, AccHeaderSize), MaxHeaderSize,
{?MODULE, decode_trailer,
@@ -276,10 +281,18 @@ decode_trailer(<<?CR, ?LF, Rest/binary>>, Header, Headers, Body, BodyLength, Rem
Body, BodyLength, RemainingSize, TotalMaxHeaderSize);
decode_trailer(<<Octet, Rest/binary>>, Header, Headers, Body,
BodyLength, RemainingSize, TotalMaxHeaderSize) ->
- decode_trailer(Rest, [Octet | Header], Headers,
- Body, BodyLength, RemainingSize - 1, TotalMaxHeaderSize).
+ decode_trailer(Rest, [Octet | Header], Headers,
+ Body, BodyLength, remaing_size(RemainingSize, 1), TotalMaxHeaderSize).
remaing_size(nolimit, _) ->
nolimit;
remaing_size(Total, Consumed) ->
Total - Consumed.
+
+encode_trailers(Trailers) ->
+ encode_trailers(Trailers, "").
+
+encode_trailers([], Acc) ->
+ Acc ++ ?CRLF ++ ?CRLF;
+encode_trailers([{Header, Value} | Rest], Acc) ->
+ encode_trailers(Rest, Header ++ ":" ++ Value ++ ?CRLF ++ Acc).
diff --git a/lib/inets/src/http_lib/http_response.erl b/lib/inets/src/http_lib/http_response.erl
index d13670700c..42e5dd263d 100644
--- a/lib/inets/src/http_lib/http_response.erl
+++ b/lib/inets/src/http_lib/http_response.erl
@@ -65,6 +65,8 @@ header_list(Headers) ->
%%%========================================================================
fill_headers([], _, Headers) ->
Headers;
+fill_headers([[]], _, Headers) ->
+ Headers;
fill_headers([[Ch|HeaderFold]|Tail], Folded, Headers)
when Ch == $\t; Ch == $\s ->
fill_headers(Tail, [HeaderFold|Folded], Headers);
diff --git a/lib/inets/src/http_server/Makefile b/lib/inets/src/http_server/Makefile
index b9f2290289..1c05d454a5 100644
--- a/lib/inets/src/http_server/Makefile
+++ b/lib/inets/src/http_server/Makefile
@@ -137,7 +137,7 @@ release_spec: opt
$(INSTALL_DIR) "$(RELSYSDIR)/src/http_server"
$(INSTALL_DATA) $(HRL_FILES) $(ERL_FILES) "$(RELSYSDIR)/src/http_server"
$(INSTALL_DIR) "$(RELSYSDIR)/ebin"
- $(INSTALL_DATA) $(TARGET_FILES) "$(RELSYSDIR)/ebin"
+ $(INSTALL_DATA) $(TARGET_FILES) $(BEHAVIOUR_TARGET_FILES) "$(RELSYSDIR)/ebin"
release_docs_spec:
diff --git a/lib/inets/src/http_server/httpd_custom_api.erl b/lib/inets/src/http_server/httpd_custom_api.erl
index 282f3a6ee6..d5a6fa8715 100644
--- a/lib/inets/src/http_server/httpd_custom_api.erl
+++ b/lib/inets/src/http_server/httpd_custom_api.erl
@@ -23,7 +23,8 @@
-callback response_default_headers() ->
[{Key::string(), Value::string()}].
-callback response_header({Key::string(), Value::string()}) ->
- {true, {Key::string(), Value::string()}} | false.
+ {true, {Key::string(), Value::string()}} | false |
+ {true, string()}. %% Used internally to avoid traversing headers twice
-callback request_header({Key::string(), Value::string()}) ->
{true, {Key::string(), Value::string()}} | false.
diff --git a/lib/inets/src/http_server/httpd_example.erl b/lib/inets/src/http_server/httpd_example.erl
index d729affd6d..0222487a4b 100644
--- a/lib/inets/src/http_server/httpd_example.erl
+++ b/lib/inets/src/http_server/httpd_example.erl
@@ -24,7 +24,7 @@
-export([newformat/3]).
%% These are used by the inets test-suite
--export([delay/1]).
+-export([delay/1, chunk_timeout/3]).
print(String) ->
@@ -142,3 +142,11 @@ i(F) -> i(F,[]).
i(F,A) -> io:format(F ++ "~n",A).
sleep(T) -> receive after T -> ok end.
+
+%% ------------------------------------------------------
+
+chunk_timeout(SessionID, _, StrInt) ->
+ mod_esi:deliver(SessionID, "Tranfer-Encoding:chunked/html\r\n\r\n"),
+ mod_esi:deliver(SessionID, top("Test chunk encoding timeout")),
+ timer:sleep(20000),
+ mod_esi:deliver(SessionID, footer()).
diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl
index 143d599edb..134576059d 100644
--- a/lib/inets/src/http_server/httpd_request_handler.erl
+++ b/lib/inets/src/http_server/httpd_request_handler.erl
@@ -630,21 +630,10 @@ decrease(N) when is_integer(N) ->
decrease(N) ->
N.
-error_log(ReasonString, Info) ->
+error_log(ReasonString, #mod{config_db = ConfigDB}) ->
Error = lists:flatten(
io_lib:format("Error reading request: ~s", [ReasonString])),
- error_log(mod_log, Info, Error),
- error_log(mod_disk_log, Info, Error).
-
-error_log(Mod, #mod{config_db = ConfigDB} = Info, String) ->
- Modules = httpd_util:lookup(ConfigDB, modules,
- [mod_get, mod_head, mod_log]),
- case lists:member(Mod, Modules) of
- true ->
- Mod:error_log(Info, String);
- _ ->
- ok
- end.
+ httpd_util:error_log(ConfigDB, Error).
%%--------------------------------------------------------------------
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index 71243f525a..c0b5f09faf 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.erl
@@ -20,8 +20,8 @@
%%
-module(httpd_response).
-export([generate_and_send_response/1, send_status/3, send_header/3,
- send_body/3, send_chunk/3, send_final_chunk/2, split_header/2,
- is_disable_chunked_send/1, cache_headers/2]).
+ send_body/3, send_chunk/3, send_final_chunk/2, send_final_chunk/3,
+ split_header/2, is_disable_chunked_send/1, cache_headers/2]).
-export([map_status_code/2]).
-include_lib("inets/src/inets_app/inets_internal.hrl").
@@ -89,8 +89,7 @@ traverse_modules(ModData,[Module|Rest]) ->
"~n Error: ~p"
"~n Stack trace: ~p",
[Module, T, E, ?STACK()])),
- report_error(mod_log, ModData#mod.config_db, String),
- report_error(mod_disk_log, ModData#mod.config_db, String),
+ httpd_util:error_log(ModData#mod.config_db, String),
send_status(ModData, 500, none),
done
end.
@@ -245,7 +244,6 @@ send_chunk(_, <<>>, _) ->
ok;
send_chunk(_, [], _) ->
ok;
-
send_chunk(#mod{http_version = "HTTP/1.1",
socket_type = Type, socket = Sock}, Response0, false) ->
Response = http_chunk:encode(Response0),
@@ -254,10 +252,13 @@ send_chunk(#mod{http_version = "HTTP/1.1",
send_chunk(#mod{socket_type = Type, socket = Sock} = _ModData, Response, _) ->
httpd_socket:deliver(Type, Sock, Response).
+send_final_chunk(Mod, IsDisableChunkedSend) ->
+ send_final_chunk(Mod, [], IsDisableChunkedSend).
+
send_final_chunk(#mod{http_version = "HTTP/1.1",
- socket_type = Type, socket = Sock}, false) ->
- httpd_socket:deliver(Type, Sock, http_chunk:encode_last());
-send_final_chunk(#mod{socket_type = Type, socket = Sock}, _) ->
+ socket_type = Type, socket = Sock}, Trailers, false) ->
+ httpd_socket:deliver(Type, Sock, http_chunk:encode_last(Trailers));
+send_final_chunk(#mod{socket_type = Type, socket = Sock}, _, _) ->
httpd_socket:close(Type, Sock).
is_disable_chunked_send(Db) ->
@@ -397,16 +398,6 @@ send_response_old(#mod{socket_type = Type,
content_length(Body)->
integer_to_list(httpd_util:flatlength(Body)).
-report_error(Mod, ConfigDB, Error) ->
- Modules = httpd_util:lookup(ConfigDB, modules,
- [mod_get, mod_head, mod_log]),
- case lists:member(Mod, Modules) of
- true ->
- Mod:report_error(ConfigDB, Error);
- _ ->
- ok
- end.
-
handle_headers([], NewHeaders) ->
{ok, NewHeaders};
diff --git a/lib/inets/src/http_server/httpd_util.erl b/lib/inets/src/http_server/httpd_util.erl
index 0387d71911..ab43f0b378 100644
--- a/lib/inets/src/http_server/httpd_util.erl
+++ b/lib/inets/src/http_server/httpd_util.erl
@@ -31,7 +31,7 @@
convert_netscapecookie_date/1, enable_debug/1, valid_options/3,
modules_validate/1, module_validate/1,
dir_validate/2, file_validate/2, mime_type_validate/1,
- mime_types_validate/1, custom_date/0]).
+ mime_types_validate/1, custom_date/0, error_log/2]).
-export([encode_hex/1, decode_hex/1]).
-include_lib("kernel/include/file.hrl").
@@ -776,3 +776,17 @@ do_enable_debug([{Level,Modules}|Rest])
ok
end,
do_enable_debug(Rest).
+
+error_log(ConfigDb, Error) ->
+ error_log(mod_log, ConfigDb, Error),
+ error_log(mod_disk_log, ConfigDb, Error).
+
+error_log(Mod, ConfigDB, Error) ->
+ Modules = httpd_util:lookup(ConfigDB, modules,
+ [mod_get, mod_head, mod_log]),
+ case lists:member(Mod, Modules) of
+ true ->
+ Mod:report_error(ConfigDB, Error);
+ _ ->
+ ok
+ end.
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index b9a0797977..1923411449 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -376,7 +376,6 @@ erl_scheme_webpage_chunk(Mod, Func, Env, Input, ModData) ->
end),
Response = deliver_webpage_chunk(ModData, Pid),
-
process_flag(trap_exit,false),
Response.
@@ -418,7 +417,6 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
?hdrv("deliver_webpage_chunk - timeout", []),
send_headers(ModData, 504, [{"connection", "close"}]),
httpd_socket:close(ModData#mod.socket_type, ModData#mod.socket),
- process_flag(trap_exit,false),
{proceed,[{response, {already_sent, 200, 0}} | ModData#mod.data]}
end.
@@ -446,7 +444,6 @@ send_headers(ModData, StatusCode, HTTPHeaders) ->
ExtraHeaders ++ HTTPHeaders).
handle_body(_, #mod{method = "HEAD"} = ModData, _, _, Size, _) ->
- process_flag(trap_exit,false),
{proceed, [{response, {already_sent, 200, Size}} | ModData#mod.data]};
handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) ->
@@ -454,34 +451,54 @@ handle_body(Pid, ModData, Body, Timeout, Size, IsDisableChunkedSend) ->
httpd_response:send_chunk(ModData, Body, IsDisableChunkedSend),
receive
{esi_data, Data} when is_binary(Data) ->
- ?hdrt("handle_body - received binary data (esi)", []),
handle_body(Pid, ModData, Data, Timeout, Size + byte_size(Data),
IsDisableChunkedSend);
{esi_data, Data} ->
- ?hdrt("handle_body - received data (esi)", []),
handle_body(Pid, ModData, Data, Timeout, Size + length(Data),
IsDisableChunkedSend);
{ok, Data} ->
- ?hdrt("handle_body - received data (ok)", []),
handle_body(Pid, ModData, Data, Timeout, Size + length(Data),
IsDisableChunkedSend);
{'EXIT', Pid, normal} when is_pid(Pid) ->
- ?hdrt("handle_body - exit:normal", []),
httpd_response:send_final_chunk(ModData, IsDisableChunkedSend),
{proceed, [{response, {already_sent, 200, Size}} |
ModData#mod.data]};
{'EXIT', Pid, Reason} when is_pid(Pid) ->
- ?hdrv("handle_body - exit", [{reason, Reason}]),
- httpd_response:send_final_chunk(ModData, IsDisableChunkedSend),
- exit({mod_esi_linked_process_died, Pid, Reason})
-
+ Error = lists:flatten(io_lib:format("mod_esi process failed with reason ~p", [Reason])),
+ httpd_util:error_log(ModData#mod.config_db, Error),
+ httpd_response:send_final_chunk(ModData,
+ [{"Warning", "199 inets server - body maybe incomplete, "
+ "internal server error"}],
+ IsDisableChunkedSend),
+ done
after Timeout ->
- ?hdrv("handle_body - timeout", []),
- process_flag(trap_exit,false),
- httpd_response:send_final_chunk(ModData, IsDisableChunkedSend),
- exit({mod_esi_linked_process_timeout, Pid})
+ kill_esi_delivery_process(Pid),
+ httpd_response:send_final_chunk(ModData, [{"Warning", "199 inets server - "
+ "body maybe incomplete, timed out"}],
+ IsDisableChunkedSend),
+ done
end.
+kill_esi_delivery_process(Pid) ->
+ exit(Pid, kill),
+ receive
+ {'EXIT', Pid, killed} ->
+ %% Clean message queue
+ receive
+ {esi_data, _} ->
+ ok
+ after 0 ->
+ ok
+ end,
+ receive
+ {ok, _} ->
+ ok
+ after 0 ->
+ ok
+ end
+ end.
+
+
erl_script_timeout(Db) ->
httpd_util:lookup(Db, erl_script_timeout, ?DEFAULT_ERL_TIMEOUT).
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index 2b9b8f5f32..883ba84e8e 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -65,6 +65,7 @@
httpd_connection_sup,
httpd_conf,
httpd_custom,
+ httpd_custom_api,
httpd_esi,
httpd_example,
httpd_file,
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl
index a927adc75e..e977bd1b9b 100644
--- a/lib/inets/test/http_format_SUITE.erl
+++ b/lib/inets/test/http_format_SUITE.erl
@@ -38,6 +38,7 @@ groups() ->
[chunk_decode, chunk_encode, chunk_extensions_otp_6005,
chunk_decode_otp_6264,
chunk_decode_empty_chunk_otp_6511,
+ chunk_whitespace_suffix,
chunk_decode_trailer, chunk_max_headersize, chunk_max_bodysize, chunk_not_hex]}].
init_per_suite(Config) ->
@@ -157,6 +158,21 @@ chunk_decode_empty_chunk_otp_6511(Config) when is_list(Config) ->
?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE).
%%-------------------------------------------------------------------------
+chunk_whitespace_suffix() ->
+ [{doc, "Test whitespace after chunked length header"}].
+chunk_whitespace_suffix(Config) when is_list(Config) ->
+ ChunkedBody = "1a ; ignore-stuff-here" ++ ?CRLF ++
+ "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10 " ++ ?CRLF
+ ++ "1234567890abcdef" ++ ?CRLF ++ "0 " ++ ?CRLF
+ ++ "some-footer:some-value" ++ ?CRLF
+ ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF,
+ {ok, {["content-length:42", "another-footer:another-value",
+ "some-footer:some-value", ""],
+ <<"abcdefghijklmnopqrstuvwxyz1234567890abcdef">>}} =
+ http_chunk:decode(list_to_binary(ChunkedBody),
+ ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE).
+
+%%-------------------------------------------------------------------------
chunk_decode_trailer() ->
[{doc,"Make sure trailers are handled correctly. Trailers should"
"become new headers"}].
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 989563cdbc..c6c59ab1af 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -106,6 +106,7 @@ only_simulated() ->
bad_response,
internal_server_error,
invalid_http,
+ invalid_chunk_size,
headers_dummy,
headers_with_obs_fold,
empty_response_header,
@@ -765,6 +766,22 @@ invalid_http(Config) when is_list(Config) ->
ct:print("Parse error: ~p ~n", [Reason]).
%%-------------------------------------------------------------------------
+
+invalid_chunk_size(doc) ->
+ ["Test parse error of HTTP chunk size"];
+invalid_chunk_size(suite) ->
+ [];
+invalid_chunk_size(Config) when is_list(Config) ->
+
+ URL = url(group_name(Config), "/invalid_chunk_size.html", Config),
+
+ {error, {chunk_size, _} = Reason} =
+ httpc:request(get, {URL, []}, [], []),
+
+ ct:print("Parse error: ~p ~n", [Reason]).
+
+%%-------------------------------------------------------------------------
+
emulate_lower_versions(doc) ->
[{doc, "Perform request as 0.9 and 1.0 clients."}];
emulate_lower_versions(Config) when is_list(Config) ->
@@ -1876,6 +1893,10 @@ handle_uri(_,"/invalid_http.html",_,_,_,_) ->
"HTTP/1.1 301\r\nDate:Sun, 09 Dec 2007 13:04:18 GMT\r\n" ++
"Transfer-Encoding:chunked\r\n\r\n";
+handle_uri(_,"/invalid_chunk_size.html",_,_,_,_) ->
+ "HTTP/1.1 200 ok\r\n" ++
+ "Transfer-Encoding:chunked\r\n\r\nåäö\r\n";
+
handle_uri(_,"/missing_reason_phrase.html",_,_,_,_) ->
"HTTP/1.1 200\r\n" ++
"Content-Length: 32\r\n\r\n"
diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl
index dd9d21bbfc..db6def9d17 100644
--- a/lib/inets/test/httpd_1_1.erl
+++ b/lib/inets/test/httpd_1_1.erl
@@ -24,7 +24,7 @@
-include_lib("kernel/include/file.hrl").
-export([host/4, chunked/4, expect/4, range/4, if_test/5, trace/4,
- head/4, mod_cgi_chunked_encoding_test/5]).
+ head/4, mod_cgi_chunked_encoding_test/5, mod_esi_chunk_timeout/4]).
%% -define(all_keys_lower_case,true).
-ifndef(all_keys_lower_case).
@@ -274,6 +274,15 @@ mod_cgi_chunked_encoding_test(Type, Port, Host, Node, [Request| Rest])->
[{statuscode, 200}]),
mod_cgi_chunked_encoding_test(Type, Port, Host, Node, Rest).
+
+mod_esi_chunk_timeout(Type, Port, Host, Node) ->
+ ok = httpd_test_lib:verify_request(Type, Host, Port, Node,
+ "GET /cgi-bin/erl/httpd_example/chunk_timeout?input=20000 HTTP/1.1\r\n"
+ "Host:"++ Host ++"\r\n"
+ "\r\n",
+ [{statuscode, 200},
+ {header, "warning"}]).
+
%%--------------------------------------------------------------------
%% Internal functions
%%--------------------------------------------------------------------
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index 9bd6f3636c..1d8a603981 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -117,7 +117,7 @@ groups() ->
{htaccess, [], [htaccess_1_1, htaccess_1_0, htaccess_0_9]},
{security, [], [security_1_1, security_1_0]}, %% Skip 0.9 as causes timing issus in test code
{http_1_1, [], [host, chunked, expect, cgi, cgi_chunked_encoding_test,
- trace, range, if_modified_since] ++ http_head() ++ http_get() ++ load()},
+ trace, range, if_modified_since, mod_esi_chunk_timeout] ++ http_head() ++ http_get() ++ load()},
{http_1_0, [], [host, cgi, trace] ++ http_head() ++ http_get() ++ load()},
{http_0_9, [], http_head() ++ http_get() ++ load()}
].
@@ -757,6 +757,13 @@ esi(Config) when is_list(Config) ->
Config, [{statuscode, 200},
{no_header, "cache-control"}]).
%%-------------------------------------------------------------------------
+mod_esi_chunk_timeout(Config) when is_list(Config) ->
+ ok = httpd_1_1:mod_esi_chunk_timeout(?config(type, Config),
+ ?config(port, Config),
+ ?config(host, Config),
+ ?config(node, Config)).
+
+%%-------------------------------------------------------------------------
cgi() ->
[{doc, "Test mod_cgi"}].
diff --git a/lib/inets/test/httpd_SUITE_data/Makefile.src b/lib/inets/test/httpd_SUITE_data/Makefile.src
index b0fdb43d8d..cea40dd8cb 100644
--- a/lib/inets/test/httpd_SUITE_data/Makefile.src
+++ b/lib/inets/test/httpd_SUITE_data/Makefile.src
@@ -10,5 +10,10 @@ all: $(PROGS)
cgi_echo@exe@: cgi_echo@obj@
$(LD) $(CROSSLDFLAGS) -o cgi_echo cgi_echo@obj@ @LIBS@
+@IFEQ@ (@CC@, cl -nologo)
+cgi_echo@obj@: cgi_echo.c
+ $(CC) /c /Focgi_echo@obj@ $(CFLAGS) cgi_echo.c
+@ELSE@
cgi_echo@obj@: cgi_echo.c
$(CC) -c -o cgi_echo@obj@ $(CFLAGS) cgi_echo.c
+@ENDIF@
diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl
index a5b836f651..c58966ce10 100644
--- a/lib/inets/test/httpd_test_lib.erl
+++ b/lib/inets/test/httpd_test_lib.erl
@@ -235,11 +235,17 @@ validate(RequestStr, #state{status_line = {Version, StatusCode, _},
_ ->
ok
end,
- do_validate(http_response:header_list(Headers), Options, N, P),
- check_body(RequestStr, StatusCode,
- Headers#http_response_h.'content-type',
- list_to_integer(Headers#http_response_h.'content-length'),
- Body).
+ HList = http_response:header_list(Headers),
+ do_validate(HList, Options, N, P),
+ case lists:keysearch("warning", 1, HList) of
+ {value, _} ->
+ ok;
+ _ ->
+ check_body(RequestStr, StatusCode,
+ Headers#http_response_h.'content-type',
+ list_to_integer(Headers#http_response_h.'content-length'),
+ Body)
+ end.
%--------------------------------------------------------------------
%% Internal functions
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index 7cc95fa6d3..2717f5b110 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 6.0.3
+INETS_VSN = 6.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"