Skip to content

Commit 499de03

Browse files
c-bikbenoitc
authored andcommitted
sockname and peername access from hackney module (#504)
* add sockname and peername methods to the hackney module. * improve example * sockname and peername helper info APIs
1 parent 1e30cee commit 499de03

File tree

8 files changed

+124
-32
lines changed

8 files changed

+124
-32
lines changed

README.md

+19-10
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ $ ./rebar3 shell
100100
It is suggested that you install rebar3 user-wide as described [here](http://blog.erlware.org/rebar3-features-part-1-local-install-and-upgrade/).
101101
This fixes zsh (and maybe other shells) escript-related bugs. Also this should speed things up.
102102

103-
```erlang-repl
103+
```erlang
104104

105-
1>> application:ensure_all_started(hackney).
105+
> application:ensure_all_started(hackney).
106106
ok
107107
```
108108

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

151151
```erlang
152-
{ok, Body} = hackney:body(Client).
152+
{ok, Body} = hackney:body(ClientRef).
153153
```
154154

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

160160
read_body(MaxLength, Ref, Acc) when MaxLength > byte_size(Acc) ->
161-
case stream_body(Ref) of
161+
case hackney:stream_body(Ref) of
162162
{ok, Data} ->
163163
read_body(MaxLength, Ref, << Acc/binary, Data/binary >>);
164164
done ->
@@ -186,30 +186,39 @@ couple of requests.
186186

187187
```erlang
188188

189-
Transport = hackney_tcp,
190-
Host = << "https://friendpaste.com" >>,
189+
Transport = hackney_ssl,
190+
Host = << "friendpaste.com" >>,
191191
Port = 443,
192192
Options = [],
193-
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options)
193+
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options).
194194
```
195195

196196
> To create a connection that will use an HTTP proxy use
197197
> `hackney_http_proxy:connect_proxy/5` instead.
198198
199+
200+
#### To get local and remote ip and port information of a connection:
201+
202+
```erlang
203+
204+
> hackney:peername(ConnRef).
205+
> hackney:sockname(ConnRef).
206+
```
207+
199208
#### Make a request
200209

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

204213
```erlang
205214

206-
ReqBody = << "{ \"snippet\": \"some snippet\" }" >>,
215+
ReqBody = << "{\"snippet\": \"some snippet\"}" >>,
207216
ReqHeaders = [{<<"Content-Type">>, <<"application/json">>}],
208217
NextPath = <<"/">>,
209218
NextMethod = post,
210-
NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody}
219+
NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody},
211220
{ok, _, _, ConnRef} = hackney:send_request(ConnRef, NextReq).
212-
{ok, Body1} = hackney:body(ConnRef),
221+
{ok, Body1} = hackney:body(ConnRef).
213222
```
214223

215224
Here we are posting a JSON payload to '/' on the friendpaste service to

THANKS

+1
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ Mayorov Andrey <[email protected]>
3030
3131
Pavel Abalihin <[email protected]>
3232
Ilya Khaprov <[email protected]>
33+
Bikram Chatterjee <[email protected]>

doc/README.md

+18-9
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ $ ./rebar3 shell
100100
It is suggested that you install rebar3 user-wide as described [here](http://blog.erlware.org/rebar3-features-part-1-local-install-and-upgrade/).
101101
This fixes zsh (and maybe other shells) escript-related bugs. Also this should speed things up.
102102

103-
```erlang-repl
103+
```erlang
104104

105-
1>> application:ensure_all_started(hackney).
105+
> application:ensure_all_started(hackney).
106106
ok
107107
```
108108

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

151151
```erlang
152-
{ok, Body} = hackney:body(Client).
152+
{ok, Body} = hackney:body(ClientRef).
153153
```
154154

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

160160
read_body(MaxLength, Ref, Acc) when MaxLength > byte_size(Acc) ->
161-
case stream_body(Ref) of
161+
case hackney:stream_body(Ref) of
162162
{ok, Data} ->
163163
read_body(MaxLength, Ref, << Acc/binary, Data/binary >>);
164164
done ->
@@ -186,16 +186,25 @@ couple of requests.
186186

187187
```erlang
188188

189-
Transport = hackney_tcp,
190-
Host = << "https://friendpaste.com" >>,
189+
Transport = hackney_ssl,
190+
Host = << "friendpaste.com" >>,
191191
Port = 443,
192192
Options = [],
193-
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options)
193+
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options).
194194
```
195195

196196
> To create a connection that will use an HTTP proxy use
197197
> `hackney_http_proxy:connect_proxy/5` instead.
198198
199+
200+
#### To get local and remote ip and port information of a connection:
201+
202+
```erlang
203+
204+
> hackney:peername(ConnRef).
205+
> hackney:sockname(ConnRef).
206+
```
207+
199208
#### Make a request
200209

