From b5d4cb91f80c833795a2d87050c3674bb7aecdc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Tue, 3 Oct 2017 13:39:41 +0200 Subject: Update Hugo, docs --- docs/en/gun/1.0/guide/http/index.html | 785 +++++++++++++++++----------------- 1 file changed, 394 insertions(+), 391 deletions(-) (limited to 'docs/en/gun/1.0/guide/http') diff --git a/docs/en/gun/1.0/guide/http/index.html b/docs/en/gun/1.0/guide/http/index.html index 668d3ff6..bbdb81ed 100644 --- a/docs/en/gun/1.0/guide/http/index.html +++ b/docs/en/gun/1.0/guide/http/index.html @@ -7,7 +7,7 @@ - + Nine Nines: HTTP @@ -67,402 +67,405 @@

HTTP

-

This chapter describes how to use the Gun client for -communicating with an HTTP/1.1 or HTTP/2 server.

-
-

Streams

-
-

Every time a request is initiated, Gun creates a stream. -A stream reference uniquely identifies a set of request and -response(s) and must be used to perform additional operations -with a stream or to identify its messages.

-

Stream references use the Erlang reference data type and -are therefore unique.

-

Streams can be canceled at any time. This will stop any further -messages from being sent to the owner process. Depending on -its capabilities, the server will also be instructed to cancel -the request.

-

Canceling a stream may result in Gun dropping the connection -temporarily, to avoid uploading or downloading data that will -not be used.

-
-
Cancelling a stream
-
-
gun:cancel(ConnPid, StreamRef).
-
-
-
-

Sending requests

-
-

Gun provides many convenient functions for performing common -operations, like GET, POST or DELETE. It also provides a -general purpose function in case you need other methods.

-

The availability of these methods on the server can vary -depending on the software used but also on a per-resource -basis.

-

Gun will automatically set a few headers depending on the -method used. For all methods however it will set the host -header if it has not been provided in the request arguments.

-

This section focuses on the act of sending a request. The -handling of responses will be explained further on.

-
-

GET and HEAD

-

Use gun:get/{2,3,4} to request a resource.

-
-
GET "/organizations/ninenines"
-
-
StreamRef = gun:get(ConnPid, "/organizations/ninenines").
-
-
GET "/organizations/ninenines" with custom headers
-
-
StreamRef = gun:get(ConnPid, "/organizations/ninenines", [
-        {<<"accept">>, "application/json"},
-        {<<"user-agent">>, "revolver/1.0"}
-]).
-

Note that the list of headers has the field name as a binary. -The field value is iodata, which is either a binary or an -iolist.

-

Use gun:head/{2,3,4} if you don’t need the response body.

-
-
HEAD "/organizations/ninenines"
-
-
StreamRef = gun:head(ConnPid, "/organizations/ninenines").
-
-
HEAD "/organizations/ninenines" with custom headers
-
-
StreamRef = gun:head(ConnPid, "/organizations/ninenines", [
-        {<<"accept">>, "application/json"},
-        {<<"user-agent">>, "revolver/1.0"}
-]).
-

It is not possible to send a request body with a GET or HEAD -request.

-
-
-

POST, PUT and PATCH

-

HTTP defines three methods to create or update a resource.

-

POST is generally used when the resource identifier (URI) isn’t known -in advance when creating the resource. POST can also be used to -replace an existing resource, although PUT is more appropriate -in that situation.

-

PUT creates or replaces a resource identified by the URI.

-

PATCH provides instructions on how to modify the resource.

-

Both POST and PUT send the entire resource representation in their -request body. The PATCH method can be used when this is not -desirable. The request body of a PATCH method may be a partial -representation or a list of instructions on how to update the -resource.

-

The gun:post/{4,5}, gun:put/{4,5} and gun:patch/{4,5} functions -take a body as their fourth argument. These functions do -not require any body-specific header to be set, although -it is always recommended to set the content-type header. -Gun will set the other headers automatically.

-

