Mint.HTTP.connect
connect
, go back to Mint.HTTP module for more information.
Specs
connect( Mint.Types.scheme(), Mint.Types.address(), :inet.port_number(), keyword() ) :: {:ok, t()} | {:error, Mint.Types.error()}
Creates a new connection to a given server.
Creates a new connection struct and establishes the connection to the given server,
identified by the given host
and port
combination. Both HTTP and HTTPS are supported
by passing respectively :http
and :https
as the scheme
.
The connection struct wraps a socket, which is created once the connection
is established inside this function. If HTTP is used, then the created socket is a TCP
socket and the :gen_tcp
module is used to create that socket. If HTTPS is used, then
the created socket is an SSL socket and the :ssl
module is used to create that socket.
The socket is created in active mode (with active: :once
), which is why it is important
to know the type of the socket: messages from the socket will be delivered directly to the
process that creates the connection and tagged appropriately by the socket module (see the
:gen_tcp
and :ssl
modules). See stream/2
for more information on the messages and
how to process them and on the socket mode.
Options
:hostname
- (string) explicitly provide the hostname used for theHost
header, hostname verification, SNI, and so on. Required whenaddress
is not a string.:transport_opts
- (keyword) options to be given to the transport being used. These options will be merged with some default options that cannot be overridden. For more details, refer to the "Transport options" section below.:mode
- (:active
or:passive
) whether to set the socket to active or passive mode. See the "Mode" section in the module documentation andset_mode/2
.:protocols
- (list of atoms) a list of protocols to try when connecting to the server. The possible values in the list are:http1
for HTTP/1 and HTTP/1.1 and:http2
for HTTP/2. If only one protocol is present in the list, then the connection will be forced to use that protocol. If both:http1
and:http2
are present in the list, then Mint will negotiate the protocol. See the section "Protocol negotiation" below for more information. Defaults to[:http1, :http2]
.:proxy_headers
- a list of headers (Mint.Types.headers/0
) to pass when using a proxy. They will be used for theCONNECT
request in tunnel proxies or merged with every request for forward proxies.
The following options are HTTP/1-specific and will force the connection to be an HTTP/1 connection.
:proxy
- a{scheme, address, port, opts}
tuple that identifies a proxy to connect to. See the "Proxying" section below for more information.
The following options are HTTP/2-specific and will only be used on HTTP/2 connections.
:client_settings
- (keyword) a list of client HTTP/2 settings to send to the server. SeeMint.HTTP2.put_settings/2
for more information. This is only used in HTTP/2 connections.
Protocol negotiation
If both :http1
and :http2
are present in the list passed in the :protocols
option,
the protocol negotiation happens in the following way:
If the scheme used to connect to the server is
:http
, then HTTP/1 or HTTP/1.1 is used.If the scheme is
:https
, then ALPN negotiation is used to determine the right protocol. This means that the server will decide whether to use HTTP/1 or HTTP/2. If the server doesn't support protocol negotiation, we will fall back to HTTP/1. If the server negotiates a protocol that we don't know how to handle,{:error, {:bad_alpn_protocol, protocol}}
is returned.
Proxying
You can set up proxying through the :proxy
option, which is a tuple
{scheme, address, port, opts}
that identifies the proxy to connect to.
Once a proxied connection is returned, the proxy is transparent to you and you
can use the connection like a normal HTTP/1 connection.
If the scheme
is :http
, we will connect to the host in the most compatible
way, supporting older proxy servers. Data will be sent in clear text.
If the connection scheme is :https
, we will connect to the host with a tunnel
through the proxy. Using :https
for both the proxy and the connection scheme
is not supported, it is recommended to use :https
for the end host connection
instead of the proxy.
Transport options
The options specified in :transport_opts
are passed to the module that
implements the socket interface: :gen_tcp
when the scheme is :http
, and
:ssl
when the scheme is :https
. Please refer to the documentation for those
modules, as well as for :inet.setopts/2
, for a detailed description of all
available options.
The behaviour of some options is modified by Mint, as described below.
A special case is the :timeout
option, which is passed to the transport
module's connect
function to limit the amount of time to wait for the
network connection to be established.
Common options for :http
and :https
:
:active
- controlled by the:mode
option. Cannot be overridden.:mode
- set to:binary
. Cannot be overriden.:packet
- set to:raw
. Cannot be overridden.:timeout
- connect timeout in milliseconds. Defaults to30_000
(30 seconds), and may be overridden by the caller. Set to:infinity
to disable the connect timeout.
Options for :https
only:
:alpn_advertised_protocols
- managed by Mint. Cannot be overridden.:cacertfile
- if:verify
is set to:verify_peer
(the default) and no CA trust store is specified using the:cacertfile
or:cacerts
option, Mint will attempt to use the trust store from the CAStore package or raise an exception if this package is not available. Due to caching the:cacertfile
option is more efficient than:cacerts
.:ciphers
- defaults to the lists returned by:ssl.filter_cipher_suites(:ssl.cipher_suites(:all, version), [])
whereversion
is each value in the:versions
setting. This list is then filtered according to the blocklist in RFC7540 appendix A; May be overridden by the caller. See the "Supporting older cipher suites" section below for some examples.:depth
- defaults to4
. May be overridden by the caller.:partial_chain
- unless a custom:partial_chain
function is specified, Mint will enable its own partial chain handler, which accepts server certificate chains containing a certificate that was issued by a CA certificate in the CA trust store, even if that certificate is not last in the chain. This improves interoperability with some servers (for example, with a cross-signed intermediate CA or some misconfigured servers), but is a less strict interpretation of the TLS specification than the Erlang/OTP default behaviour.:reuse_sessions
- defaults totrue
. May be overridden by the caller. If:"tlsv1.3"
is the only TLS version specified,:reuse_sessions
will be removed from the options.:secure_renegotiate
- defaults totrue
. May be overridden by the caller. If:"tlsv1.3"
is the only TLS version specified,:secure_renegotiate
will be removed from the options.:server_name_indication
- defaults to specified destination hostname. May be overridden by the caller.:verify
- defaults to:verify_peer
. May be overridden by the caller.:verify_fun
- unless a custom:verify_fun
is specified, or:verify
is set to:verify_none
, Mint will enable hostname verification with support for wildcards in the server's 'SubjectAltName' extension, similar to the behaviour implemented in:public_key.pkix_verify_hostname_match_fun(:https)
in recent Erlang/OTP releases. This improves compatibility with recently issued wildcard certificates also on older Erlang/OTP releases.:versions
- defaults to[:"tlsv1.2"]
(TLS v1.2 only). May be overridden by the caller.
Supporting older cipher suites
By default only a small list of modern cipher suites is enabled, in compliance with the HTTP/2 specification. Some servers, in particular HTTP/1 servers, may not support any of these cipher suites, resulting in TLS handshake failures or closed connections.
To select the default cipher suites of Erlang/OTP (including for example
AES-CBC), use the following :transport_opts
:
# Erlang/OTP 20.3 or later:
transport_opts: [ciphers: :ssl.cipher_suites(:default, :"tlsv1.2")]
# Older versions:
transport_opts: [ciphers: :ssl.cipher_suites()]
Recent Erlang/OTP releases do not enable RSA key exchange by default, due to
known weaknesses. If necessary, you can build a cipher list with RSA exchange
and use it in :transport_opts
:
ciphers =
:ssl.cipher_suites(:all, :"tlsv1.2")
|> :ssl.filter_cipher_suites(
key_exchange: &(&1 == :rsa),
cipher: &(&1 in [:aes_256_gcm, :aes_128_gcm, :aes_256_cbc, :aes_128_cbc])
)
|> :ssl.append_cipher_suites(:ssl.cipher_suites(:default, :"tlsv1.2"))
Examples
{:ok, conn} = Mint.HTTP.connect(:http, "httpbin.org", 80)
Using a proxy:
proxy = {:http, "myproxy.example.com", 80, []}
{:ok, conn} = Mint.HTTP.connect(:https, "httpbin.org", 443, proxy: proxy)
Forcing the connection to be an HTTP/2 connection:
{:ok, conn} = Mint.HTTP.connect(:https, "http2.golang.org", 443, protocols: [:http2])
Enable all default cipher suites of Erlang/OTP (release 20.3 or later):
opts = [transport_opts: [ciphers: :ssl.cipher_suites(:default, :"tlsv1.2")]]
{:ok, conn} = Mint.HTTP.connect(:https, "httpbin.org", 443, opts)