aboutsummaryrefslogtreecommitdiffstats
path: root/doc/src
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/manual/gun.asciidoc791
-rw-r--r--doc/src/manual/gun.await.asciidoc114
-rw-r--r--doc/src/manual/gun.await_body.asciidoc88
-rw-r--r--doc/src/manual/gun.await_up.asciidoc73
-rw-r--r--doc/src/manual/gun.cancel.asciidoc68
-rw-r--r--doc/src/manual/gun.close.asciidoc44
-rw-r--r--doc/src/manual/gun.data.asciidoc75
-rw-r--r--doc/src/manual/gun.delete.asciidoc82
-rw-r--r--doc/src/manual/gun.flush.asciidoc59
-rw-r--r--doc/src/manual/gun.get.asciidoc85
-rw-r--r--doc/src/manual/gun.head.asciidoc92
-rw-r--r--doc/src/manual/gun.info.asciidoc49
-rw-r--r--doc/src/manual/gun.open.asciidoc72
-rw-r--r--doc/src/manual/gun.open_unix.asciidoc60
-rw-r--r--doc/src/manual/gun.options.asciidoc83
-rw-r--r--doc/src/manual/gun.patch.asciidoc119
-rw-r--r--doc/src/manual/gun.post.asciidoc116
-rw-r--r--doc/src/manual/gun.put.asciidoc115
-rw-r--r--doc/src/manual/gun.request.asciidoc105
-rw-r--r--doc/src/manual/gun.ws_send.asciidoc65
-rw-r--r--doc/src/manual/gun.ws_upgrade.asciidoc100
-rw-r--r--doc/src/manual/gun_app.asciidoc39
-rw-r--r--doc/src/manual/gun_data.asciidoc77
-rw-r--r--doc/src/manual/gun_down.asciidoc86
-rw-r--r--doc/src/manual/gun_error.asciidoc67
-rw-r--r--doc/src/manual/gun_inform.asciidoc70
-rw-r--r--doc/src/manual/gun_push.asciidoc90
-rw-r--r--doc/src/manual/gun_response.asciidoc75
-rw-r--r--doc/src/manual/gun_trailers.asciidoc67
-rw-r--r--doc/src/manual/gun_up.asciidoc61
-rw-r--r--doc/src/manual/gun_upgrade.asciidoc72
-rw-r--r--doc/src/manual/gun_ws.asciidoc62
32 files changed, 2580 insertions, 641 deletions
diff --git a/doc/src/manual/gun.asciidoc b/doc/src/manual/gun.asciidoc
index 98fbabe..77253ba 100644
--- a/doc/src/manual/gun.asciidoc
+++ b/doc/src/manual/gun.asciidoc
@@ -2,7 +2,7 @@
== Name
-gun - asynchronous HTTP client
+gun - Asynchronous HTTP client
== Description
@@ -10,711 +10,242 @@ The `gun` module provides an asynchronous interface for
connecting and communicating with Web servers over HTTP,
HTTP/2 or Websocket.
-== Types
-
-=== opts() = map()
-
-Configuration for the connection.
-
-The following keys are defined:
-
-connect_timeout => timeout()::
- Connection timeout. Defaults to `infinity`.
-http_opts => http_opts()::
- Options specific to the HTTP protocol. See below.
-http2_opts => http2_opts()::
- Options specific to the HTTP/2 protocol. See below.
-protocols => [http | http2]::
- Ordered list of preferred protocols. When the transport is tcp,
- this list must contain exactly one protocol. When the transport
- is ssl, this list must contain at least one protocol and will be
- used using the ALPN protocol negotiation method. When the server
- does not support ALPN then http will always be used. Defaults to
- [http] when the transport is tcp, and [http2, http] when the
- transport is ssl.
-retry => non_neg_integer()::
- Number of times Gun will try to reconnect on failure before giving up.
- Defaults to 5.
-retry_timeout => pos_integer()::
- Time between retries in milliseconds. Defaults to 5000.
-trace => boolean()::
- Whether to enable `dbg` tracing of the connection process. Should
- only be used during debugging. Defaults to false.
-transport => tcp | ssl::
- Whether to use SSL or plain TCP. The default varies depending on the
- port used. Port 443 defaults to ssl. All other ports default to tcp.
-transport_opts => proplists:proplist()::
- Transport options. They are TCP options or SSL options depending on
- the selected transport.
-ws_opts => ws_opts()::
- Options specific to the Websocket protocol. See below.
-
-// @todo better spec for transport_opts
-
-=== http_opts() = map()
-
-Configuration for the HTTP protocol.
-
-The following keys are defined:
-
-keepalive => timeout()::
- Time between pings in milliseconds. Since the HTTP protocol has
- no standardized way to ping the server, Gun will simply send an
- empty line when the connection is idle. Gun only makes a best
- effort here as servers usually have configurable limits to drop
- idle connections. Use `infinity` to disable. Defaults to 5000.
-transform_header_name => fun((LowercaseName :: binary()) -> TransformedName :: binary()) | undefined::
- A function that will be applied to all header names before they
- are sent to the server. Gun assumes that all header names are in
- lower case. This function is useful if you, for example, need to
- re-case header names in the event that the server incorrectly
- considers header name case to be significant.
-version => 'HTTP/1.1' | 'HTTP/1.0'::
- HTTP version to use. Defaults to 'HTTP/1.1'.
-
-=== http2_opts() = map()
-
-Configuration for the HTTP/2 protocol.
-
-The following keys are defined:
-
-keepalive => pos_integer()::
- Time between pings in milliseconds. Defaults to 5000.
-
-=== req_opts() = map()
-
-Configuration for a particular request.
-
-The following keys are defined:
-
-reply_to => pid()::
- The pid of a process that is responsible for the response handling.
-
-=== ws_opts() = map()
-
-Configuration for the Websocket protocol.
-
-The following keys are defined:
-
-compress => boolean()::
- Whether to enable permessage-deflate compression. This does
- not guarantee that compression will be used as it is the
- server that ultimately decides. Defaults to false.
-
-== Messages
-
-Calling functions from this module may result in the following
-messages being sent.
-
-=== {gun_up, ConnPid, Protocol}
-
-ConnPid = pid():: The pid of the Gun connection process.
-Protocol = http | http2:: The protocol selected for this connection.
-
-The connection is up.
-
-This message informs the owner process that the connection or
-reconnection completed.
-
-The protocol selected during the connection is sent in this
-message. It can be used to determine the capabilities of the
-server.
-
-Gun will now start processing the messages it received while
-waiting for the connection to be up. If this is a reconnection,
-then this may not be desirable for all requests. Those requests
-should be cancelled when the connection goes down, and any
-subsequent messages ignored.
-
-=== {gun_down, ConnPid, Protocol, Reason, KilledStreams, UnprocessedStreams}
-
-ConnPid = pid():: The pid of the Gun connection process.
-Protocol = http | http2 | ws:: The protocol in use when the connection was lost.
-Reason = normal | closed | {error, atom()}:: The reason for the loss of the connection.
-KilledStreams = [reference()]:: List of streams that have been brutally terminated.
-UnprocessedStreams = [reference()]:: List of streams that have not been processed by the server.
-
-The connection is down.
-
-This message informs the owner process that the connection is
-currently down. Gun will automatically attempt to reconnect
-depending on the `retry` and `retry_timeout` options.
-
-The reason of the termination is there for debugging purposes
-only. You should not rely on this value to know what streams
-were processed or completed.
-
-The _killed streams_ are the active streams that did not complete
-before the closing of the connection. Whether they can be retried
-safely depends on the protocol used and the idempotence property
-of the requests.
-
-The _unprocessed streams_ are streams that the server did not
-start processing yet. They may be retried safely depending on
-what streams were killed before.
-
-When the connection goes back up, Gun will not attempt to retry
-requests. It will also not upgrade to Websocket automatically
-if that was the protocol in use when the connection was lost.
-
-=== {gun_push, ConnPid, StreamRef, NewStreamRef, URI, Headers}
-
-ConnPid = pid():: The pid of the Gun connection process.
-StreamRef = reference():: Identifier of the stream initiated by the owner process.
-NewStreamRef = reference():: Identifier of the stream being pushed.
-URI = binary():: URI of the resource.
-Headers = [{binary(), binary()}]:: Headers @todo
-
-A resource pushed alongside an HTTP response.
-
-This message can only be sent when the protocol is HTTP/2.
-
-@todo I fear we also need the scheme; resource is identified by URI
-@todo Perhaps we really should send the URI entirely, because cache
-@todo relies on URI to work and this feature is for caching...
-@todo Not sure why Method is there, spec says it is only for GET
-
-=== {gun_response, ConnPid, StreamRef, IsFin, Status, Headers}
-
-ConnPid = pid():: The pid of the Gun connection process.
-StreamRef = reference():: Identifier of the stream initiated by the owner process.
-IsFin = fin | nofin:: Whether this message terminates the response.
-Status = binary():: Status line for the response.
-Headers = [{binary(), binary()}]:: Headers sent with the response.
-
-A response to an HTTP request.
-
-=== {gun_data, ConnPid, StreamRef, IsFin, Data}
-
-ConnPid = pid():: The pid of the Gun connection process.
-StreamRef = reference():: Identifier of the stream this data belongs to.
-IsFin = fin | nofin:: Whether this message terminates the response.
-Data = binary():: Data from the stream.
-
-Data associated with a stream.
-
-The stream in question can be either one initiated by the owner
-process or a stream initiated by the server through the push
-mechanism. In any case a `gun_response` or a `gun_push` message
-will be sent before any `gun_data` message.
-
-=== {gun_error, ConnPid, StreamRef, Reason}
-
-ConnPid = pid():: The pid of the Gun connection process.
-StreamRef = reference():: Identifier of the stream this error relates to.
-Reason = any():: Error reason.
-
-Stream-specific error.
-
-=== {gun_error, ConnPid, Reason}
-
-ConnPid = pid():: The pid of the Gun connection process.
-Reason = any():: Error reason.
-
-General error.
-
-=== {gun_ws_upgrade, ConnPid, ok, Headers}
-
-ConnPid = pid():: The pid of the Gun connection process.
-Headers = [{binary(), binary()}]:: Headers sent with the response.
-
-Successful upgrade to the Websocket protocol.
-
-=== {gun_ws, ConnPid, Frame}
-
-ConnPid = pid():: The pid of the Gun connection process.
-Frame = @todo:: Frame.
-
-Websocket frame.
-
== Exports
-=== open(Host, Port) -> open(Host, Port, [])
-
-Alias of `gun:open/3`.
-
-=== open(Host, Port, Opts) -> {ok, ConnPid} | {error, Reason}
-
-Host = inet:hostname() | inet:ipaddress():: Host or IP to connect to.
-Port = inet:port_number():: Port to connect to.
-Opts = opts():: Options for this connection.
-ConnPid = pid():: The pid of the Gun connection process.
-Reason = any():: Error reason. @todo really any?
-
-Open a connection to the given host and port.
-
-=== close(ConnPid) -> ok
-
-ConnPid = pid():: The pid of the Gun connection process.
-
-Brutally close the connection.
-
-=== shutdown(ConnPid) -> ok
-
-ConnPid = pid():: The pid of the Gun connection process.
-
-Gracefully close the connection.
-
-A monitor can be used to be notified when the connection is
-effectively closed.
-
-=== delete(ConnPid, Path) -> delete(ConnPid, Path, [], #{})
-
-Alias of `gun:delete/4`.
-
-=== delete(ConnPid, Path, Headers) -> delete(ConnPid, Path, Headers, #{})
-
-Alias of `gun:delete/4`.
-
-=== delete(ConnPid, Path, Headers, ReqOpts) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-ReqOpts = req_opts():: Request options.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Delete a resource.
-
-=== get(ConnPid, Path) -> get(ConnPid, Path, [], #{})
+Connection:
-Alias of `gun:get/4`.
+* link:man:gun:open(3)[gun:open(3)] - Open a connection to the given host and port
+* link:man:gun:open_unix(3)[gun:open_unix(3)] - Open a connection to the given Unix domain socket
+// @todo * link:man:gun:shutdown(3)[gun:shutdown(3)] - Gracefully close the connection
+* link:man:gun:close(3)[gun:close(3)] - Brutally close the connection
+* link:man:gun:info(3)[gun:info(3)] - Obtain information about the connection
-=== get(ConnPid, Path, Headers) -> get(ConnPid, Path, Headers, #{})
+Requests:
-Alias of `gun:get/4`.
+* link:man:gun:get(3)[gun:get(3)] - Get a resource representation
+* link:man:gun:head(3)[gun:head(3)] - Get headers of a resource representation
+* link:man:gun:options(3)[gun:options(3)] - Query the capabilities of the server or a resource
+* link:man:gun:patch(3)[gun:patch(3)] - Apply a set of changes to a resource
+* link:man:gun:post(3)[gun:post(3)] - Process the enclosed representation according to a resource's own semantics
+* link:man:gun:put(3)[gun:put(3)] - Create or replace a resource
+* link:man:gun:delete(3)[gun:delete(3)] - Delete a resource
+* link:man:gun:request(3)[gun:request(3)] - Perform the given request
+* link:man:gun:data(3)[gun:data(3)] - Stream the body of a request
-=== get(ConnPid, Path, Headers, ReqOpts) -> StreamRef
+Messages:
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-ReqOpts = req_opts():: Request options.
-StreamRef = reference():: Identifier of the stream for this request.
+* link:man:gun:await(3)[gun:await(3)] - Wait for a response
+* link:man:gun:await_body(3)[gun:await_body(3)] - Wait for the complete response body
+* link:man:gun:await_up(3)[gun:await(3)] - Wait for the connection to be up
+* link:man:gun:flush(3)[gun:flush(3)] - Flush all messages related to a connection or a stream
-Get a resource.
+Streams:
-=== head(ConnPid, Path) -> head(ConnPid, Path, [], #{})
+* link:man:gun:cancel(3)[gun:cancel(3)] - Cancel the given stream
-Alias of `gun:head/4`.
+Websocket:
-=== head(ConnPid, Path, Headers) -> head(ConnPid, Path, Headers, #{})
+* link:man:gun:ws_upgrade(3)[gun:ws_upgrade(3)] - Upgrade to Websocket
+* link:man:gun:ws_send(3)[gun:ws_send(3)] - Send one or more Websocket frame(s)
-Alias of `gun:head/4`.
-
-=== head(ConnPid, Path, Headers, ReqOpts) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-ReqOpts = req_opts():: Request options.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Get headers of a resource.
-
-This function performs the same operation as `get/{2,3}` except
-the server will not send the resource representation, only the
-response's status line and headers.
-
-While servers should send the same headers they would if the
-request was a GET, like `content-length`, it is not always
-the case and differences may exist.
-
-=== options(ConnPid, Path) -> options(ConnPid, Path, [], #{})
-
-Alias of `gun:options/4`.
-
-=== options(ConnPid, Path, Headers) -> options(ConnPid, Path, Headers, #{})
-
-Alias of `gun:options/4`.
-
-=== options(ConnPid, Path, Headers, ReqOpts) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-ReqOpts = req_opts():: Request options.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Obtain information about the capabilities of the server or of a resource.
-
-The special path `"*"` can be used to obtain information about
-the server as a whole. Any other path will return information
-about the resource only.
-
-=== patch(ConnPid, Path, Headers) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Request that a set of changes be applied to the resource.
-
-This function expects either `content-length` or `content-type`
-to be set to know a body is going to be sent afterwards.
-Gun will assume the request has no body otherwise. It is
-highly recommended to set both when possible.
-
-The body sent in this request should be a patch document
-with instructions on how to update the resource.
-
-You can use the `gun:data/4` function to send the body, if any.
-
-=== patch(ConnPid, Path, Headers, Body) -> patch(ConnPid, Path, Headers, Body, #{})
-
-Alias of `gun:patch/5`.
-
-=== patch(ConnPid, Path, Headers, Body, ReqOpts) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-Body = iodata():: Body of the request.
-ReqOpts = req_opts():: Request options.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Request that a set of changes be applied to the resource.
-
-It is highly recommended to set the `content-type` header
-to inform the server what media type the body contains.
-Gun will automatically set the `content-length` header.
-
-The body sent in this request should be a patch document
-with instructions on how to update the resource.
-
-The complete request is sent when calling this function.
-It is not possible to stream more of the body after
-calling it.
-
-=== post(ConnPid, Path, Headers) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Process the enclosed representation according to the resource's own semantics.
-
-This function expects either `content-length` or `content-type`
-to be set to know a body is going to be sent afterwards.
-Gun will assume the request has no body otherwise. It is
-highly recommended to set both when possible.
-
-The body sent in this request will be processed
-according to the resource's own semantics. A new
-resource may be created as a result, and may be
-located at a different URI.
-
-You can use the `gun:data/4` function to send the body, if any.
-
-=== post(ConnPid, Path, Headers, Body) -> post(ConnPid, Path, Headers, Body, #{})
-
-Alias of `gun:post/5`.
-
-=== post(ConnPid, Path, Headers, Body, ReqOpts) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-Body = iodata():: Body of the request.
-ReqOpts = req_opts():: Request options.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Process the enclosed representation according to the resource's own semantics.
-
-It is highly recommended to set the `content-type` header
-to inform the server what media type the body contains.
-Gun will automatically set the `content-length` header.
-
-The body sent in this request will be processed
-according to the resource's own semantics. A new
-resource may be created as a result, and may be
-located at a different URI.
-
-The complete request is sent when calling this function.
-It is not possible to stream more of the body after
-calling it.
-
-=== put(ConnPid, Path, Headers) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Create or replace a resource.
-
-The body of the request is the entire representation of the resource.
-
-This function expects either `content-length` or `content-type`
-to be set to know a body is going to be sent afterwards.
-Gun will assume the request has no body otherwise. It is
-highly recommended to set both when possible.
-
-You can use the `gun:data/4` function to send the body, if any.
-
-=== put(ConnPid, Path, Headers, Body) -> put(ConnPid, Path, Headers, Body, #{})
-
-Alias of `gun:put/5`.
-
-=== put(ConnPid, Path, Headers, Body, ReqOpts) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-Body = iodata():: Body of the request.
-ReqOpts = req_opts():: Request options.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Create or replace a resource.
-
-The body of the request is the entire representation of the resource.
-
-It is highly recommended to set the `content-type` header
-to inform the server what media type the body contains.
-Gun will automatically set the `content-length` header.
-
-The complete request is sent when calling this function.
-It is not possible to stream more of the body after
-calling it.
-
-=== request(ConnPid, Method, Path, Headers) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Method = iodata():: Request method.
-Path = iodata():: Path of the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Perform the given request.
-
-This is a general purpose function that should only be used
-when existing method-specific functions don't apply.
-
-This function expects either `content-length` or `content-type`
-to be set to know a body is going to be sent afterwards.
-Gun will assume the request has no body otherwise. It is
-highly recommended to set both when possible.
-
-You can use the `gun:data/4` function to send the body, if any.
-
-=== request(ConnPid, Method, Path, Headers, Body) -> request(ConnPid, Method, Path, Headers, Body, #{})
-
-Alias of `gun:request/6`.
-
-=== request(ConnPid, Method, Path, Headers, Body, ReqOpts) -> StreamRef
-
-ConnPid = pid():: The pid of the Gun connection process.
-Method = iodata():: Request method.
-Path = iodata():: Path of the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-Body = iodata():: Body of the request.
-ReqOpts = req_opts():: Request options.
-StreamRef = reference():: Identifier of the stream for this request.
-
-Perform the given request.
-
-This is a general purpose function that should only be used
-when existing method-specific functions don't apply.
-
-It is highly recommended to set the `content-type` header
-to inform the server what media type the body contains.
-Gun will automatically set the `content-length` header.
-
-The complete request is sent when calling this function.
-It is not possible to stream more of the body after
-calling it.
-
-=== data(ConnPid, StreamRef, IsFin, Data) -> ok
-
-ConnPid = pid():: The pid of the Gun connection process.
-StreamRef = reference():: Identifier of the stream this data belongs to.
-IsFin = fin | nofin:: Whether this message terminates the request.
-Data = iodata():: Data to be sent with the request.
-
-Stream the body of a request.
-
-@todo empty chunks
-
-This function can only be used if the request identified by
-`StreamRef` came with headers indicating the presence of a
-body and that body not being given when creating the request.
-
-All calls to this function must use `nofin` except for the
-last which must use `fin` to indicate the end of the request
-body.
+== Messages
-Empty data is allowed regardless of the value of `IsFin`.
-Gun will not send empty data chunks unless required to
-indicate the request body is finished, however.
+Gun will inform the calling process of events asynchronously
+by sending any of the following messages:
-=== await(ConnPid, StreamRef) -> await(ConnPid, StreamRef, 5000, MonitorRef)
+Connection:
-Alias of `gun:await/4`.
+* link:man:gun_up(3)[gun_up(3)] - The connection is up
+* link:man:gun_down(3)[gun_down(3)] - The connection is down
+* link:man:gun_upgrade(3)[gun_upgrade(3)] - Successful protocol upgrade
+* link:man:gun_error(3)[gun_error(3)] - Stream or connection-wide error
-A monitor `MonitorRef` is automatically created for the duration of
-this call and an error will be returned if the Gun connection process
-terminates.
+Responses:
-=== await(ConnPid, StreamRef, MonitorRef) -> await(ConnPid, StreamRef, 5000, MonitorRef)
+* link:man:gun_push(3)[gun_push(3)] - Server-initiated push
+* link:man:gun_inform(3)[gun_inform(3)] - Informational response
+* link:man:gun_response(3)[gun_response(3)] - Response
+* link:man:gun_data(3)[gun_data(3)] - Response body
+* link:man:gun_trailers(3)[gun_trailers(3)] - Response trailers
-Alias of `gun:await/4`.
+Websocket:
-=== await(ConnPid, StreamRef, Timeout) -> await(ConnPid, StreamRef, Timeout, MonitorRef)
+* link:man:gun_ws(3)[gun_ws(3)] - Websocket frame
-Alias of `gun:await/4`.
+The response messages will be sent to the process that opened
+the connection by default. The `reply_to` request option can
+be used to redirect request-specific messages to a different
+process.
-A monitor `MonitorRef` is automatically created for the duration of
-this call and an error will be returned if the Gun connection process
-terminates.
+== Types
-=== await(ConnPid, StreamRef, Timeout, MonitorRef) -> tuple() -- see below
+=== http_opts()
-ConnPid = pid():: The pid of the Gun connection process.
-StreamRef = reference():: Identifier of the stream to await messages from.
-Timeout = timeout():: How long this function will wait for messages.
-MonitorRef = reference():: Monitor reference for the Gun connection process.
+[source,erlang]
+----
+http_opts() :: #{
+ keepalive => timeout(),
+ transform_header_name => fun((binary()) -> binary()),
+ version => 'HTTP/1.1' | 'HTTP/1.0'
+}
+----
-Wait for a response message.
+Configuration for the HTTP protocol.
-This function can be used when a synchronous handling of
-responses is desired. It will only return when a message
-for the given stream is received, on error or on timeout.
+The default value is given next to the option name:
-The return values are described in the next few subsections.
+// @todo Document content_handlers and gun_sse.
-==== {response, IsFin, Status, Headers}
+keepalive (5000)::
-IsFin = fin | nofin:: Whether this message terminates the response.
-Status = binary():: Status line for the response.
-Headers = [{binary(), binary()}]:: Headers sent with the response.
+Time between pings in milliseconds. Since the HTTP protocol has
+no standardized way to ping the server, Gun will simply send an
+empty line when the connection is idle. Gun only makes a best
+effort here as servers usually have configurable limits to drop
+idle connections. Use `infinity` to disable.
-Equivalent of a `gun_response` message.
+transform_header_name - see below::
-==== {data, IsFin, Data}
+A function that will be applied to all header names before they
+are sent to the server. Gun assumes that all header names are in
+lower case. This function is useful if you, for example, need to
+re-case header names in the event that the server incorrectly
+considers the case of header names to be significant.
-IsFin = fin | nofin:: Whether this message terminates the response.
-Data = binary():: Data from the stream.
+version (`'HTTP/1.1'`)::
-Equivalent of a `gun_data` message.
+HTTP version to use.
-==== {push, NewStreamRef, URI, Headers}
+=== http2_opts()
-NewStreamRef = reference():: Identifier of the stream being pushed.
-URI = binary():: URI of the resource.
-Headers = [{binary(), binary()}]:: Headers @todo
+[source,erlang]
+----
+http2_opts() :: #{
+ keepalive => timeout()
+}
+----
-Equivalent of a `gun_push` message.
+Configuration for the HTTP/2 protocol.
-@todo Same changes as gun_push
+The default value is given next to the option name:
-==== {error, Reason}
+// @todo Document content_handlers and gun_sse.
-Reason = any():: Error reason. @todo any?
+keepalive (5000)::
-Equivalent of a `gun_error` message.
+Time between pings in milliseconds.
-@todo I think we want to distinguish a stream error, a general error,
-@todo a DOWN and a timeout error
+// @todo Allow and document max_frame_size_sent.
-=== await_body(ConnPid, StreamRef) -> await_body(ConnPid, StreamRef, 5000, MonitorRef)
+=== opts()
-Alias of `gun:await_body/4`.
+[source,erlang]
+----
+opts() :: #{
+ connect_timeout => timeout(),
+ http_opts => http_opts(),
+ http2_opts => http2_opts(),
+ protocols => [http | http2],
+ retry => non_neg_integer(),
+ retry_timeout => pos_integer(),
+ trace => boolean(),
+ transport => tcp | ssl,
+ transport_opts => [gen_tcp:connect_option()] | [ssl:connect_option()]
+ ws_opts => ws_opts()
+}
+----
-A monitor `MonitorRef` is automatically created for the duration of
-this call and an error will be returned if the Gun connection process
-terminates.
+Configuration for the connection.
-=== await_body(ConnPid, StreamRef, MonitorRef) -> await_body(ConnPid, StreamRef, 5000, MonitorRef)
+The default value is given next to the option name:
-Alias of `gun:await_body/4`.
+connect_timeout (infinity)::
-=== await_body(ConnPid, StreamRef, Timeout) -> await_body(ConnPid, StreamRef, Timeout, MonitorRef)
+Connection timeout.
-Alias of `gun:await_body/4`.
+http_opts (#{})::
-A monitor `MonitorRef` is automatically created for the duration of
-this call and an error will be returned if the Gun connection process
-terminates.
+Options specific to the HTTP protocol.
-=== await_body(ConnPid, StreamRef, Timeout, MonitorRef) -> {ok, Body} | {error, Reason}
+http2_opts (#{})::
-ConnPid = pid():: The pid of the Gun connection process.
-StreamRef = reference():: Identifier of the stream to await messages from.
-Timeout = timeout():: How long this function will wait for each message.
-MonitorRef = reference():: Monitor reference for the Gun connection process.
-Body = binary():: Body for the given stream.
-Reason = any():: Error reason. @todo any?
+Options specific to the HTTP/2 protocol.
-Wait for a response body.
+protocols - see below::
-This function can be used when a synchronous handling of
-responses is desired. It will only return when it has
-finished fetching the entire response body.
+Ordered list of preferred protocols. When the transport is `tcp`,
+this list must contain exactly one protocol. When the transport
+is `ssl`, this list must contain at least one protocol and will be
+used to negotiate a protocol via ALPN. When the server does not
+support ALPN then `http` will always be used. Defaults to
+`[http]` when the transport is `tcp`, and `[http2, http]` when the
+transport is `ssl`.
-The timeout value is *per message*. The actual function call
-can last much longer for large bodies.
+retry (5)::
-@todo I think we want to distinguish a stream error, a general error,
-@todo a DOWN and a timeout error
+Number of times Gun will try to reconnect on failure before giving up.
-@todo guide might be a little incorrect about await/await_body
+retry_timeout (5000)::
-=== flush(ConnPid) -> ok
+Time between retries in milliseconds.
-ConnPid = pid():: The pid of the Gun connection process.
+trace (false)::
-Flush all messages from the Gun connection process from the mailbox.
+Whether to enable `dbg` tracing of the connection process. Should
+only be used during debugging.
-=== flush(StreamRef) -> ok
+transport - see below::
-StreamRef = reference():: Stream identifier.
+Whether to use SSL or plain TCP. The default varies depending on the
+port used. Port 443 defaults to `ssl`. All other ports default to `tcp`.
-Flush all messages related to the given stream.
+transport_opts ([])::
-=== cancel(ConnPid, StreamRef) -> ok
+Transport options. They are TCP options or SSL options depending on
+the selected transport.
-ConnPid = pid():: The pid of the Gun connection process.
-StreamRef = reference():: Identifier of the stream to cancel.
+ws_opts (#{})::
-Cancel the given stream.
+Options specific to the Websocket protocol.
-HTTP/1.1 streams can't be cancelled. Gun will simply silence
-the stream and stop relaying messages.
+=== req_opts()
-@todo Depending on the length
-@todo of a response Gun may also attempt to reconnect rather than
-@todo receive the entire response body.
+[source,erlang]
+----
+req_opts() :: #{
+ reply_to => pid()
+}
+----
-HTTP/2 streams can however be cancelled at any time.
+Configuration for a particular request.
-=== ws_upgrade(ConnPid, Path) -> ws_upgrade(ConnPid, Path, [])
+The default value is given next to the option name:
-Alias of `gun:ws_upgrade/3`.
+reply_to (`self()`)::
-=== ws_upgrade(ConnPid, Path, Headers) -> StreamRef
+The pid of the process that will receive the response messages.
-Similar to `gun:ws_upgrade/4`, except `WsOpts` is taken from
-the options given in the `gun:open/{2,3}` call when opening
-the connection.
+=== ws_opts()
-=== ws_upgrade(ConnPid, Path, Headers, WsOpts) -> StreamRef
+[source,erlang]
+----
+ws_opts() :: #{
+ compress => boolean()
+}
+----
-ConnPid = pid():: The pid of the Gun connection process.
-Path = iodata():: Path to the resource.
-Headers = [{binary(), iodata()}]:: Additional request headers.
-WsOpts = map():: Options for the Websocket connection.
+Configuration for the Websocket protocol.
-Request the connection to be upgraded to the Websocket protocol.
+The default value is given next to the option name:
-This function can only be used when the current protocol is `http`.
+compress => boolean()::
-=== ws_send(ConnPid, Frames) -> ok
+Whether to enable permessage-deflate compression. This does
+not guarantee that compression will be used as it is the
+server that ultimately decides. Defaults to false.
-ConnPid = pid():: The pid of the Gun connection process.
-Frames = @todo:: @todo
+// @todo Document default_protocol, protocols and user_opts.
-Send one or more Websocket frames.
+== See also
-This function can only be used following a successful `ws_upgrade` call.
+link:man:gun(7)[gun(7)]
diff --git a/doc/src/manual/gun.await.asciidoc b/doc/src/manual/gun.await.asciidoc
new file mode 100644
index 0000000..b96d643
--- /dev/null
+++ b/doc/src/manual/gun.await.asciidoc
@@ -0,0 +1,114 @@
+= gun:await(3)
+
+== Name
+
+gun:await - Wait for a response
+
+== Description
+
+[source,erlang]
+----
+await(ConnPid, StreamRef)
+ -> await(ConnPid, StreamRef, 5000, MonitorRef)
+
+await(ConnPid, StreamRef, MonitorRef)
+ -> await(ConnPid, StreamRef, 5000, MonitorRef)
+
+await(ConnPid, StreamRef, Timeout)
+ -> await(ConnPid, StreamRef, Timeout, MonitorRef)
+
+await(ConnPid, StreamRef, Timeout, MonitorRef)
+ -> Result
+
+ConnPid :: pid()
+StreamRef :: reference()
+MonitorRef :: reference()
+Timeout :: timeout()
+Result :: tuple() - see below
+----
+
+Wait for a response.
+
+This function waits for a message from the given stream and
+returns it as a tuple. An error will be returned should the
+process fail or a relevant message is not received within
+the specified duration.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream for the original request.
+
+Timeout::
+
+How long to wait for a message, in milliseconds.
+
+MonitorRef::
+
+Monitor for the Gun connection process.
++
+A monitor is automatically created for the duration of this
+call when one is not provided.
+
+== Return value
+
+A number of different tuples can be returned. They correspond
+to the message of the same name and they contain the same
+elements minus the pid and stream reference. Error tuples
+may also be returned when a timeout or an error occur.
+
+[source,erlang]
+----
+Result :: {inform, Status, Headers}
+ {response, IsFin, Status, Headers}
+ {data, IsFin, Data}
+ {trailers, Trailers}
+ {push, NewStreamRef, Method, URI, Headers}
+ {error, Reason}
+
+Reason :: timeout | any()
+----
+
+Because the messages and returned tuples are equivalent,
+please refer to the manual pages for each message for
+further information:
+
+* link:man:gun_push(3)[gun_push(3)] - Server-initiated push
+* link:man:gun_inform(3)[gun_inform(3)] - Informational response
+* link:man:gun_response(3)[gun_response(3)] - Response
+* link:man:gun_data(3)[gun_data(3)] - Response body
+* link:man:gun_trailers(3)[gun_trailers(3)] - Response trailers
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Wait for a response
+[source,erlang]
+----
+StreamRef = gun:get(ConnPid, "/articles", [
+ {<<"accept">>, <<"text/html;q=1.0, application/xml;q=0.1">>}
+]).
+{response, nofin, 200, _Headers} = gun:await(ConnPid, StreamRef).
+{data, fin, <<"Hello world!">>} = gun:await(ConnPid, StreamRef).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:get(3)[gun:get(3)],
+link:man:gun:head(3)[gun:head(3)],
+link:man:gun:options(3)[gun:options(3)],
+link:man:gun:patch(3)[gun:patch(3)],
+link:man:gun:post(3)[gun:post(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun:delete(3)[gun:delete(3)],
+link:man:gun:request(3)[gun:request(3)],
+link:man:gun:await_body(3)[gun:await_body(3)]
diff --git a/doc/src/manual/gun.await_body.asciidoc b/doc/src/manual/gun.await_body.asciidoc
new file mode 100644
index 0000000..ac6a8c4
--- /dev/null
+++ b/doc/src/manual/gun.await_body.asciidoc
@@ -0,0 +1,88 @@
+= gun:await_body(3)
+
+== Name
+
+gun:await_body - Wait for the complete response body
+
+== Description
+
+[source,erlang]
+----
+await_body(ConnPid, StreamRef)
+ -> await_body(ConnPid, StreamRef, 5000, MonitorRef)
+
+await_body(ConnPid, StreamRef, MonitorRef)
+ -> await_body(ConnPid, StreamRef, 5000, MonitorRef)
+
+await_body(ConnPid, StreamRef, Timeout)
+ -> await_body(ConnPid, StreamRef, Timeout, MonitorRef)
+
+await_body(ConnPid, StreamRef, Timeout, MonitorRef)
+ -> {ok, Body} | {ok, Body, Trailers} | {error, Reason}
+
+ConnPid :: pid()
+StreamRef :: reference()
+MonitorRef :: reference()
+Timeout :: timeout()
+Body :: binary()
+Trailers :: [{binary(), binary()}]
+Reason :: timeout | any()
+----
+
+Wait for the complete response body.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream for the original request.
+
+Timeout::
+
+How long to wait for each message, in milliseconds.
+
+MonitorRef::
+
+Monitor for the Gun connection process.
++
+A monitor is automatically created for the duration of this
+call when one is not provided.
+
+== Return value
+
+The body is returned, possibly with trailers if the
+request contained a `te: trailers` header. Error tuples
+may also be returned when a timeout or an error occur.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Wait for the complete response body
+[source,erlang]
+----
+StreamRef = gun:get(ConnPid, "/articles", [
+ {<<"accept">>, <<"text/html;q=1.0, application/xml;q=0.1">>}
+]).
+{response, nofin, 200, _Headers} = gun:await(ConnPid, StreamRef).
+{ok, _Body} = gun:await_body(ConnPid, StreamRef).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:get(3)[gun:get(3)],
+link:man:gun:head(3)[gun:head(3)],
+link:man:gun:options(3)[gun:options(3)],
+link:man:gun:patch(3)[gun:patch(3)],
+link:man:gun:post(3)[gun:post(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun:delete(3)[gun:delete(3)],
+link:man:gun:request(3)[gun:request(3)],
+link:man:gun:await(3)[gun:await(3)]
diff --git a/doc/src/manual/gun.await_up.asciidoc b/doc/src/manual/gun.await_up.asciidoc
new file mode 100644
index 0000000..3937665
--- /dev/null
+++ b/doc/src/manual/gun.await_up.asciidoc
@@ -0,0 +1,73 @@
+= gun:await_up(3)
+
+== Name
+
+gun:await_up - Wait for the connection to be up
+
+== Description
+
+[source,erlang]
+----
+await_up(ConnPid)
+ -> await_up(ConnPid, 5000, MonitorRef)
+
+await_up(ConnPid, MonitorRef)
+ -> await_up(ConnPid, 5000, MonitorRef)
+
+await_up(ConnPid, Timeout)
+ -> await_up(ConnPid, Timeout, MonitorRef)
+
+await_up(ConnPid, Timeout, MonitorRef)
+ -> {ok, Protocol} | {error, Reason}
+
+ConnPid :: pid()
+MonitorRef :: reference()
+Timeout :: timeout()
+Protocol :: http | http2
+Reason :: timeout | any()
+----
+
+Wait for the connection to be up.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Timeout::
+
+How long to wait for, in milliseconds.
+
+MonitorRef::
+
+Monitor for the Gun connection process.
++
+A monitor is automatically created for the duration of this
+call when one is not provided.
+
+== Return value
+
+The protocol selected for this connection. It can be used
+to determine the capabilities of the server. Error tuples
+may also be returned when a timeout or an error occur.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Wait for the connection to be up
+[source,erlang]
+----
+{ok, ConnPid} = gun:open("example.org", 443).
+{ok, _} = gun:await_up(ConnPid).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:open(3)[gun:open(3)],
+link:man:gun:open_unix(3)[gun:open_unix(3)],
+link:man:gun_up(3)[gun_up(3)]
diff --git a/doc/src/manual/gun.cancel.asciidoc b/doc/src/manual/gun.cancel.asciidoc
new file mode 100644
index 0000000..bc2bab9
--- /dev/null
+++ b/doc/src/manual/gun.cancel.asciidoc
@@ -0,0 +1,68 @@
+= gun:cancel(3)
+
+== Name
+
+gun:cancel - Cancel the given stream
+
+== Description
+
+[source,erlang]
+----
+cancel(ConnPid, StreamRef) -> ok
+
+ConnPid :: pid()
+StreamRef :: reference()
+----
+
+Cancel the given stream.
+
+The behavior of this function depends on the protocol
+selected.
+
+HTTP/1.1 does not support this feature. Gun will simply
+silence the stream and stop relaying messages. Gun may
+also decide to close the connection if the response body
+is too large, to avoid wasting time and bandwidth.
+
+HTTP/2 allows cancelling streams at any time.
+
+This function is asynchronous. Messages related to this
+stream may still be sent after the function returns.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream for the original request.
+
+== Return value
+
+The atom `ok` is returned.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Cancel a stream
+[source,erlang]
+----
+gun:cancel(ConnPid, StreamRef).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:get(3)[gun:get(3)],
+link:man:gun:head(3)[gun:head(3)],
+link:man:gun:options(3)[gun:options(3)],
+link:man:gun:patch(3)[gun:patch(3)],
+link:man:gun:post(3)[gun:post(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun:delete(3)[gun:delete(3)],
+link:man:gun:request(3)[gun:request(3)]
diff --git a/doc/src/manual/gun.close.asciidoc b/doc/src/manual/gun.close.asciidoc
new file mode 100644
index 0000000..20fd1bf
--- /dev/null
+++ b/doc/src/manual/gun.close.asciidoc
@@ -0,0 +1,44 @@
+= gun:close(3)
+
+== Name
+
+gun:close - Brutally close the connection
+
+== Description
+
+[source,erlang]
+----
+close(ConnPid) -> ok
+
+ConnPid :: pid()
+----
+
+Brutally close the connection.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+== Return value
+
+The atom `ok` is returned.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Close the connection
+[source,erlang]
+----
+ok = gun:close(ConnPid).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:open(3)[gun:open(3)],
+link:man:gun:open_unix(3)[gun:open_unix(3)]
diff --git a/doc/src/manual/gun.data.asciidoc b/doc/src/manual/gun.data.asciidoc
new file mode 100644
index 0000000..9c65d34
--- /dev/null
+++ b/doc/src/manual/gun.data.asciidoc
@@ -0,0 +1,75 @@
+= gun:data(3)
+
+== Name
+
+gun:data - Stream the body of a request
+
+== Description
+
+[source,erlang]
+----
+data(ConnPid, StreamRef, IsFin, Data) -> ok
+
+ConnPid :: pid()
+StreamRef :: reference()
+IsFin :: fin | nofin
+Data :: iodata()
+----
+
+Stream the body of a request.
+
+This function can only be used if the original request
+had headers indicating that a body would be streamed.
+
+All calls to this function must use the `nofin` flag
+except for the last which must use `fin` to indicate
+the end of the request body.
+
+Empty data is allowed regardless of the value of `IsFin`.
+Gun may or may not send empty data chunks, however.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream for the original request.
+
+IsFin::
+
+Whether this message terminates the request.
+
+Data::
+
+All or part of the response body.
+
+== Return value
+
+The atom `ok` is returned.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Stream the body of a request
+[source,erlang]
+----
+StreamRef = gun:put(ConnPid, "/lang/fr_FR/hello", [
+ {<<"content-type">>, <<"text/plain">>}
+]).
+gun:data(ConnPid, StreamRef, nofin, <<"Bonjour !\n">>).
+gun:data(ConnPid, StreamRef, fin, <<"Bonsoir !\n">>).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:patch(3)[gun:patch(3)],
+link:man:gun:post(3)[gun:post(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun:request(3)[gun:request(3)]
diff --git a/doc/src/manual/gun.delete.asciidoc b/doc/src/manual/gun.delete.asciidoc
new file mode 100644
index 0000000..feb64ff
--- /dev/null
+++ b/doc/src/manual/gun.delete.asciidoc
@@ -0,0 +1,82 @@
+= gun:delete(3)
+
+== Name
+
+gun:delete - Delete a resource
+
+== Description
+
+[source,erlang]
+----
+delete(ConnPid, Path)
+ -> delete(ConnPid, Path, [], #{}).
+
+delete(ConnPid, Path, Headers)
+ -> delete(ConnPid, Path, Headers, #{})
+
+delete(ConnPid, Path, Headers, ReqOpts)
+ -> StreamRef
+
+ConnPid :: pid()
+Path :: iodata()
+Headers :: [{binary(), iodata()}]
+ReqOpts :: gun:req_opts()
+StreamRef :: reference()
+----
+
+Delete a resource.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Path::
+
+Path to the resource.
+
+Headers::
+
+Additional request headers.
+
+ReqOpts::
+
+Request options.
+
+== Return value
+
+A reference that identifies the newly created stream is
+returned. It is this reference that must be passed in
+subsequent calls and will be received in messages related
+to this new stream.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Delete a resource
+[source,erlang]
+----
+StreamRef = gun:delete(ConnPid, "/drafts/123").
+----
+
+.Delete a resource with request options
+[source,erlang]
+----
+StreamRef = gun:delete(ConnPid, "/drafts/123", [],
+ #{reply_to => ReplyToPid}).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun:await(3)[gun:await(3)],
+link:man:gun:await_body(3)[gun:await_body(3)],
+link:man:gun_push(3)[gun_push(3)],
+link:man:gun_inform(3)[gun_inform(3)],
+link:man:gun_response(3)[gun_response(3)],
+link:man:gun_data(3)[gun_data(3)]
diff --git a/doc/src/manual/gun.flush.asciidoc b/doc/src/manual/gun.flush.asciidoc
new file mode 100644
index 0000000..b6424a9
--- /dev/null
+++ b/doc/src/manual/gun.flush.asciidoc
@@ -0,0 +1,59 @@
+= gun:flush(3)
+
+== Name
+
+gun:flush - Flush all messages related to a connection or a stream
+
+== Description
+
+[source,erlang]
+----
+flush(ConnPid) -> ok
+flush(StreamRef) -> ok
+
+ConnPid :: pid()
+StreamRef :: reference()
+----
+
+Flush all messages related to a connection or a stream.
+
+== Arguments
+
+Either of these arguments may be provided:
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream for the original request.
+
+== Return value
+
+The atom `ok` is returned.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Flush all messages from a connection
+[source,erlang]
+----
+gun:flush(ConnPid).
+----
+
+.Flush messages from a single stream
+[source,erlang]
+----
+gun:flush(StreamRef).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:await(3)[gun:await(3)],
+link:man:gun:await_body(3)[gun:await_body(3)],
+link:man:gun:await_up(3)[gun:await_up(3)]
diff --git a/doc/src/manual/gun.get.asciidoc b/doc/src/manual/gun.get.asciidoc
new file mode 100644
index 0000000..623c038
--- /dev/null
+++ b/doc/src/manual/gun.get.asciidoc
@@ -0,0 +1,85 @@
+= gun:get(3)
+
+== Name
+
+gun:get - Get a resource representation
+
+== Description
+
+[source,erlang]
+----
+get(ConnPid, Path)
+ -> get(ConnPid, Path, [], #{}).
+
+get(ConnPid, Path, Headers)
+ -> get(ConnPid, Path, Headers, #{})
+
+get(ConnPid, Path, Headers, ReqOpts)
+ -> StreamRef
+
+ConnPid :: pid()
+Path :: iodata()
+Headers :: [{binary(), iodata()}]
+ReqOpts :: gun:req_opts()
+StreamRef :: reference()
+----
+
+Get a resource representation.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Path::
+
+Path to the resource.
+
+Headers::
+
+Additional request headers.
+
+ReqOpts::
+
+Request options.
+
+== Return value
+
+A reference that identifies the newly created stream is
+returned. It is this reference that must be passed in
+subsequent calls and will be received in messages related
+to this new stream.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Get a resource representation
+[source,erlang]
+----
+StreamRef = gun:get(ConnPid, "/articles", [
+ {<<"accept">>, <<"text/html;q=1.0, application/xml;q=0.1">>}
+]).
+----
+
+.Get a resource representation with request options
+[source,erlang]
+----
+StreamRef = gun:get(ConnPid, "/articles", [], #{
+ reply_to => ReplyToPid
+}).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:head(3)[gun:head(3)],
+link:man:gun:await(3)[gun:await(3)],
+link:man:gun:await_body(3)[gun:await_body(3)],
+link:man:gun_push(3)[gun_push(3)],
+link:man:gun_inform(3)[gun_inform(3)],
+link:man:gun_response(3)[gun_response(3)],
+link:man:gun_data(3)[gun_data(3)]
diff --git a/doc/src/manual/gun.head.asciidoc b/doc/src/manual/gun.head.asciidoc
new file mode 100644
index 0000000..3d92e38
--- /dev/null
+++ b/doc/src/manual/gun.head.asciidoc
@@ -0,0 +1,92 @@
+= gun:head(3)
+
+== Name
+
+gun:head - Get headers of a resource representation
+
+== Description
+
+[source,erlang]
+----
+head(ConnPid, Path)
+ -> head(ConnPid, Path, [], #{}).
+
+head(ConnPid, Path, Headers)
+ -> head(ConnPid, Path, Headers, #{})
+
+head(ConnPid, Path, Headers, ReqOpts)
+ -> StreamRef
+
+ConnPid :: pid()
+Path :: iodata()
+Headers :: [{binary(), iodata()}]
+ReqOpts :: gun:req_opts()
+StreamRef :: reference()
+----
+
+Get headers of a resource representation.
+
+This function performs the same operation as
+link:man:gun:get(3)[gun:get(3)], except the server will not
+send the resource representation, only the response's status
+code and headers.
+
+While servers are supposed to send the same headers as for
+a GET request, they sometimes will not. For example the
+`content-length` header may be dropped from the response.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Path::
+
+Path to the resource.
+
+Headers::
+
+Additional request headers.
+
+ReqOpts::
+
+Request options.
+
+== Return value
+
+A reference that identifies the newly created stream is
+returned. It is this reference that must be passed in
+subsequent calls and will be received in messages related
+to this new stream.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Get headers of a resource representation
+[source,erlang]
+----
+StreamRef = gun:head(ConnPid, "/articles", [
+ {<<"accept">>, <<"text/html;q=1.0, application/xml;q=0.1">>}
+]).
+----
+
+.Get headers of a resource representation with request options
+[source,erlang]
+----
+StreamRef = gun:head(ConnPid, "/articles", [], #{
+ reply_to => ReplyToPid
+}).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:get(3)[gun:head(3)],
+link:man:gun:await(3)[gun:await(3)],
+link:man:gun_push(3)[gun_push(3)],
+link:man:gun_inform(3)[gun_inform(3)],
+link:man:gun_response(3)[gun_response(3)]
diff --git a/doc/src/manual/gun.info.asciidoc b/doc/src/manual/gun.info.asciidoc
new file mode 100644
index 0000000..ca7e47a
--- /dev/null
+++ b/doc/src/manual/gun.info.asciidoc
@@ -0,0 +1,49 @@
+= gun:info(3)
+
+== Name
+
+gun:info - Obtain information about the connection
+
+== Description
+
+[source,erlang]
+----
+info(ConnPid) -> Info
+
+ConnPid :: pid()
+Info :: #{
+ sock_ip => inet:ip_address(),
+ sock_port => inet:port_number()
+}
+----
+
+Obtain information about the connection.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+== Return value
+
+A map is returned containing various informations about
+the connection.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Obtain information about the connection
+[source,erlang]
+----
+Info = gun:info(ConnPid).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:open(3)[gun:open(3)],
+link:man:gun:open_unix(3)[gun:open_unix(3)]
diff --git a/doc/src/manual/gun.open.asciidoc b/doc/src/manual/gun.open.asciidoc
new file mode 100644
index 0000000..2e6c8b9
--- /dev/null
+++ b/doc/src/manual/gun.open.asciidoc
@@ -0,0 +1,72 @@
+= gun:open(3)
+
+== Name
+
+gun:open - Open a connection to the given host and port
+
+== Description
+
+[source,erlang]
+----
+open(Host, Port) -> open(Host, Port, #{})
+open(Host, Port, Opts) -> {ok, pid()} | {error, any()}
+
+Host :: inet:hostname() | inet:ip_address()
+Port :: inet:port_number()
+Opts :: gun:opts()
+----
+
+Open a connection to the given host and port.
+
+== Arguments
+
+Host::
+
+Host or IP address to connect to.
+
+Port::
+
+Port to connect to.
+
+Opts::
+
+Options for this connection.
+
+== Return value
+
+The pid of the newly created Gun process is returned.
+Note that this does not indicate that the connection
+has been successfully opened; the link:man:gun_up(3)[gun_up(3)]
+message will be sent for that.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Connect to a server
+[source,erlang]
+----
+{ok, ConnPid} = gun:open("example.org", 443).
+----
+
+.Connect to a server with custom options
+[source,erlang]
+----
+{ok, ConnPid} = gun:open("example.org", 443,
+ #{protocols => [http2]}).
+----
+
+.Connect to a server using its IP address
+[source,erlang]
+----
+{ok, ConnPid} = gun:open({127,0,0,1}, 443).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:open_unix(3)[gun:open_unix(3)],
+link:man:gun:await_up(3)[gun:await_up(3)],
+link:man:gun_up(3)[gun_up(3)]
diff --git a/doc/src/manual/gun.open_unix.asciidoc b/doc/src/manual/gun.open_unix.asciidoc
new file mode 100644
index 0000000..225ecc8
--- /dev/null
+++ b/doc/src/manual/gun.open_unix.asciidoc
@@ -0,0 +1,60 @@
+= gun:open_unix(3)
+
+== Name
+
+gun:open_unix - Open a connection to the given Unix domain socket
+
+== Description
+
+[source,erlang]
+----
+open_unix(SocketPath, Opts) -> {ok, pid()} | {error, any()}
+
+SocketPath :: string()
+Opts :: gun:opts()
+----
+
+Open a connection to the given Unix domain socket.
+
+== Arguments
+
+SocketPath::
+
+Path to the Unix domain socket to connect to.
+
+Opts::
+
+Options for this connection.
+
+== Return value
+
+The pid of the newly created Gun process is returned.
+Note that this does not indicate that the connection
+has been successfully opened; the link:man:gun_up(3)[gun_up(3)]
+message will be sent for that.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Connect to a server via a Unix domain socket
+[source,erlang]
+----
+{ok, ConnPid} = gun:open_unix("/var/run/dbus/system_bus_socket", #{}).
+----
+
+.Connect to a server via a Unix domain socket with custom options
+[source,erlang]
+----
+{ok, ConnPid} = gun:open_unix("/var/run/dbus/system_bus_socket",
+ #{protocols => [http2]}).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:open(3)[gun:open(3)],
+link:man:gun:await_up(3)[gun:await_up(3)],
+link:man:gun_up(3)[gun_up(3)]
diff --git a/doc/src/manual/gun.options.asciidoc b/doc/src/manual/gun.options.asciidoc
new file mode 100644
index 0000000..5b36f22
--- /dev/null
+++ b/doc/src/manual/gun.options.asciidoc
@@ -0,0 +1,83 @@
+= gun:options(3)
+
+== Name
+
+gun:options - Query the capabilities of the server or a resource
+
+== Description
+
+[source,erlang]
+----
+options(ConnPid, Path)
+ -> options(ConnPid, Path, [], #{}).
+
+options(ConnPid, Path, Headers)
+ -> options(ConnPid, Path, Headers, #{})
+
+options(ConnPid, Path, Headers, ReqOpts)
+ -> StreamRef
+
+ConnPid :: pid()
+Path :: iodata()
+Headers :: [{binary(), iodata()}]
+ReqOpts :: gun:req_opts()
+StreamRef :: reference()
+----
+
+Query the capabilities of the server or a resource.
+
+The special path `"*"` can be used to obtain information about
+the server as a whole. Any other path will return information
+about that resource specifically.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Path::
+
+Path to the resource.
+
+Headers::
+
+Additional request headers.
+
+ReqOpts::
+
+Request options.
+
+== Return value
+
+A reference that identifies the newly created stream is
+returned. It is this reference that must be passed in
+subsequent calls and will be received in messages related
+to this new stream.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Query the capabilities of the server
+[source,erlang]
+----
+StreamRef = gun:options(ConnPid, "*").
+----
+
+.Query the capabilities of a resource
+[source,erlang]
+----
+StreamRef = gun:options(ConnPid, "/articles").
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:await(3)[gun:await(3)],
+link:man:gun:await_body(3)[gun:await_body(3)],
+link:man:gun_inform(3)[gun_inform(3)],
+link:man:gun_response(3)[gun_response(3)],
+link:man:gun_data(3)[gun_data(3)]
diff --git a/doc/src/manual/gun.patch.asciidoc b/doc/src/manual/gun.patch.asciidoc
new file mode 100644
index 0000000..3f7baa9
--- /dev/null
+++ b/doc/src/manual/gun.patch.asciidoc
@@ -0,0 +1,119 @@
+= gun:patch(3)
+
+== Name
+
+gun:patch - Apply a set of changes to a resource
+
+== Description
+
+[source,erlang]
+----
+patch(ConnPid, Path, Headers)
+ -> StreamRef
+
+patch(ConnPid, Path, Headers, Body)
+ -> patch(ConnPid, Path, Headers, Body, #{})
+
+patch(ConnPid, Path, Headers, Body, ReqOpts)
+ -> StreamRef
+
+ConnPid :: pid()
+Path :: iodata()
+Headers :: [{binary(), iodata()}]
+Body :: iodata()
+ReqOpts :: gun:req_opts()
+StreamRef :: reference()
+----
+
+Apply a set of changes to a resource.
+
+The behavior of this function varies depending on whether
+a body is provided.
+
+The function `patch/3` expects either a content-length
+or content-type header to indicate that a body will be
+sent afterwards. The body can then be sent using
+link:man:gun:data(3)[gun:data(3)].
+
+The function `patch/4,5` sends the entire request, including
+the request body, immediately. It is therefore not possible
+to use link:man:gun:data(3)[gun:data(3)] after that. You
+should provide a content-type header. Gun will set the
+content-length header automatically.
+
+The body sent in this request should be a patch document
+with instructions on how to update the resource.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Path::
+
+Path to the resource.
+
+Headers::
+
+Additional request headers.
+
+Body::
+
+Request body.
+
+ReqOpts::
+
+Request options.
+
+== Return value
+
+A reference that identifies the newly created stream is
+returned. It is this reference that must be passed in
+subsequent calls and will be received in messages related
+to this new stream.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Patch a resource
+[source,erlang]
+----
+StreamRef = gun:patch(ConnPid, "/users/1",
+ [{<<"content-type">>, <<"application/json-patch+json">>}],
+ <<"[{\"op\":\"add\",\"path\":\"/baz\",\"value\":\"qux\"}]">>).
+----
+
+.Patch a resource in multiple calls
+[source,erlang]
+----
+StreamRef = gun:patch(ConnPid, "/users/1", [
+ {<<"content-type">>, <<"application/json-patch+json">>}
+]).
+gun:data(ConnPid, StreamRef, fin,
+ <<"[{\"op\":\"add\",\"path\":\"/baz\",\"value\":\"qux\"}]">>).
+----
+
+.Patch a resource with request options
+[source,erlang]
+----
+StreamRef = gun:patch(ConnPid, "/users/1",
+ [{<<"content-type">>, <<"application/json-patch+json">>}],
+ <<"[{\"op\":\"add\",\"path\":\"/baz\",\"value\":\"qux\"}]">>,
+ #{reply_to => ReplyToPid}).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:post(3)[gun:post(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun:await(3)[gun:await(3)],
+link:man:gun:await_body(3)[gun:await_body(3)],
+link:man:gun_push(3)[gun_push(3)],
+link:man:gun_inform(3)[gun_inform(3)],
+link:man:gun_response(3)[gun_response(3)],
+link:man:gun_data(3)[gun_data(3)]
diff --git a/doc/src/manual/gun.post.asciidoc b/doc/src/manual/gun.post.asciidoc
new file mode 100644
index 0000000..e548824
--- /dev/null
+++ b/doc/src/manual/gun.post.asciidoc
@@ -0,0 +1,116 @@
+= gun:post(3)
+
+== Name
+
+gun:post - Process the enclosed representation according to a resource's own semantics
+
+== Description
+
+[source,erlang]
+----
+post(ConnPid, Path, Headers)
+ -> StreamRef
+
+post(ConnPid, Path, Headers, Body)
+ -> post(ConnPid, Path, Headers, Body, #{})
+
+post(ConnPid, Path, Headers, Body, ReqOpts)
+ -> StreamRef
+
+ConnPid :: pid()
+Path :: iodata()
+Headers :: [{binary(), iodata()}]
+Body :: iodata()
+ReqOpts :: gun:req_opts()
+StreamRef :: reference()
+----
+
+Process the enclosed representation according to a resource's
+own semantics.
+
+The behavior of this function varies depending on whether
+a body is provided.
+
+The function `post/3` expects either a content-length
+or content-type header to indicate that a body will be
+sent afterwards. The body can then be sent using
+link:man:gun:data(3)[gun:data(3)].
+
+The function `post/4,5` sends the entire request, including
+the request body, immediately. It is therefore not possible
+to use link:man:gun:data(3)[gun:data(3)] after that. You
+should provide a content-type header. Gun will set the
+content-length header automatically.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Path::
+
+Path to the resource.
+
+Headers::
+
+Additional request headers.
+
+Body::
+
+Request body.
+
+ReqOpts::
+
+Request options.
+
+== Return value
+
+A reference that identifies the newly created stream is
+returned. It is this reference that must be passed in
+subsequent calls and will be received in messages related
+to this new stream.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Post to a resource
+[source,erlang]
+----
+StreamRef = gun:post(ConnPid, "/search",
+ [{<<"content-type">>, <<"application/x-www-form-urlencoded">>}],
+ <<"q=nine%20nines">>).
+----
+
+.Post to a resource in multiple calls
+[source,erlang]
+----
+StreamRef = gun:post(ConnPid, "/search", [
+ {<<"content-type">>, <<"application/x-www-form-urlencoded">>}
+]).
+gun:data(ConnPid, StreamRef, fin, <<"q=nine%20nines">>).
+----
+
+.Post to a resource with request options
+[source,erlang]
+----
+StreamRef = gun:post(ConnPid, "/search",
+ [{<<"content-type">>, <<"application/x-www-form-urlencoded">>}],
+ <<"q=nine%20nines">>,
+ #{reply_to => ReplyToPid}).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:patch(3)[gun:patch(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun:await(3)[gun:await(3)],
+link:man:gun:await_body(3)[gun:await_body(3)],
+link:man:gun_push(3)[gun_push(3)],
+link:man:gun_inform(3)[gun_inform(3)],
+link:man:gun_response(3)[gun_response(3)],
+link:man:gun_data(3)[gun_data(3)]
diff --git a/doc/src/manual/gun.put.asciidoc b/doc/src/manual/gun.put.asciidoc
new file mode 100644
index 0000000..4f0cb39
--- /dev/null
+++ b/doc/src/manual/gun.put.asciidoc
@@ -0,0 +1,115 @@
+= gun:put(3)
+
+== Name
+
+gun:put - Create or replace a resource
+
+== Description
+
+[source,erlang]
+----
+put(ConnPid, Path, Headers)
+ -> StreamRef
+
+put(ConnPid, Path, Headers, Body)
+ -> put(ConnPid, Path, Headers, Body, #{})
+
+put(ConnPid, Path, Headers, Body, ReqOpts)
+ -> StreamRef
+
+ConnPid :: pid()
+Path :: iodata()
+Headers :: [{binary(), iodata()}]
+Body :: iodata()
+ReqOpts :: gun:req_opts()
+StreamRef :: reference()
+----
+
+Create or replace a resource.
+
+The behavior of this function varies depending on whether
+a body is provided.
+
+The function `put/3` expects either a content-length
+or content-type header to indicate that a body will be
+sent afterwards. The body can then be sent using
+link:man:gun:data(3)[gun:data(3)].
+
+The function `put/4,5` sends the entire request, including
+the request body, immediately. It is therefore not possible
+to use link:man:gun:data(3)[gun:data(3)] after that. You
+should provide a content-type header. Gun will set the
+content-length header automatically.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Path::
+
+Path to the resource.
+
+Headers::
+
+Additional request headers.
+
+Body::
+
+Request body.
+
+ReqOpts::
+
+Request options.
+
+== Return value
+
+A reference that identifies the newly created stream is
+returned. It is this reference that must be passed in
+subsequent calls and will be received in messages related
+to this new stream.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Put a resource
+[source,erlang]
+----
+StreamRef = gun:put(ConnPid, "/lang/fr_FR/hello",
+ [{<<"content-type">>, <<"text/plain">>}],
+ <<"Bonjour !">>).
+----
+
+.Put a resource in multiple calls
+[source,erlang]
+----
+StreamRef = gun:put(ConnPid, "/lang/fr_FR/hello", [
+ {<<"content-type">>, <<"text/plain">>}
+]).
+gun:data(ConnPid, StreamRef, fin, <<"Bonjour !">>).
+----
+
+.Put a resource with request options
+[source,erlang]
+----
+StreamRef = gun:put(ConnPid, "/lang/fr_FR/hello",
+ [{<<"content-type">>, <<"text/plain">>}],
+ <<"Bonjour !">>,
+ #{reply_to => ReplyToPid}).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:patch(3)[gun:patch(3)],
+link:man:gun:post(3)[gun:post(3)],
+link:man:gun:await(3)[gun:await(3)],
+link:man:gun:await_body(3)[gun:await_body(3)],
+link:man:gun_push(3)[gun_push(3)],
+link:man:gun_inform(3)[gun_inform(3)],
+link:man:gun_response(3)[gun_response(3)],
+link:man:gun_data(3)[gun_data(3)]
diff --git a/doc/src/manual/gun.request.asciidoc b/doc/src/manual/gun.request.asciidoc
new file mode 100644
index 0000000..ec169ac
--- /dev/null
+++ b/doc/src/manual/gun.request.asciidoc
@@ -0,0 +1,105 @@
+= gun:request(3)
+
+== Name
+
+gun:request - Perform the given request
+
+== Description
+
+[source,erlang]
+----
+request(ConnPid, Method, Path, Headers)
+ -> StreamRef
+
+request(ConnPid, Method, Path, Headers, Body)
+ -> request(ConnPid, Method, Path, Headers, Body, #{})
+
+request(ConnPid, Method, Path, Headers, Body, ReqOpts)
+ -> StreamRef
+
+ConnPid :: pid()
+Method :: binary()
+Path :: iodata()
+Headers :: [{binary(), iodata()}]
+Body :: iodata()
+ReqOpts :: gun:req_opts()
+StreamRef :: reference()
+----
+
+Perform the given request.
+
+This is a general purpose function that should only be
+used when other method-specific functions do not apply.
+
+The behavior of this function varies depending on whether
+a body is provided.
+
+The function `request/4` expects either a content-length
+or content-type header to indicate that a body will be
+sent afterwards. Gun will assume the request has no body
+otherwise. The body can then be sent using
+link:man:gun:data(3)[gun:data(3)].
+
+The function `request/5,6` sends the entire request, including
+the request body, immediately. It is therefore not possible
+to use link:man:gun:data(3)[gun:data(3)] after that. You
+should provide a content-type header. Gun will set the
+content-length header automatically.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Method::
+
+Method to be used for the request.
+
+Path::
+
+Path to the resource.
+
+Headers::
+
+Additional request headers.
+
+Body::
+
+Request body.
+
+ReqOpts::
+
+Request options.
+
+== Return value
+
+A reference that identifies the newly created stream is
+returned. It is this reference that must be passed in
+subsequent calls and will be received in messages related
+to this new stream.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Perform a request
+[source,erlang]
+----
+StreamRef = gun:request(ConnPid, <<"PUT">>,
+ "/lang/fr_FR/hello",
+ [{<<"content-type">>, <<"text/plain">>}],
+ <<"Bonjour !">>).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:await(3)[gun:await(3)],
+link:man:gun:await_body(3)[gun:await_body(3)],
+link:man:gun_push(3)[gun_push(3)],
+link:man:gun_inform(3)[gun_inform(3)],
+link:man:gun_response(3)[gun_response(3)],
+link:man:gun_data(3)[gun_data(3)]
diff --git a/doc/src/manual/gun.ws_send.asciidoc b/doc/src/manual/gun.ws_send.asciidoc
new file mode 100644
index 0000000..307cfae
--- /dev/null
+++ b/doc/src/manual/gun.ws_send.asciidoc
@@ -0,0 +1,65 @@
+= gun:ws_send(3)
+
+== Name
+
+gun:ws_send - Send one or more Websocket frame(s)
+
+== Description
+
+[source,erlang]
+----
+ws_send(ConnPid, Frames) -> ok
+
+ConnPid :: pid()
+Frames :: Frame | [Frame]
+Frame :: close | ping | pong
+ | {text | binary | close | ping | pong, iodata()}
+ | {close, non_neg_integer(), iodata()}
+----
+
+Send one or more Websocket frame(s).
+
+The connection must first be upgraded to Websocket using
+the function link:man:gun:ws_upgrade(3)[gun:ws_upgrade(3)].
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Frames::
+
+One or more Websocket frame(s).
+
+== Return value
+
+The atom `ok` is returned.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Send a single frame
+[source,erlang]
+----
+gun:ws_send(ConnPid, {text, <<"Hello world!">>}).
+----
+
+.Send many frames including a close frame
+[source,erlang]
+----
+gun:ws_send(ConnPid, [
+ {text, <<"See you later, world!">>},
+ close
+]).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:ws_upgrade(3)[gun:ws_upgrade(3)],
+link:man:gun_upgrade(3)[gun_upgrade(3)],
+link:man:gun_ws(3)[gun_ws(3)]
diff --git a/doc/src/manual/gun.ws_upgrade.asciidoc b/doc/src/manual/gun.ws_upgrade.asciidoc
new file mode 100644
index 0000000..cb9da06
--- /dev/null
+++ b/doc/src/manual/gun.ws_upgrade.asciidoc
@@ -0,0 +1,100 @@
+= gun:ws_upgrade(3)
+
+== Name
+
+gun:ws_upgrade - Upgrade to Websocket
+
+== Description
+
+[source,erlang]
+----
+ws_upgrade(ConnPid, Path)
+ -> ws_upgrade(ConnPid, Path, [])
+
+ws_upgrade(ConnPid, Path, Headers)
+ -> StreamRef
+
+ws_upgrade(ConnPid, Path, Headers, WsOpts)
+ -> StreamRef
+
+ConnPid :: pid()
+Path :: iodata()
+Headers :: [{binary(), iodata()}]
+WsOpts :: gun:ws_opts
+StreamRef :: reference()
+----
+
+Upgrade to Websocket.
+
+The behavior of this function depends on the protocol
+selected.
+
+HTTP/1.1 cannot handle Websocket and HTTP requests
+concurrently. The upgrade, if successful, will result
+in the complete takeover of the connection. Any
+subsequent HTTP requests will be rejected.
+
+Gun does not currently support Websocket over HTTP/2.
+
+By default Gun will take the Websocket options from
+the connection's `ws_opts`.
+
+== Arguments
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Path::
+
+Path to the resource.
+
+Headers::
+
+Additional request headers.
+
+WsOpts::
+
+Configuration for the Websocket protocol.
+
+== Return value
+
+A reference that identifies the newly created stream is
+returned. It is this reference that must be passed in
+subsequent calls and will be received in messages related
+to this new stream.
+
+== Changelog
+
+* *1.0*: Function introduced.
+
+== Examples
+
+.Upgrade to Websocket
+[source,erlang]
+----
+StreamRef = gun:ws_upgrade(ConnPid, "/ws", [
+ {<<"sec-websocket-protocol">>, <<"chat">>}
+]).
+receive
+ {gun_upgrade, ConnPid, StreamRef, [<<"websocket">>], _} ->
+ ok
+after 5000 ->
+ error(timeout)
+end.
+----
+
+.Upgrade to Websocket with different options
+[source,erlang]
+----
+StreamRef = gun:ws_upgrade(ConnPid, "/ws", [], #{
+ compress => false
+}).
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:ws_send(3)[gun:ws_send(3)],
+link:man:gun_upgrade(3)[gun_upgrade(3)],
+link:man:gun_ws(3)[gun_ws(3)]
diff --git a/doc/src/manual/gun_app.asciidoc b/doc/src/manual/gun_app.asciidoc
index 219a323..606d9fb 100644
--- a/doc/src/manual/gun_app.asciidoc
+++ b/doc/src/manual/gun_app.asciidoc
@@ -2,23 +2,40 @@
== Name
-gun - Erlang HTTP client with support for HTTP/1.1, HTTP/2 and Websocket.
+gun - HTTP/1.1, HTTP/2 and Websocket client for Erlang/OTP
+
+== Description
+
+Gun is an HTTP client for Erlang/OTP with support for the
+HTTP/1.1, HTTP/2 and Websocket protocols.
+
+Gun aims to provide an easy to use, asynchronous and
+always-connected client. It maintains a permanent connection
+to the server and reconnects automatically when necessary.
+
+== Modules
+
+* link:man:gun(3)[gun(3)] - Asynchronous HTTP client
== Dependencies
-The `gun` application uses the Erlang applications `ranch`
-for abstracting TCP and TLS over a common interface, and
-the `ssl` application for TLS support, required for HTTPS
-and secure HTTP/2 support. In addition, Gun requires the `crypto`
-application (a dependency of `ssl`) for Websocket.
+// @todo I do not want a dependency on Ranch, remove it
+* link:man:cowlib(7)[cowlib(7)] - Support library for manipulating Web protocols
+* ssl - Secure communication over sockets
+
+All these applications must be started before the `gun`
+application. To start Gun and all dependencies at once:
-These dependencies must be started for the `gun`
-application to work. In an embedded environment
-this means that they need to be started with the
-`application:start/{1,2}` function before the `gun`
-application is started.
+[source,erlang]
+----
+{ok, _} = application:ensure_all_started(gun).
+----
== Environment
The `gun` application does not define any application
environment configuration parameters.
+
+== See also
+
+link:man:cowlib(7)[cowlib(7)]
diff --git a/doc/src/manual/gun_data.asciidoc b/doc/src/manual/gun_data.asciidoc
new file mode 100644
index 0000000..0176707
--- /dev/null
+++ b/doc/src/manual/gun_data.asciidoc
@@ -0,0 +1,77 @@
+= gun_data(3)
+
+== Name
+
+gun_data - Response body
+
+== Description
+
+[source,erlang]
+----
+{gun_data, ConnPid, StreamRef, IsFin, Data}
+
+ConnPid :: pid()
+StreamRef :: reference()
+IsFin :: fin | nofin
+Data :: binary()
+----
+
+Response body.
+
+This message informs the relevant process that the server
+sent a all or part of the body for the response to the
+original request.
+
+A data message is always preceded by a response message.
+
+The response body may be terminated either by a data
+message with the flag `fin` set or by a
+link:man:gun_trailers(3)[gun_trailers(3)] message.
+
+== Elements
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream for the original request.
+
+IsFin::
+
+Whether this message terminates the response.
+
+Data::
+
+All or part of the response body.
+
+== Changelog
+
+* *1.0*: Message introduced.
+
+== Examples
+
+.Receive a gun_data message in a gen_server
+[source,erlang]
+----
+handle_info({gun_data, ConnPid, _StreamRef,
+ _IsFin, _Data},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State}.
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:get(3)[gun:get(3)],
+link:man:gun:head(3)[gun:head(3)],
+link:man:gun:patch(3)[gun:patch(3)],
+link:man:gun:post(3)[gun:post(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun:delete(3)[gun:delete(3)],
+link:man:gun:options(3)[gun:options(3)],
+link:man:gun:request(3)[gun:request(3)],
+link:man:gun_response(3)[gun_response(3)],
+link:man:gun_trailers(3)[gun_trailers(3)]
diff --git a/doc/src/manual/gun_down.asciidoc b/doc/src/manual/gun_down.asciidoc
new file mode 100644
index 0000000..67c7796
--- /dev/null
+++ b/doc/src/manual/gun_down.asciidoc
@@ -0,0 +1,86 @@
+= gun_down(3)
+
+== Name
+
+gun_down - The connection is down
+
+== Description
+
+[source,erlang]
+----
+{gun_down, ConnPid, Protocol, Reason, KilledStreams, UnprocessedStreams}
+
+ConnPid :: pid()
+Protocol :: http | http2 | ws
+Reason :: any()
+KilledStreams :: [reference()]
+UnprocessedStreams :: [reference()]
+----
+
+The connection is down.
+
+This message informs the owner process that the connection
+was lost. Depending on the `retry` and `retry_timeout`
+options Gun may automatically attempt to reconnect.
+
+When the connection goes back up, Gun will not attempt to retry
+requests. It will also not upgrade to Websocket automatically
+if that was the protocol in use when the connection was lost.
+
+== Elements
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Protocol::
+
+The protocol that was selected for this connection
+or upgraded to during the course of the connection.
+
+Reason::
+
+The reason for the loss of the connection.
++
+It is present for debugging purposes only. You should not
+rely on this value to perform operations programmatically.
+
+KilledStreams::
+
+List of streams that have been brutally terminated.
++
+They are active streams that did not complete before the closing
+of the connection. Whether they can be retried safely depends
+on the protocol used and the idempotence property of the requests.
+
+UnprocessedStreams::
+
+List of streams that have not been processed by the server.
++
+They are streams that the server did not start processing yet.
+They may be retried safely depending on whether related streams
+were killed.
+
+== Changelog
+
+* *1.0*: Message introduced.
+
+== Examples
+
+.Receive a gun_down message in a gen_server
+[source,erlang]
+----
+handle_info({gun_down, ConnPid, _Protocol,
+ _Reason, _Killed, _Unprocessed},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State}.
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:open(3)[gun:open(3)],
+link:man:gun:open_unix(3)[gun:open_unix(3)],
+link:man:gun_up(3)[gun_up(3)],
+link:man:gun_error(3)[gun_error(3)]
diff --git a/doc/src/manual/gun_error.asciidoc b/doc/src/manual/gun_error.asciidoc
new file mode 100644
index 0000000..a43d32b
--- /dev/null
+++ b/doc/src/manual/gun_error.asciidoc
@@ -0,0 +1,67 @@
+= gun_error(3)
+
+== Name
+
+gun_error - Stream or connection-wide error
+
+== Description
+
+[source,erlang]
+----
+{gun_error, ConnPid, StreamRef, Reason}
+{gun_error, ConnPid, Reason}
+
+ConnPid :: pid()
+StreamRef :: reference()
+Reason :: any()
+----
+
+Stream or connection-wide error.
+
+These messages inform the relevant process that an error
+occurred. A reference is given when the error pertains
+to a specific stream. Connection-wide errors do not
+imply that the connection is no longer usable, they are
+used for all errors that are not specific to a stream.
+
+== Elements
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream that resulted in an error.
+
+Reason::
+
+The reason for the error.
++
+It is present for debugging purposes only. You should not
+rely on this value to perform operations programmatically.
+
+== Changelog
+
+* *1.0*: Message introduced.
+
+== Examples
+
+.Receive a gun_error message in a gen_server
+[source,erlang]
+----
+handle_info({gun_error, ConnPid, _Reason},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State};
+handle_info({gun_error, ConnPid, _StreamRef, _Reason},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State}.
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun_up(3)[gun_up(3)],
+link:man:gun_down(3)[gun_down(3)]
diff --git a/doc/src/manual/gun_inform.asciidoc b/doc/src/manual/gun_inform.asciidoc
new file mode 100644
index 0000000..0d24beb
--- /dev/null
+++ b/doc/src/manual/gun_inform.asciidoc
@@ -0,0 +1,70 @@
+= gun_inform(3)
+
+== Name
+
+gun_inform - Informational response
+
+== Description
+
+[source,erlang]
+----
+{gun_inform, ConnPid, StreamRef, Status, Headers}
+
+ConnPid :: pid()
+StreamRef :: reference()
+Status :: 100..199
+Headers :: [{binary(), binary()}]
+----
+
+Informational response.
+
+This message informs the relevant process that the server
+sent an informational response to the original request.
+
+Informational responses are only intermediate responses
+and provide no guarantees as to what the final response
+will be. An informational response always precedes the
+response to the original request.
+
+== Elements
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream for the original request.
+
+Status::
+
+Status code for the informational response.
+
+Headers::
+
+Headers sent with the informational response.
+
+== Changelog
+
+* *1.0*: Message introduced.
+
+== Examples
+
+.Receive a gun_inform message in a gen_server
+[source,erlang]
+----
+handle_info({gun_inform, ConnPid, _StreamRef,
+ _Status, _Headers},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State}.
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:get(3)[gun:get(3)],
+link:man:gun:patch(3)[gun:patch(3)],
+link:man:gun:post(3)[gun:post(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun_response(3)[gun_response(3)]
diff --git a/doc/src/manual/gun_push.asciidoc b/doc/src/manual/gun_push.asciidoc
new file mode 100644
index 0000000..e73c3b6
--- /dev/null
+++ b/doc/src/manual/gun_push.asciidoc
@@ -0,0 +1,90 @@
+= gun_push(3)
+
+== Name
+
+gun_push - Server-initiated push
+
+== Description
+
+[source,erlang]
+----
+{gun_push, ConnPid, StreamRef, NewStreamRef, Method, URI, Headers}
+
+ConnPid :: pid()
+StreamRef :: reference()
+NewStreamRef :: reference()
+Method :: binary()
+URI :: binary()
+Headers :: [{binary(), binary()}]
+----
+
+Server-initiated push.
+
+This message informs the relevant process that the server
+is pushing a resource related to the effective target URI
+of the original request.
+
+A server-initiated push message always precedes the response
+to the original request.
+
+This message will not be sent when using the HTTP/1.1 protocol
+because it lacks the concept of server-initiated push.
+
+== Elements
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream for the original request.
+
+NewStreamRef::
+
+Identifier of the stream being pushed.
+
+Method::
+
+Method of the equivalent HTTP request.
+
+URI::
+
+URI of the resource being pushed.
+
+Headers::
+
+Headers of the equivalent HTTP request.
+
+== Changelog
+
+* *1.0*: Message introduced.
+
+== Examples
+
+.Receive a gun_push message in a gen_server
+[source,erlang]
+----
+handle_info({gun_push, ConnPid, _StreamRef,
+ _NewStreamRef, _Method, _URI, _Headers},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State}.
+----
+
+.Cancel an unwanted push
+[source,erlang]
+----
+handle_info({gun_push, ConnPid, _StreamRef,
+ NewStreamRef, _Method, _URI, _Headers},
+ State=#state{conn_pid=ConnPid}) ->
+ gun:cancel(ConnPid, NewStreamRef),
+ {noreply, State}.
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:get(3)[gun:get(3)],
+link:man:gun:cancel(3)[gun:cancel(3)],
+link:man:gun_response(3)[gun_response(3)]
diff --git a/doc/src/manual/gun_response.asciidoc b/doc/src/manual/gun_response.asciidoc
new file mode 100644
index 0000000..cc55b44
--- /dev/null
+++ b/doc/src/manual/gun_response.asciidoc
@@ -0,0 +1,75 @@
+= gun_response(3)
+
+== Name
+
+gun_response - Response
+
+== Description
+
+[source,erlang]
+----
+{gun_response, ConnPid, StreamRef, IsFin, Status, Headers}
+
+ConnPid :: pid()
+StreamRef :: reference()
+IsFin :: fin | nofin
+Status :: non_neg_integer()
+Headers :: [{binary(), binary()}]
+----
+
+Response.
+
+This message informs the relevant process that the server
+sent a response to the original request.
+
+== Elements
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream for the original request.
+
+IsFin::
+
+Whether this message terminates the response.
+
+Status::
+
+Status code for the response.
+
+Headers::
+
+Headers sent with the response.
+
+== Changelog
+
+* *1.0*: Message introduced.
+
+== Examples
+
+.Receive a gun_response message in a gen_server
+[source,erlang]
+----
+handle_info({gun_response, ConnPid, _StreamRef,
+ _IsFin, _Status, _Headers},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State}.
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:get(3)[gun:get(3)],
+link:man:gun:head(3)[gun:head(3)],
+link:man:gun:patch(3)[gun:patch(3)],
+link:man:gun:post(3)[gun:post(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun:delete(3)[gun:delete(3)],
+link:man:gun:options(3)[gun:options(3)],
+link:man:gun:request(3)[gun:request(3)],
+link:man:gun_inform(3)[gun_inform(3)],
+link:man:gun_push(3)[gun_push(3)]
diff --git a/doc/src/manual/gun_trailers.asciidoc b/doc/src/manual/gun_trailers.asciidoc
new file mode 100644
index 0000000..d1862fa
--- /dev/null
+++ b/doc/src/manual/gun_trailers.asciidoc
@@ -0,0 +1,67 @@
+= gun_trailers(3)
+
+== Name
+
+gun_trailers - Response trailers
+
+== Description
+
+[source,erlang]
+----
+{gun_trailers, ConnPid, StreamRef, Headers}
+
+ConnPid :: pid()
+StreamRef :: reference()
+Headers :: [{binary(), binary()}]
+----
+
+Response trailers.
+
+This message informs the relevant process that the server
+sent response trailers for the response to the original
+request.
+
+A trailers message terminates the response.
+
+== Elements
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream for the original request.
+
+Headers::
+
+Trailing headers sent after the response body.
+
+== Changelog
+
+* *1.0*: Message introduced.
+
+== Examples
+
+.Receive a gun_trailers message in a gen_server
+[source,erlang]
+----
+handle_info({gun_trailers, ConnPid, _StreamRef, _Headers},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State}.
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:get(3)[gun:get(3)],
+link:man:gun:head(3)[gun:head(3)],
+link:man:gun:patch(3)[gun:patch(3)],
+link:man:gun:post(3)[gun:post(3)],
+link:man:gun:put(3)[gun:put(3)],
+link:man:gun:delete(3)[gun:delete(3)],
+link:man:gun:options(3)[gun:options(3)],
+link:man:gun:request(3)[gun:request(3)],
+link:man:gun_response(3)[gun_response(3)],
+link:man:gun_data(3)[gun_data(3)]
diff --git a/doc/src/manual/gun_up.asciidoc b/doc/src/manual/gun_up.asciidoc
new file mode 100644
index 0000000..c7089fb
--- /dev/null
+++ b/doc/src/manual/gun_up.asciidoc
@@ -0,0 +1,61 @@
+= gun_up(3)
+
+== Name
+
+gun_up - The connection is up
+
+== Description
+
+[source,erlang]
+----
+{gun_up, ConnPid, Protocol}
+
+ConnPid :: pid()
+Protocol :: http | http2
+----
+
+The connection is up.
+
+This message informs the owner process that the connection or
+reconnection completed.
+
+Gun will now start processing the messages it received while
+waiting for the connection to be up. If this is a reconnection,
+then this may not be desirable for all requests. Those requests
+should be cancelled when the connection goes down, and any
+subsequent messages ignored.
+
+== Elements
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+Protocol::
+
+The protocol selected for this connection. It can be used
+to determine the capabilities of the server.
+
+== Changelog
+
+* *1.0*: Message introduced.
+
+== Examples
+
+.Receive a gun_up message in a gen_server
+[source,erlang]
+----
+handle_info({gun_up, ConnPid, _Protocol},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State}.
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:open(3)[gun:open(3)],
+link:man:gun:open_unix(3)[gun:open_unix(3)],
+link:man:gun:await_up(3)[gun:await_up(3)],
+link:man:gun_down(3)[gun_down(3)],
+link:man:gun_error(3)[gun_error(3)]
diff --git a/doc/src/manual/gun_upgrade.asciidoc b/doc/src/manual/gun_upgrade.asciidoc
new file mode 100644
index 0000000..3fc0340
--- /dev/null
+++ b/doc/src/manual/gun_upgrade.asciidoc
@@ -0,0 +1,72 @@
+= gun_upgrade(3)
+
+== Name
+
+gun_upgrade - Successful protocol upgrade
+
+== Description
+
+[source,erlang]
+----
+{gun_upgrade, ConnPid, StreamRef, Protocols, Headers}
+
+ConnPid :: pid()
+StreamRef :: reference()
+Protocols :: [<<"websocket">>]
+Headers :: [{binary(), binary()}]
+----
+
+Successful protocol upgrade.
+
+This message informs the relevant process that the server
+accepted to upgrade to one or more protocols given in the
+original request.
+
+The exact semantics of this message depend on the original
+protocol. HTTP/1.1 upgrades apply to the entire connection.
+HTTP/2 uses a different mechanism which allows switching
+specific streams to a different protocol.
+
+Gun currently only supports upgrading HTTP/1.1 connections
+to the Websocket protocol.
+
+== Elements
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream that resulted in an upgrade.
+
+Protocols::
+
+List of protocols this stream was upgraded to.
+
+Headers::
+
+Headers sent with the upgrade response.
+
+== Changelog
+
+* *1.0*: Message introduced.
+
+== Examples
+
+.Receive a gun_upgrade message in a gen_server
+[source,erlang]
+----
+handle_info({gun_upgrade, ConnPid, _StreamRef,
+ _Protocols, _Headers},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State}.
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:ws_upgrade(3)[gun:ws_upgrade(3)],
+link:man:gun:ws_send(3)[gun:ws_send(3)],
+link:man:gun_ws(3)[gun_ws(3)]
diff --git a/doc/src/manual/gun_ws.asciidoc b/doc/src/manual/gun_ws.asciidoc
new file mode 100644
index 0000000..127f2a2
--- /dev/null
+++ b/doc/src/manual/gun_ws.asciidoc
@@ -0,0 +1,62 @@
+= gun_ws(3)
+
+== Name
+
+gun_ws - Websocket frame
+
+== Description
+
+[source,erlang]
+----
+{gun_ws, ConnPid, StreamRef, Frame}
+
+ConnPid :: pid()
+StreamRef :: reference()
+Frame :: close
+ | {text | binary | close, binary()}
+ | {close, non_neg_integer(), binary()}
+----
+
+Websocket frame.
+
+This message informs the relevant process that the server
+sent the enclosed frame.
+
+This message can only be sent on streams that were upgraded
+to the Websocket protocol.
+
+== Elements
+
+ConnPid::
+
+The pid of the Gun connection process.
+
+StreamRef::
+
+Identifier of the stream that was upgraded to Websocket.
+
+Frame::
+
+The Websocket frame in question.
+
+== Changelog
+
+* *1.0*: Message introduced.
+
+== Examples
+
+.Receive a gun_ws message in a gen_server
+[source,erlang]
+----
+handle_info({gun_ws, ConnPid, _StreamRef, _Frame},
+ State=#state{conn_pid=ConnPid}) ->
+ %% Do something.
+ {noreply, State}.
+----
+
+== See also
+
+link:man:gun(3)[gun(3)],
+link:man:gun:ws_upgrade(3)[gun:ws_upgrade(3)],
+link:man:gun:ws_send(3)[gun:ws_send(3)],
+link:man:gun_upgrade(3)[gun_upgrade(3)]