In this and the following examples in this section, gun:post -can be replaced by gun:put or gun:patch for performing -a PUT or PATCH request, respectively.

-
-
POST "/organizations/ninenines"
-
-
Body = "{\"msg\": \"Hello world!\"}",
-StreamRef = gun:post(ConnPid, "/organizations/ninenines", [
-        {<<"content-type">>, "application/json"}
-], Body).
-

The gun:post/3, gun:put/3 and gun:patch/3 functions -do not take a body in their arguments. If a body is to be -provided later on, using the gun:data/4 function, then -the request headers must indicate this. This can be done -by setting the content-length or content-type request -headers. If these headers are not set then Gun will assume -the request has no body.

-

It is recommended to send the content-length header if you -know it in advance, although this is not required. If it -is not set, HTTP/1.1 will use the chunked transfer-encoding, -and HTTP/2 will continue normally as it is chunked by design.

-
-
POST "/organizations/ninenines" with delayed body
-
-
Body = "{\"msg\": \"Hello world!\"}",
-StreamRef = gun:post(ConnPid, "/organizations/ninenines", [
-        {<<"content-length">>, integer_to_binary(length(Body))},
-        {<<"content-type">>, "application/json"}
-]),
-gun:data(ConnPid, StreamRef, fin, Body).
-

The atom fin indicates this is the last chunk of data to -be sent. You can call the gun:data/4 function as many -times as needed until you have sent the entire body. The -last call must use fin and all the previous calls must -use nofin. The last chunk may be empty.

-

@todo what to do about empty chunk, ignore?

-
-
Streaming the request body
-
-
sendfile(ConnPid, StreamRef, Filepath) ->
-        {ok, IoDevice} = file:open(Filepath, [read, binary, raw]),
-        do_sendfile(ConnPid, StreamRef, IoDevice).
-
-do_sendfile(ConnPid, StreamRef, IoDevice) ->
-        case file:read(IoDevice, 8000) of
-                eof ->
-                        gun:data(ConnPid, StreamRef, fin, <<>>),
-                        file:close(IoDevice);
-                {ok, Bin} ->
-                        gun:data(ConnPid, StreamRef, nofin, Bin),
-                        do_sendfile(ConnPid, StreamRef, IoDevice)
-        end.
-
-
-

DELETE

-

Use gun:delete/{2,3,4} to delete a resource.

-
-
DELETE "/organizations/ninenines"
-
-
StreamRef = gun:delete(ConnPid, "/organizations/ninenines").
-
-
DELETE "/organizations/ninenines" with custom headers
-
-
StreamRef = gun:delete(ConnPid, "/organizations/ninenines", [
-        {<<"user-agent">>, "revolver/1.0"}
-]).
-
-
-

OPTIONS

-

Use gun:options/{2,3} to request information about a resource.

-
-
OPTIONS "/organizations/ninenines"
-
-
StreamRef = gun:options(ConnPid, "/organizations/ninenines").
-
-
OPTIONS "/organizations/ninenines" with custom headers
-
-
StreamRef = gun:options(ConnPid, "/organizations/ninenines", [
-        {<<"user-agent">>, "revolver/1.0"}
-]).
-

You can also use this function to request information about -the server itself.

-
-
OPTIONS "*"
-
-
StreamRef = gun:options(ConnPid, "*").
-
-
-

Requests with an arbitrary method

-

The gun:request/{4,5,6} function can be used to send requests -with a configurable method name. It is mostly useful when you -need a method that Gun does not understand natively.

-
-
Example of a TRACE request
-
-
gun:request(ConnPid, "TRACE", "/", [
-        {<<"max-forwards">>, "30"}
-]).
-
-
-
-
-

Processing responses

-
-

All data received from the server is sent to the owner -process as a message. First a gun_response message is sent, -followed by zero or more gun_data messages. If something goes wrong, -a gun_error message is sent instead.

-

The response message will inform you whether there will be -data messages following. If it contains fin there will be -no data messages. If it contains nofin then one or more data -messages will follow.

