An HTTP/1.1 client
This module provides the API to an HTTP/1.1 compatible client according
to
Note!
When starting the Inets
application, a manager process for the
default profile is started. The functions in this API
that do not explicitly use a profile accesses the
default profile. A profile keeps track of proxy options,
cookies, and other options that can be applied to more than one
request.
If the scheme https
is used, the SSL
application must
be started. When https
links need to go through a proxy, the
CONNECT method extension to HTTP-1.1 is used to establish a
tunnel and then the connection is upgraded to TLS.
However, "TLS upgrade" according to
Pipelining is only used if the pipeline time-out is set, otherwise persistent connections without pipelining are used. That is, the client always waits for the previous response before sending the next request.
Some examples are provided in the Inets User's Guide.
DATA TYPES
Type definitions that are used more than once in this module:
boolean() = true | false
string()
= list of ASCII characters
request_id() = reference()
profile() = atom()
path() = string()
representing a file path or directory path
ip_address()
= See the
inet(3) manual page in Kernel.
socket_opt()
= See the options used by
gen_tcp(3) gen_tcp(3)
and
ssl(3) connect(s)
HTTP DATA TYPES
Type definitions related to HTTP:
method() = head | get | put | post | trace | options | delete | patch
request()
= {url(), headers()}
| {url(), headers(), content_type(), body()}
url() = string()
syntax according to the URI definition in
"http://www.erlang.org"
status_line() = {http_version(), status_code(), reason_phrase()}
http_version() = string()
, for example, "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()
For more information about HTTP, see
SSL DATA TYPES
See ssl(3) for information
about SSL
options (ssloptions()
).
HTTP CLIENT SERVICE START/STOP
An HTTP client can be configured to start when starting the Inets
application or started dynamically in runtime by calling the
Inets
application API inets:start(httpc, ServiceConfig)
or inets:start(httpc, ServiceConfig, How)
,
see inets(3).
The configuration options are as follows:
Name of the profile, see DATA TYPES. This option is mandatory.
Directory where the profile can save persistent data. If omitted, all cookies are treated as session cookies.
The client can be stopped using inets:stop(httpc, Pid)
or
inets:stop(httpc, Profile)
.
Functions
RequestId = request_id() - A unique identifier as returned by request/4
Profile = profile() | pid()
stand_alone
only the pid can be used.Cancels an asynchronous HTTP request. Notice that this does not guarantee that the request response is not delivered. Because it is asynchronous, the request can already have been completed when the cancellation arrives.
Url = url()
Opts = [cookie_header_opt()]
Profile = profile() | pid()
cookie_header_opt() = {ipv6_host_with_brackets, boolean()}
stand_alone
.Returns the cookie header that would have been sent
when making a request to Url
using profile Profile
.
If no profile is specified, the default profile is used.
Option ipv6_host_with_bracket
deals with how to
parse IPv6 addresses. For details,
see argument Options
of
request/[4,5].
OptionItems = all | [option_item()]
option_item() = proxy | https_proxy | max_sessions | keep_alive_timeout | max_keep_alive_length | pipeline_timeout | max_pipeline_length | cookies | ipfamily | ip | port | socket_opts | verbose | unix_socket
Profile = profile() | pid()
Values = [{option_item(), term()}]
Reason = term()
stand_alone
only the pid can used.Retrieves the options currently used by the client.
Profile = profile() | pid()
stand_alone
only the pid can be used.Produces a list of miscellaneous information. Intended for debugging. If no profile is specified, the default profile is used.
Profile = profile() | pid()
stand_alone
only the pid can be used.Resets (clears) the cookie database for the specified
Profile
. If no profile is specified the default profile
is used.
Url = url()
Result = {status_line(), headers(), Body} | {status_code(), Body} | request_id()
Body = string() | binary()
Profile = profile() | pid()
Reason = term()
stand_alone
only the pid can be used.Equivalent to httpc:request(get, {Url, []}, [], [])
.
Method = method()
Request = request()
HTTPOptions = http_options()
http_options() = [http_option()]
http_option() = {timeout, timeout()} | {connect_timeout, timeout()} | {ssl, ssloptions()} | {essl, ssloptions()} | {autoredirect, boolean()} | {proxy_auth, {userstring(), passwordstring()}} | {version, http_version()} | {relaxed, boolean()}
timeout() = integer() >= 0 | infinity
Options = options()
options() = [option()]
option() = {sync, boolean()} | {stream, stream_to()} | {body_format, body_format()} | {full_result, boolean()} | {headers_as_is, boolean() | {socket_opts, socket_opts()} | {receiver, receiver()} | {ipv6_host_with_brackets, boolean()}
stream_to() = none | self | {self, once} | filename()
socket_opts() = [socket_opt()]
receiver() = pid() | function()/1 | {Module, Function, Args}
Module = atom()
Function = atom()
Args = list()
body_format() = string | binary
Result = {status_line(), headers(), Body} | {status_code(), Body} | request_id()
Body = string() | binary()
Profile = profile() | pid()
Reason = term()
stand_alone
only the pid can be used.Sends an HTTP request. The function can be both synchronous
and asynchronous. In the latter case, the function returns
{ok, RequestId}
and then the information is delivered
to the receiver
depending on that value.
HTTP option (http_option()
) details:
timeout
Time-out time for the request.
The clock starts ticking when the request is sent.
Time is in milliseconds.
Default is infinity
.
connect_timeout
Connection time-out time, used during the initial request, when the client is connecting to the server.
Time is in milliseconds.
Default is the value of option timeout
.
ssl
This is the SSL/TLS
connectin configuration option.
Defaults to []
. See ssl:connect/[2,3,4] for available options.
autoredirect
The client automatically retrieves the information from the new URI and returns that as the result, instead of a 30X-result code.
For some 30X-result codes, automatic redirect is not allowed. In these cases the 30X-result is always returned.
Default is true
.
proxy_auth
A proxy-authorization header using the provided username and password is added to the request.
version
Can be used to make the client act as an HTTP/1.0
or
HTTP/0.9
client. By default this is an HTTP/1.1
client. When using HTTP/1.0
persistent connections are
not used.
Default is the string "HTTP/1.1"
.
relaxed
If set to true
, workarounds for known server deviations
from the HTTP-standard are enabled.
Default is false
.
Option (option()
) details:
sync
Option for the request to be synchronous or asynchronous.
Default is true
.
stream
Streams the body of a 200 or 206 response to the calling
process or to a file. When streaming to the calling process
using option self
, the following stream messages
are sent to that process: {http, {RequestId,
stream_start, Headers}}, {http, {RequestId, stream,
BinBodyPart}}, and {http, {RequestId, stream_end, Headers}}
.
When streaming to the calling processes using option
{self, once}
, the first message has an extra
element, that is, {http, {RequestId, stream_start, Headers, Pid}}
.
This is the process id to be used as an argument to
httpc:stream_next/1
to trigger the next message to be sent to
the calling process.
Notice that chunked encoding can add
headers so that there are more headers in the stream_end
message than in stream_start
.
When streaming to a file and the request is asynchronous, the
message {http, {RequestId, saved_to_file}}
is sent.
Default is none
.
body_format
Defines if the body is to be delivered as a string or binary. This option is only valid for the synchronous request.
Default is string
.
full_result
Defines if a "full result" is to be returned to the caller (that is, the body, the headers, and the entire status line) or not (the body and the status code).
Default is true
.
headers_as_is
Defines if the headers provided by the user are to be made lower case or to be regarded as case sensitive.
The HTTP standard requires them to be case insensitive. Use this feature only if there is no other way to communicate with the server or for testing purpose. When this option is used, no headers are automatically added. All necessary headers must be provided by the user.
Default is false
.
socket_opts
Socket options to be used for this request.
Overrides any value set by function set_options.
The validity of the options is not checked by the HTTP client they are assumed to be correct and passed on to ssl application and inet driver, which may reject them if they are not correct.
Note!
Persistent connections are not supported when setting the
socket_opts
option. When socket_opts
is not
set the current implementation assumes the requests to the
same host, port combination will use the same socket options.
By default the socket options set by function set_options/[1,2] are used when establishing a connection.
receiver
Defines how the client delivers the result of an
asynchronous request (sync
has the value
false
).
pid()
Messages are sent to this process in the format
{http, ReplyInfo}
.
function/1
Information is delivered to the receiver through calls
to the provided fun Receiver(ReplyInfo)
.
{Module, Function, Args}
Information is delivered to the receiver through calls
to the callback function
apply(Module, Function, [ReplyInfo | Args])
.
In all of these cases, ReplyInfo
has the following
structure:
{RequestId, saved_to_file} {RequestId, {error, Reason}} {RequestId, Result} {RequestId, stream_start, Headers} {RequestId, stream_start, Headers, HandlerPid} {RequestId, stream, BinBodyPart} {RequestId, stream_end, Headers}
Default is the pid
of the process calling the request
function (self()
).
ipv6_host_with_brackets
Defines when parsing the Host-Port part of an URI with an IPv6 address
with brackets, if those brackets are to be retained (true
)
or stripped (false
).
Default is false
.
Options = [Option]
Option = {proxy, {Proxy, NoProxy}}
| {https_proxy, {Proxy, NoProxy}}
| {max_sessions, MaxSessions}
| {max_keep_alive_length, MaxKeepAlive}
| {keep_alive_timeout, KeepAliveTimeout}
| {max_pipeline_length, MaxPipeline}
| {pipeline_timeout, PipelineTimeout}
| {cookies, CookieMode}
| {ipfamily, IpFamily}
| {ip, IpAddress}
| {port, Port}
| {socket_opts, socket_opts()}
| {verbose, VerboseMode}
| {unix_socket, UnixSocket}
Proxy = {Hostname, Port}
Hostname = string()
Port = integer()
NoProxy = [NoProxyDesc]
NoProxyDesc = DomainDesc | HostName | IPDesc
DomainDesc = "*.Domain"
IpDesc = string()
MaxSessions = integer()
MaxKeepAlive = integer()
KeepAliveTimeout = integer()
MaxPipeline = integer()
PipelineTimeout = integer()
CookieMode = enabled | disabled | verify
IpFamily = inet | inet6 | local
IpAddress = ip_address()
Port = integer()
socket_opts() = [socket_opt()]
VerboseMode = false | verbose | debug | trace
Profile = profile() | pid()
UnixSocket = path()
proxy
defaults to {undefined, []}
,
that is, no proxy is configured and
https_proxy
defaults to the value of proxy
.2
.5
.keep_alive_timeout
in milliseconds,
the client closes the connection.
The server can also have such a time-out but do not take that for granted.
Default is 120000
(= 2 min).2
.pipeline_timeout
in milliseconds,
the client closes the connection. Default is 0
,
which results in pipelining not being used.verify
is used, function store_cookies/2
has to be called for the cookies to be saved.
Default is disabled
.inet
.gen_tcp
or SSL
)
without verification.false
.
This option is used to switch on (or off)
different levels of Erlang trace on the client.
It is a debug feature.stand_alone
only the pid can be used.unix_socket
shall be the full path to a unix domain socket file with read/write
permissions for the erlang process. Default is undefined
.
Sets options to be used for subsequent requests.
Note!
If possible, the client keeps its connections alive and uses persistent connections with or without pipeline depending on configuration and current circumstances. The HTTP/1.1 specification does not provide a guideline for how many requests that are ideal to be sent on a persistent connection. This depends much on the application.
A long queue of requests can cause a
user-perceived delay, as earlier requests can take a long time
to complete. The HTTP/1.1 specification suggests a
limit of two persistent connections per server, which is the
default value of option max_sessions
.
The current implementation assumes the requests to the same host, port combination will use the same socket options.
SetCookieHeaders = headers() - where field = "set-cookie"
Url = url()
Profile = profile() | pid()
stand_alone
only the pid can be used.Saves the cookies defined in SetCookieHeaders
in the client profile cookie database.
Call this function if option cookies
is set to verify
.
If no profile is specified, the default profile is used.
Pid = pid()
stream_start message
Triggers the next message to be streamed, that is, the same behavior as active ones for sockets.
Profile = profile() | pid()
cookies() = [cookie_stores()]
cookie_stores() = {cookies, cookies()} | {session_cookies, cookies()}
cookies() = [cookie()]
cookie() = term()
stand_alone
only the pid can be used.Produces a list of the entire cookie database. Intended for debugging/testing purposes. If no profile is specified, the default profile is used.
Profile = profile() | pid()
session_info() = {GoodSessions, BadSessions, NonSessions}
GoodSessions = session()
BadSessions = tuple()
NonSessions = term()
stand_alone
only the pid can be used.Produces a slightly processed dump of the session database. It is intended for debugging. If no profile is specified, the default profile is used.