Skip to content

Commit

Permalink
sockname and peername access from hackney module (#504)
Browse files Browse the repository at this point in the history
* add sockname and peername methods to the hackney module.

* improve example

* sockname and peername helper info APIs
  • Loading branch information
c-bik authored and benoitc committed Sep 1, 2018
1 parent c6e4ad0 commit d6b0b05
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 32 deletions.
29 changes: 19 additions & 10 deletions README.md
Expand Up @@ -100,9 +100,9 @@ $ ./rebar3 shell
It is suggested that you install rebar3 user-wide as described [here](http://blog.erlware.org/rebar3-features-part-1-local-install-and-upgrade/).
This fixes zsh (and maybe other shells) escript-related bugs. Also this should speed things up.

```erlang-repl
```erlang

1>> application:ensure_all_started(hackney).
> application:ensure_all_started(hackney).
ok
```

Expand Down Expand Up @@ -149,7 +149,7 @@ where `Method`, can be any HTTP method in lowercase.
### Read the body

```erlang
{ok, Body} = hackney:body(Client).
{ok, Body} = hackney:body(ClientRef).
```

`hackney:body/1` fetch the body. To fetch it by chunk you can use the
Expand All @@ -158,7 +158,7 @@ where `Method`, can be any HTTP method in lowercase.
```erlang

read_body(MaxLength, Ref, Acc) when MaxLength > byte_size(Acc) ->
case stream_body(Ref) of
case hackney:stream_body(Ref) of
{ok, Data} ->
read_body(MaxLength, Ref, << Acc/binary, Data/binary >>);
done ->
Expand Down Expand Up @@ -186,30 +186,39 @@ couple of requests.

```erlang

Transport = hackney_tcp,
Host = << "https://friendpaste.com" >>,
Transport = hackney_ssl,
Host = << "friendpaste.com" >>,
Port = 443,
Options = [],
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options)
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options).
```

> To create a connection that will use an HTTP proxy use
> `hackney_http_proxy:connect_proxy/5` instead.

#### To get local and remote ip and port information of a connection:

```erlang

> hackney:peername(ConnRef).
> hackney:sockname(ConnRef).
```

#### Make a request

Once you created a connection use the `hackney:send_request/2` function
to make a request:

```erlang

ReqBody = << "{ \"snippet\": \"some snippet\" }" >>,
ReqBody = << "{\"snippet\": \"some snippet\"}" >>,
ReqHeaders = [{<<"Content-Type">>, <<"application/json">>}],
NextPath = <<"/">>,
NextMethod = post,
NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody}
NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody},
{ok, _, _, ConnRef} = hackney:send_request(ConnRef, NextReq).
{ok, Body1} = hackney:body(ConnRef),
{ok, Body1} = hackney:body(ConnRef).
```

Here we are posting a JSON payload to '/' on the friendpaste service to
Expand Down
1 change: 1 addition & 0 deletions THANKS
Expand Up @@ -30,3 +30,4 @@ Mayorov Andrey <avmayorov@platbox.com>
omarkj <omarkj@gmail.com>
Pavel Abalihin <anpavl@gmail.com>
Ilya Khaprov <dead.trickster@gmail.com>
Bikram Chatterjee <razorpeak@gmail.com>
27 changes: 18 additions & 9 deletions doc/README.md
Expand Up @@ -100,9 +100,9 @@ $ ./rebar3 shell
It is suggested that you install rebar3 user-wide as described [here](http://blog.erlware.org/rebar3-features-part-1-local-install-and-upgrade/).
This fixes zsh (and maybe other shells) escript-related bugs. Also this should speed things up.

```erlang-repl
```erlang

1>> application:ensure_all_started(hackney).
> application:ensure_all_started(hackney).
ok
```

Expand Down Expand Up @@ -149,7 +149,7 @@ where `Method`, can be any HTTP method in lowercase.
### Read the body

```erlang
{ok, Body} = hackney:body(Client).
{ok, Body} = hackney:body(ClientRef).
```

`hackney:body/1` fetch the body. To fetch it by chunk you can use the
Expand All @@ -158,7 +158,7 @@ where `Method`, can be any HTTP method in lowercase.
```erlang

read_body(MaxLength, Ref, Acc) when MaxLength > byte_size(Acc) ->
case stream_body(Ref) of
case hackney:stream_body(Ref) of
{ok, Data} ->
read_body(MaxLength, Ref, << Acc/binary, Data/binary >>);
done ->
Expand Down Expand Up @@ -186,16 +186,25 @@ couple of requests.

```erlang

Transport = hackney_tcp,
Host = << "https://friendpaste.com" >>,
Transport = hackney_ssl,
Host = << "friendpaste.com" >>,
Port = 443,
Options = [],
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options)
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options).
```

> To create a connection that will use an HTTP proxy use
> `hackney_http_proxy:connect_proxy/5` instead.

#### To get local and remote ip and port information of a connection:

```erlang

> hackney:peername(ConnRef).
> hackney:sockname(ConnRef).
```

#### Make a request

Once you created a connection use the `hackney:send_request/2` function
Expand All @@ -207,9 +216,9 @@ ReqBody = << "{ \"snippet\": \"some snippet\" }" >>,
ReqHeaders = [{<<"Content-Type">>, <<"application/json">>}],
NextPath = <<"/">>,
NextMethod = post,
NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody}
NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody},
{ok, _, _, ConnRef} = hackney:send_request(ConnRef, NextReq).
{ok, Body1} = hackney:body(ConnRef),
{ok, Body1} = hackney:body(ConnRef).
```

Here we are posting a JSON payload to '/' on the friendpaste service to
Expand Down
20 changes: 18 additions & 2 deletions doc/hackney.md
Expand Up @@ -46,7 +46,7 @@ url() = #hackney_url{} | binary()
length doesn't go over MaxLength.</td></tr><tr><td valign="top"><a href="#cancel_request-1">cancel_request/1</a></td><td>Extract raw informations from the client context
This feature can be useful when you want to create a simple proxy, rerouting
on the headers and the status line and continue to forward the connection for example.</td></tr><tr><td valign="top"><a href="#close-1">close/1</a></td><td>close the client.</td></tr><tr><td valign="top"><a href="#connect-1">connect/1</a></td><td></td></tr><tr><td valign="top"><a href="#connect-2">connect/2</a></td><td></td></tr><tr><td valign="top"><a href="#connect-3">connect/3</a></td><td>connect a socket and create a client state.</td></tr><tr><td valign="top"><a href="#connect-4">connect/4</a></td><td></td></tr><tr><td valign="top"><a href="#controlling_process-2">controlling_process/2</a></td><td>Assign a new controlling process <em>Pid</em> to <em>Client</em>.</td></tr><tr><td valign="top"><a href="#cookies-1">cookies/1</a></td><td></td></tr><tr><td valign="top"><a href="#finish_send_body-1">finish_send_body/1</a></td><td></td></tr><tr><td valign="top"><a href="#location-1">location/1</a></td><td>return the requested location.</td></tr><tr><td valign="top"><a href="#pause_stream-1">pause_stream/1</a></td><td>pause a response stream, the stream process will hibernate and
be woken later by the resume function.</td></tr><tr><td valign="top"><a href="#redirect_location-1">redirect_location/1</a></td><td></td></tr><tr><td valign="top"><a href="#request-1">request/1</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-2">request/2</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-3">request/3</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-4">request/4</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-5">request/5</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request_info-1">request_info/1</a></td><td>get request info.</td></tr><tr><td valign="top"><a href="#resume_stream-1">resume_stream/1</a></td><td>resume a paused response stream, the stream process will be
be woken later by the resume function.</td></tr><tr><td valign="top"><a href="#peername-1">peername/1</a></td><td>peername of the client.</td></tr><tr><td valign="top"><a href="#redirect_location-1">redirect_location/1</a></td><td></td></tr><tr><td valign="top"><a href="#request-1">request/1</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-2">request/2</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-3">request/3</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-4">request/4</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-5">request/5</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request_info-1">request_info/1</a></td><td>get request info.</td></tr><tr><td valign="top"><a href="#resume_stream-1">resume_stream/1</a></td><td>resume a paused response stream, the stream process will be
awoken.</td></tr><tr><td valign="top"><a href="#send_body-2">send_body/2</a></td><td>send the request body until eob.</td></tr><tr><td valign="top"><a href="#send_multipart_body-2">send_multipart_body/2</a></td><td>send a multipart body until eof
Possible value are :
<ul>
Expand All @@ -71,7 +71,7 @@ multipart content</li>
multipart content</li>
</ul><p></p>Note: You can calculate the full length of a multipart stream using
the function <code>hackney_multipart:len_mp_stream/2</code> .</td></tr><tr><td valign="top"><a href="#send_request-2">send_request/2</a></td><td>send a request using the current client state.</td></tr><tr><td valign="top"><a href="#send_request-3">send_request/3</a></td><td>send a request using the current client state and pass new
options to it.</td></tr><tr><td valign="top"><a href="#setopts-2">setopts/2</a></td><td>set client options.</td></tr><tr><td valign="top"><a href="#skip_body-1">skip_body/1</a></td><td>skip the full body.</td></tr><tr><td valign="top"><a href="#skip_multipart-1">skip_multipart/1</a></td><td>Stream the response body.</td></tr><tr><td valign="top"><a href="#start_response-1">start_response/1</a></td><td>start a response.</td></tr><tr><td valign="top"><a href="#stop_async-1">stop_async/1</a></td><td>stop to receive asynchronously.</td></tr><tr><td valign="top"><a href="#stream_body-1">stream_body/1</a></td><td>Stream the response body.</td></tr><tr><td valign="top"><a href="#stream_multipart-1">stream_multipart/1</a></td><td>Stream the response body.</td></tr><tr><td valign="top"><a href="#stream_next-1">stream_next/1</a></td><td>continue to the next stream message.</td></tr></table>
options to it.</td></tr><tr><td valign="top"><a href="#setopts-2">setopts/2</a></td><td>set client options.</td></tr><tr><td valign="top"><a href="#skip_body-1">skip_body/1</a></td><td>skip the full body.</td></tr><tr><td valign="top"><a href="#skip_multipart-1">skip_multipart/1</a></td><td>Stream the response body.</td></tr><tr><td valign="top"><a href="#sockname-1">sockname/1</a></td><td>sockname of the client.</td></tr><tr><td valign="top"><a href="#start_response-1">start_response/1</a></td><td>start a response.</td></tr><tr><td valign="top"><a href="#stop_async-1">stop_async/1</a></td><td>stop to receive asynchronously.</td></tr><tr><td valign="top"><a href="#stream_body-1">stream_body/1</a></td><td>Stream the response body.</td></tr><tr><td valign="top"><a href="#stream_multipart-1">stream_multipart/1</a></td><td>Stream the response body.</td></tr><tr><td valign="top"><a href="#stream_next-1">stream_next/1</a></td><td>continue to the next stream message.</td></tr></table>


<a name="functions"></a>
Expand Down Expand Up @@ -208,6 +208,14 @@ pause_stream(Ref::<a href="#type-client_ref">client_ref()</a>) -&gt; ok | {error
pause a response stream, the stream process will hibernate and
be woken later by the resume function

<a name="peername-1"></a>

### peername/1 ###

`peername(Ref) -> any()`

peername of the client

<a name="redirect_location-1"></a>

### redirect_location/1 ###
Expand Down Expand Up @@ -547,6 +555,14 @@ skip_multipart(Ref::<a href="#type-client_ref">client_ref()</a>) -&gt; ok | {err

Stream the response body.

<a name="sockname-1"></a>

### sockname/1 ###

`sockname(Ref) -> any()`

sockname of the client

<a name="start_response-1"></a>

### start_response/1 ###
Expand Down
18 changes: 17 additions & 1 deletion doc/hackney_connect.md
Expand Up @@ -9,7 +9,7 @@
## Function Index ##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#check_or_close-1">check_or_close/1</a></td><td></td></tr><tr><td valign="top"><a href="#close-1">close/1</a></td><td>close the client.</td></tr><tr><td valign="top"><a href="#connect-3">connect/3</a></td><td></td></tr><tr><td valign="top"><a href="#connect-4">connect/4</a></td><td></td></tr><tr><td valign="top"><a href="#connect-5">connect/5</a></td><td></td></tr><tr><td valign="top"><a href="#create_connection-4">create_connection/4</a></td><td>create a connection and return a client state.</td></tr><tr><td valign="top"><a href="#create_connection-5">create_connection/5</a></td><td></td></tr><tr><td valign="top"><a href="#is_pool-1">is_pool/1</a></td><td>get current pool pid or name used by a client if needed.</td></tr><tr><td valign="top"><a href="#maybe_connect-1">maybe_connect/1</a></td><td>connect a socket and create a client state.</td></tr><tr><td valign="top"><a href="#partial_chain-1">partial_chain/1</a></td><td></td></tr><tr><td valign="top"><a href="#reconnect-4">reconnect/4</a></td><td></td></tr><tr><td valign="top"><a href="#set_sockopts-2">set_sockopts/2</a></td><td>add set sockets options in the client.</td></tr><tr><td valign="top"><a href="#ssl_opts-2">ssl_opts/2</a></td><td></td></tr></table>
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#check_or_close-1">check_or_close/1</a></td><td></td></tr><tr><td valign="top"><a href="#close-1">close/1</a></td><td>close the client.</td></tr><tr><td valign="top"><a href="#connect-3">connect/3</a></td><td></td></tr><tr><td valign="top"><a href="#connect-4">connect/4</a></td><td></td></tr><tr><td valign="top"><a href="#connect-5">connect/5</a></td><td></td></tr><tr><td valign="top"><a href="#create_connection-4">create_connection/4</a></td><td>create a connection and return a client state.</td></tr><tr><td valign="top"><a href="#create_connection-5">create_connection/5</a></td><td></td></tr><tr><td valign="top"><a href="#is_pool-1">is_pool/1</a></td><td>get current pool pid or name used by a client if needed.</td></tr><tr><td valign="top"><a href="#maybe_connect-1">maybe_connect/1</a></td><td>connect a socket and create a client state.</td></tr><tr><td valign="top"><a href="#partial_chain-1">partial_chain/1</a></td><td></td></tr><tr><td valign="top"><a href="#peername-1">peername/1</a></td><td>get the address and port for the other end of current connection in the client.</td></tr><tr><td valign="top"><a href="#reconnect-4">reconnect/4</a></td><td></td></tr><tr><td valign="top"><a href="#set_sockopts-2">set_sockopts/2</a></td><td>add set sockets options in the client.</td></tr><tr><td valign="top"><a href="#sockname-1">sockname/1</a></td><td>the local address and port of current socket in the client.</td></tr><tr><td valign="top"><a href="#ssl_opts-2">ssl_opts/2</a></td><td></td></tr></table>


<a name="functions"></a>
Expand Down Expand Up @@ -84,6 +84,14 @@ connect a socket and create a client state.

`partial_chain(Certs) -> any()`

<a name="peername-1"></a>

### peername/1 ###

`peername(Client) -> any()`

get the address and port for the other end of current connection in the client

<a name="reconnect-4"></a>

### reconnect/4 ###
Expand All @@ -98,6 +106,14 @@ connect a socket and create a client state.

add set sockets options in the client

<a name="sockname-1"></a>

### sockname/1 ###

`sockname(Client) -> any()`

the local address and port of current socket in the client

<a name="ssl_opts-2"></a>

### ssl_opts/2 ###
Expand Down
26 changes: 16 additions & 10 deletions doc/overview.edoc
Expand Up @@ -118,8 +118,8 @@ $ ./rebar3 shell
It is suggested that you install rebar3 user-wide as described [here](http://blog.erlware.org/rebar3-features-part-1-local-install-and-upgrade/).
This fixes zsh (and maybe other shells) escript-related bugs. Also this should speed things up.

<pre lang="erlang-repl">
1>> application:ensure_all_started(hackney).
<pre lang="erlang">
> application:ensure_all_started(hackney).
ok</pre>

It will start hackney and all of the application it depends on:
Expand Down Expand Up @@ -161,14 +161,14 @@ where `Method', can be any HTTP method in lowercase.

### Read the body

<pre lang="erlang">{ok, Body} = hackney:body(Client).</pre>
<pre lang="erlang">{ok, Body} = hackney:body(ClientRef).</pre>

`hackney:body/1' fetch the body. To fetch it by chunk you can use the
`hackney:stream_body/1' function:

<pre lang="erlang">
read_body(MaxLength, Ref, Acc) when MaxLength > byte_size(Acc) ->
case stream_body(Ref) of
case hackney:stream_body(Ref) of
{ok, Data} ->
read_body(MaxLength, Ref, &lt;&lt; Acc/binary, Data/binary >>);
done ->
Expand All @@ -194,15 +194,21 @@ couple of requests.
#### To create a connection:

<pre lang="erlang">
Transport = hackney_tcp,
Host = &lt;&lt; "https://friendpaste.com" >>,
Transport = hackney_ssl,
Host = &lt;&lt; "friendpaste.com" >>,
Port = 443,
Options = [],
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options)</pre>
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options).</pre>