201210
Once you created a connection use the `hackney:send_request/2` function
@@ -207,9 +216,9 @@ ReqBody = << "{ \"snippet\": \"some snippet\" }" >>,
207216
ReqHeaders = [{<<"Content-Type">>, <<"application/json">>}],
208217
NextPath = <<"/">>,
209218
NextMethod = post,
210-
NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody}
219+
NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody},
211220
{ok, _, _, ConnRef} = hackney:send_request(ConnRef, NextReq).
212-
{ok, Body1} = hackney:body(ConnRef),
221+
{ok, Body1} = hackney:body(ConnRef).
213222
```
214223

215224
Here we are posting a JSON payload to '/' on the friendpaste service to

doc/hackney.md

+18-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ url() = #hackney_url{} | binary()
4646
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
4747
This feature can be useful when you want to create a simple proxy, rerouting
4848
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
49-
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
49+
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
5050
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
5151
Possible value are :
5252
<ul>
@@ -71,7 +71,7 @@ multipart content</li>
7171
multipart content</li>
7272
</ul><p></p>Note: You can calculate the full length of a multipart stream using
7373
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
74-
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>
74+
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>
7575

7676

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

211+
<a name="peername-1"></a>
212+
213+
### peername/1 ###
214+
215+
`peername(Ref) -> any()`
216+
217+
peername of the client
218+
211219
<a name="redirect_location-1"></a>
212220

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

548556
Stream the response body.
549557

558+
<a name="sockname-1"></a>
559+
560+
### sockname/1 ###
561+
562+
`sockname(Ref) -> any()`
563+
564+
sockname of the client
565+
550566
<a name="start_response-1"></a>
551567

552568
### start_response/1 ###

doc/hackney_connect.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
## Function Index ##
1010

1111

12-
<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>
12+
<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>
1313

1414

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

8585
`partial_chain(Certs) -> any()`
8686

87+
<a name="peername-1"></a>
88+
89+
### peername/1 ###
90+
91+
`peername(Client) -> any()`
92+
93+
get the address and port for the other end of current connection in the client
94+
8795
<a name="reconnect-4"></a>
8896

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

99107
add set sockets options in the client
100108

109+
<a name="sockname-1"></a>
110+
111+
### sockname/1 ###
112+
113+
`sockname(Client) -> any()`
114+
115+
the local address and port of current socket in the client
116+
101117
<a name="ssl_opts-2"></a>
102118

103119
### ssl_opts/2 ###

doc/overview.edoc

+16-10
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ $ ./rebar3 shell
118118
It is suggested that you install rebar3 user-wide as described [here](http://blog.erlware.org/rebar3-features-part-1-local-install-and-upgrade/).
119119
This fixes zsh (and maybe other shells) escript-related bugs. Also this should speed things up.
120120

121-
<pre lang="erlang-repl">
122-
1>> application:ensure_all_started(hackney).
121+
<pre lang="erlang">
122+
> application:ensure_all_started(hackney).
123123
ok</pre>
124124

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

162162
### Read the body
163163

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

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

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

196196
<pre lang="erlang">
197-
Transport = hackney_tcp,
198-
Host = &lt;&lt; "https://friendpaste.com" >>,
197+
Transport = hackney_ssl,
198+
Host = &lt;&lt; "friendpaste.com" >>,
199199
Port = 443,
200200
Options = [],
201-
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options)</pre>
201+
{ok, ConnRef} = hackney:connect(Transport, Host, Port, Options).</pre>
202202

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

206+
#### To get local and remote ip and port information of a connection:
207+
208+
<pre lang="erlang">
209+
> hackney:peername(ConnRef).
210+
> hackney:sockname(ConnRef).</pre>
211+
206212
#### Make a request
207213

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

220226
Here we are posting a JSON payload to '/' on the friendpaste service to
221227
create a paste. Then we close the client connection.

src/hackney.erl

+10
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
-export([connect/1, connect/2, connect/3, connect/4,
1010
close/1,
11+
peername/1,
12+
sockname/1,
1113
request_info/1,
1214
location/1,
1315
request/1, request/2, request/3, request/4, request/5,
@@ -116,6 +118,14 @@ close(Ref) ->
116118
hackney_connect:close(Ref).
117119

118120

121+
%% @doc peername of the client
122+
peername(Ref) ->
123+
hackney_connect:peername(Ref).
124+
125+
%% @doc sockname of the client
126+
sockname(Ref) ->
127+
hackney_connect:sockname(Ref).
128+
119129
%% @doc get request info
120130
-spec request_info(client_ref()) -> list().
121131
request_info(Ref) ->

src/hackney_connect.erl

+25
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
set_sockopts/2,
1313
ssl_opts/2,
1414
check_or_close/1,
15+
peername/1,
16+
sockname/1,
1517
close/1,
1618
is_pool/1]).
1719

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

137139

140+
%% @doc get the address and port for the other end of current connection in the client
141+
peername(#client{transport=Transport, socket=Socket}) ->
142+
Transport:peername(Socket);
143+
peername(Ref) when is_reference(Ref) ->
144+
case hackney_manager:get_state(Ref) of
145+
req_not_found ->
146+
req_not_found;
147+
Client ->
148+
peername(Client)
149+
end.
150+
151+
152+
%% @doc the local address and port of current socket in the client
153+
sockname(#client{transport=Transport, socket=Socket}) ->
154+
Transport:sockname(Socket);
155+
sockname(Ref) when is_reference(Ref) ->
156+
case hackney_manager:get_state(Ref) of
157+
req_not_found ->
158+
req_not_found;
159+
Client ->
160+
sockname(Client)
161+
end.
162+
138163
%% @doc close the client
139164
%%
140165
%%

0 commit comments

Comments
 (0)