-

When using HTTP/2 this value is sent with the frame and simply -passed on in the message. When using HTTP/1.1 however Gun must -guess whether data will follow by looking at the response headers.

-

You can receive messages directly, or you can use the await -functions to let Gun receive them for you.

-
-
Receiving a response using receive
-
-
print_body(ConnPid, MRef) ->
-        StreamRef = gun:get(ConnPid, "/"),
-        receive
-                {gun_response, ConnPid, StreamRef, fin, Status, Headers} ->
-                        no_data;
-                {gun_response, ConnPid, StreamRef, nofin, Status, Headers} ->
-                        receive_data(ConnPid, MRef, StreamRef);
-                {'DOWN', MRef, process, ConnPid, Reason} ->
-                        error_logger:error_msg("Oops!"),
-                        exit(Reason)
-        after 1000 ->
-                exit(timeout)
-        end.
-
-receive_data(ConnPid, MRef, StreamRef) ->
-        receive
-                {gun_data, ConnPid, StreamRef, nofin, Data} ->
-                        io:format("~s~n", [Data]),
-                        receive_data(ConnPid, MRef, StreamRef);
-                {gun_data, ConnPid, StreamRef, fin, Data} ->
-                        io:format("~s~n", [Data]);
-                {'DOWN', MRef, process, ConnPid, Reason} ->
-                        error_logger:error_msg("Oops!"),
-                        exit(Reason)
-        after 1000 ->
-                exit(timeout)
-        end.
-

While it may seem verbose, using messages like this has the -advantage of never locking your process, allowing you to -easily debug your code. It also allows you to start more than -one connection and concurrently perform queries on all of them -at the same time.

-

You can also use Gun in a synchronous manner by using the await -functions.

-

The gun:await/{2,3,4} function will wait until it receives -a response to, a pushed resource related to, or data from -the given stream.

-

When calling gun:await/{2,3} and not passing a monitor -reference, one is automatically created for you for the -duration of the call.

-

The gun:await_body/{2,3,4} works similarly, but returns the -body received. Both functions can be combined to receive the -response and its body sequentially.

-
-
Receiving a response using await
-
-
StreamRef = gun:get(ConnPid, "/"),
-case gun:await(ConnPid, StreamRef) of
-        {response, fin, Status, Headers} ->
-                no_data;
-        {response, nofin, Status, Headers} ->
-                {ok, Body} = gun:await_body(ConnPid, StreamRef),
-                io:format("~s~n", [Body])
-end.
-
-
-
-

Handling streams pushed by the server

-
-

The HTTP/2 protocol allows the server to push more than one -resource for every request. It will start sending those -extra resources before it starts sending the response itself, -so Gun will send you gun_push messages before gun_response -when that happens.

-

You can safely choose to ignore gun_push messages, or -you can handle them. If you do, you can either receive the -messages directly or use await functions.

-

The gun_push message contains both the new stream reference -and the stream reference of the original request.

-
-
Receiving a pushed response using receive
-
-
receive
-        {gun_push, ConnPid, OriginalStreamRef, PushedStreamRef,
-                        Method, Host, Path, Headers} ->
-                enjoy()
-end.
-

If you use the gun:await/{2,3,4} function, however, Gun -will use the original reference to identify the message but -will return a tuple that doesn’t contain it.

-
-
Receiving a pushed response using await
-
-
{push, PushedStreamRef, Method, Host, Path, Headers}
-        = gun:await(ConnPid, OriginalStreamRef).
-

The PushedStreamRef variable can then be used with gun:await_body/{2,3,4} -if needed.

-
-
-
-

Flushing unwanted messages

-
-

Gun provides the function gun:flush/1 to quickly get rid -of unwanted messages sitting in the process mailbox. You -can use it to get rid of all messages related to a connection, -or just the messages related to a stream.

-
-
Flush all messages from a Gun connection
-
-
gun:flush(ConnPid).
-
-
Flush all messages from a specific stream
-
-
gun:flush(StreamRef).
-
-
-
-