> To create a connection that will use an HTTP proxy use
> `hackney_http_proxy:connect_proxy/5' instead.

#### To get local and remote ip and port information of a connection:

<pre lang="erlang">
> hackney:peername(ConnRef).
> hackney:sockname(ConnRef).</pre>

#### Make a request

Once you created a connection use the `hackney:send_request/2' function
Expand All @@ -213,9 +219,9 @@ ReqBody = &lt;&lt; "{ \"snippet\": \"some snippet\" }" >>,
ReqHeaders = [{&lt;&lt;"Content-Type">>, &lt;&lt;"application/json">>}],
NextPath = &lt;&lt;"/">>,
NextMethod = post,
NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody}
{ok, _, _, ConnRef} = hackney:send_request(ConnRef, NextReq).
{ok, Body1} = hackney:body(ConnRef),</pre>
NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody},
{ok, _, _, ConnRef} = hackney:send_request(ConnRef, NextReq),
{ok, Body1} = hackney:body(ConnRef).</pre>

Here we are posting a JSON payload to '/' on the friendpaste service to
create a paste. Then we close the client connection.
Expand Down
10 changes: 10 additions & 0 deletions src/hackney.erl
Expand Up @@ -8,6 +8,8 @@

-export([connect/1, connect/2, connect/3, connect/4,
close/1,
peername/1,
sockname/1,
request_info/1,
location/1,
request/1, request/2, request/3, request/4, request/5,
Expand Down Expand Up @@ -116,6 +118,14 @@ close(Ref) ->
hackney_connect:close(Ref).


%% @doc peername of the client
peername(Ref) ->
hackney_connect:peername(Ref).

%% @doc sockname of the client
sockname(Ref) ->
hackney_connect:sockname(Ref).

%% @doc get request info
-spec request_info(client_ref()) -> list().
request_info(Ref) ->
Expand Down
25 changes: 25 additions & 0 deletions src/hackney_connect.erl
Expand Up @@ -12,6 +12,8 @@
set_sockopts/2,
ssl_opts/2,
check_or_close/1,
peername/1,
sockname/1,
close/1,
is_pool/1]).

Expand Down Expand Up @@ -135,6 +137,29 @@ set_sockopts(#client{transport=Transport, socket=Skt}, Options) ->
Transport:setopts(Skt, Options).


%% @doc get the address and port for the other end of current connection in the client
peername(#client{transport=Transport, socket=Socket}) ->
Transport:peername(Socket);
peername(Ref) when is_reference(Ref) ->
case hackney_manager:get_state(Ref) of
req_not_found ->
req_not_found;
Client ->
peername(Client)
end.


%% @doc the local address and port of current socket in the client
sockname(#client{transport=Transport, socket=Socket}) ->
Transport:sockname(Socket);
sockname(Ref) when is_reference(Ref) ->
case hackney_manager:get_state(Ref) of
req_not_found ->
req_not_found;
Client ->
sockname(Client)
end.

%% @doc close the client
%%
%%
Expand Down

0 comments on commit d6b0b05

Please sign in to comment.