Redirecting responses to a different process

-
-

Gun allows you to specify which process will handle responses -to a request via the reply_to request option.

-
-
GET "/organizations/ninenines" to a different process
-
-
StreamRef = gun:get(ConnPid, "/organizations/ninenines", [],
-        #{reply_to => Pid}).
-
-
+

This chapter describes how to use the Gun client for +communicating with an HTTP/1.1 or HTTP/2 server.

+
+

Streams

+
+

Every time a request is initiated, Gun creates a stream. +A stream reference uniquely identifies a set of request and +response(s) and must be used to perform additional operations +with a stream or to identify its messages.

+

Stream references use the Erlang reference data type and +are therefore unique.

+

Streams can be canceled at any time. This will stop any further +messages from being sent to the owner process. Depending on +its capabilities, the server will also be instructed to cancel +the request.

+

Canceling a stream may result in Gun dropping the connection +temporarily, to avoid uploading or downloading data that will +not be used.

+
+
Cancelling a stream
+
+
gun:cancel(ConnPid, StreamRef).
+
+
+
+

Sending requests

+
+

Gun provides many convenient functions for performing common +operations, like GET, POST or DELETE. It also provides a +general purpose function in case you need other methods.

+

The availability of these methods on the server can vary +depending on the software used but also on a per-resource +basis.

+

Gun will automatically set a few headers depending on the +method used. For all methods however it will set the host +header if it has not been provided in the request arguments.

+

This section focuses on the act of sending a request. The +handling of responses will be explained further on.

+
+

GET and HEAD

+

Use gun:get/{2,3,4} to request a resource.

+
+
GET "/organizations/ninenines"
+
+
StreamRef = gun:get(ConnPid, "/organizations/ninenines").
+
+
GET "/organizations/ninenines" with custom headers
+
+
StreamRef = gun:get(ConnPid, "/organizations/ninenines", [
+        {<<"accept">>, "application/json"},
+        {<<"user-agent">>, "revolver/1.0"}
+]).
+

Note that the list of headers has the field name as a binary. +The field value is iodata, which is either a binary or an +iolist.

+

Use gun:head/{2,3,4} if you don’t need the response body.

+
+
HEAD "/organizations/ninenines"
+
+
StreamRef = gun:head(ConnPid, "/organizations/ninenines").
+
+
HEAD "/organizations/ninenines" with custom headers
+
+
StreamRef = gun:head(ConnPid, "/organizations/ninenines", [
+        {<<"accept">>, "application/json"},
+        {<<"user-agent">>, "revolver/1.0"}
+]).
+

It is not possible to send a request body with a GET or HEAD +request.

+
+
+

POST, PUT and PATCH

+

HTTP defines three methods to create or update a resource.

+

POST is generally used when the resource identifier (URI) isn’t known +in advance when creating the resource. POST can also be used to +replace an existing resource, although PUT is more appropriate +in that situation.

+

PUT creates or replaces a resource identified by the URI.

+

PATCH provides instructions on how to modify the resource.

+

Both POST and PUT send the entire resource representation in their +request body. The PATCH method can be used when this is not +desirable. The request body of a PATCH method may be a partial +representation or a list of instructions on how to update the +resource.

+

The gun:post/{4,5}, gun:put/{4,5} and gun:patch/{4,5} functions +take a body as their fourth argument. These functions do +not require any body-specific header to be set, although +it is always recommended to set the content-type header. +Gun will set the other headers automatically.

+

In this and the following examples in this section, gun:post +can be replaced by gun:put or gun:patch for performing +a PUT or PATCH request, respectively.

+
+
POST "/organizations/ninenines"
+
+
Body = "{\"msg\": \"Hello world!\"}",
+StreamRef = gun:post(ConnPid, "/organizations/ninenines", [
+        {<<"content-type">>, "application/json"}
+], Body).
+

The gun:post/3, gun:put/3 and gun:patch/3 functions +do not take a body in their arguments. If a body is to be +provided later on, using the gun:data/4 function, then +the request headers must indicate this. This can be done +by setting the content-length or content-type request +headers. If these headers are not set then Gun will assume +the request has no body.

+

It is recommended to send the content-length header if you +know it in advance, although this is not required. If it +is not set, HTTP/1.1 will use the chunked transfer-encoding, +and HTTP/2 will continue normally as it is chunked by design.

+
+
POST "/organizations/ninenines" with delayed body
+
+
Body = "{\"msg\": \"Hello world!\"}",
+StreamRef = gun:post(ConnPid, "/organizations/ninenines", [
+        {<<"content-length">>, integer_to_binary(length(Body))},
+        {<<"content-type">>, "application/json"}
+]),
+gun:data(ConnPid, StreamRef, fin, Body).
+

The atom fin indicates this is the last chunk of data to +be sent. You can call the gun:data/4 function as many +times as needed until you have sent the entire body. The +last call must use fin and all the previous calls must +use nofin. The last chunk may be empty.

+

@todo what to do about empty chunk, ignore?

+
+
Streaming the request body
+
+
sendfile(ConnPid, StreamRef, Filepath) ->
+        {ok, IoDevice} = file:open(Filepath, [read, binary, raw]),
+        do_sendfile(ConnPid, StreamRef, IoDevice).
+
+do_sendfile(ConnPid, StreamRef, IoDevice) ->
+        case file:read(IoDevice, 8000) of
+                eof ->
+                        gun:data(ConnPid, StreamRef, fin, <<>>),
+                        file:close(IoDevice);
+                {ok, Bin} ->
+                        gun:data(ConnPid, StreamRef, nofin, Bin),
+                        do_sendfile(ConnPid, StreamRef, IoDevice)
+        end.
+
+
+

DELETE

+

Use gun:delete/{2,3,4} to delete a resource.

+
+
DELETE "/organizations/ninenines"
+
+
StreamRef = gun:delete(ConnPid, "/organizations/ninenines").
+
+
DELETE "/organizations/ninenines" with custom headers
+
+
StreamRef = gun:delete(ConnPid, "/organizations/ninenines", [
+        {<<"user-agent">>, "revolver/1.0"}
+]).
+
+
+

OPTIONS

+

Use gun:options/{2,3} to request information about a resource.

+
+
OPTIONS "/organizations/ninenines"
+
+
StreamRef = gun:options(ConnPid, "/organizations/ninenines").
+
+
OPTIONS "/organizations/ninenines" with custom headers
+
+
StreamRef = gun:options(ConnPid, "/organizations/ninenines", [
+        {<<"user-agent">>, "revolver/1.0"}
+]).
+

You can also use this function to request information about +the server itself.

+
+
OPTIONS "*"
+
+
StreamRef = gun:options(ConnPid, "*").
+
+
+

Requests with an arbitrary method

+

The gun:request/{4,5,6} function can be used to send requests +with a configurable method name. It is mostly useful when you +need a method that Gun does not understand natively.

+
+
Example of a TRACE request
+
+
gun:request(ConnPid, "TRACE", "/", [
+        {<<"max-forwards">>, "30"}
+]).
+
+
+
+
+

Processing responses

+
+

All data received from the server is sent to the owner +process as a message. First a gun_response message is sent, +followed by zero or more gun_data messages. If something goes wrong, +a gun_error message is sent instead.

+

The response message will inform you whether there will be +data messages following. If it contains fin there will be +no data messages. If it contains nofin then one or more data +messages will follow.

+

When using HTTP/2 this value is sent with the frame and simply +passed on in the message. When using HTTP/1.1 however Gun must +guess whether data will follow by looking at the response headers.

+

You can receive messages directly, or you can use the await +functions to let Gun receive them for you.

+
+
Receiving a response using receive
+
+
print_body(ConnPid, MRef) ->
+        StreamRef = gun:get(ConnPid, "/"),
+        receive
+                {gun_response, ConnPid, StreamRef, fin, Status, Headers} ->
+                        no_data;
+                {gun_response, ConnPid, StreamRef, nofin, Status, Headers} ->
+                        receive_data(ConnPid, MRef, StreamRef);
+                {'DOWN', MRef, process, ConnPid, Reason} ->
+                        error_logger:error_msg("Oops!"),
+                        exit(Reason)
+        after 1000 ->
+                exit(timeout)
+        end.
+
+receive_data(ConnPid, MRef, StreamRef) ->
+        receive
+                {gun_data, ConnPid, StreamRef, nofin, Data} ->
+                        io:format("~s~n", [Data]),
+                        receive_data(ConnPid, MRef, StreamRef);
+                {gun_data, ConnPid, StreamRef, fin, Data} ->
+                        io:format("~s~n", [Data]);
+                {'DOWN', MRef, process, ConnPid, Reason} ->
+                        error_logger:error_msg("Oops!"),
+                        exit(Reason)
+        after 1000 ->
+                exit(timeout)
+        end.
+

While it may seem verbose, using messages like this has the +advantage of never locking your process, allowing you to +easily debug your code. It also allows you to start more than +one connection and concurrently perform queries on all of them +at the same time.

+

You can also use Gun in a synchronous manner by using the await +functions.

+

The gun:await/{2,3,4} function will wait until it receives +a response to, a pushed resource related to, or data from +the given stream.

+

When calling gun:await/{2,3} and not passing a monitor +reference, one is automatically created for you for the +duration of the call.

+

The gun:await_body/{2,3,4} works similarly, but returns the +body received. Both functions can be combined to receive the +response and its body sequentially.

+
+
Receiving a response using await
+
+
StreamRef = gun:get(ConnPid, "/"),
+case gun:await(ConnPid, StreamRef) of
+        {response, fin, Status, Headers} ->
+                no_data;
+        {response, nofin, Status, Headers} ->
+                {ok, Body} = gun:await_body(ConnPid, StreamRef),
+                io:format("~s~n", [Body])
+end.
+
+
+
+

Handling streams pushed by the server

+
+

The HTTP/2 protocol allows the server to push more than one +resource for every request. It will start sending those +extra resources before it starts sending the response itself, +so Gun will send you gun_push messages before gun_response +when that happens.

+

You can safely choose to ignore gun_push messages, or +you can handle them. If you do, you can either receive the +messages directly or use await functions.

+

The gun_push message contains both the new stream reference +and the stream reference of the original request.

+
+
Receiving a pushed response using receive
+
+
receive
+        {gun_push, ConnPid, OriginalStreamRef, PushedStreamRef,
+                        Method, Host, Path, Headers} ->
+                enjoy()
+end.
+

If you use the gun:await/{2,3,4} function, however, Gun +will use the original reference to identify the message but +will return a tuple that doesn’t contain it.

+
+
Receiving a pushed response using await
+
+
{push, PushedStreamRef, Method, Host, Path, Headers}
+        = gun:await(ConnPid, OriginalStreamRef).
+

The PushedStreamRef variable can then be used with gun:await_body/{2,3,4} +if needed.

+
+
+
+

Flushing unwanted messages

+
+

Gun provides the function gun:flush/1 to quickly get rid +of unwanted messages sitting in the process mailbox. You +can use it to get rid of all messages related to a connection, +or just the messages related to a stream.

+
+
Flush all messages from a Gun connection
+
+
gun:flush(ConnPid).
+
+
Flush all messages from a specific stream
+
+
gun:flush(StreamRef).
+
+
+
+

Redirecting responses to a different process

+
+

Gun allows you to specify which process will handle responses +to a request via the reply_to request option.

+
+
GET "/organizations/ninenines" to a different process
+
+
StreamRef = gun:get(ConnPid, "/organizations/ninenines", [],
+        #{reply_to => Pid}).
+
+
+ + +