From 0cd34961e90d4b25208c5b5ffe67da7f5c7ab102 Mon Sep 17 00:00:00 2001 From: benoitc Date: Mon, 21 Mar 2016 10:21:10 +0100 Subject: [PATCH] add path_encode_fun option to request This function allows the users to bypass default hackney strict PATH encoding similar chromium algorithm. So they can handle servers that need a specific encoding. fix #277; #272, #246 --- doc/hackney.md | 4 ++++ doc/hackney_url.md | 22 ++++++++++++++++++++-- src/hackney.erl | 9 ++++++++- src/hackney_url.erl | 20 ++++++++++++++++---- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/doc/hackney.md b/doc/hackney.md index 30f128b6..97a55aac 100644 --- a/doc/hackney.md +++ b/doc/hackney.md @@ -317,6 +317,10 @@ When {async, once} is used the response will be received only once. To receive the other messages use the function `hackney:stream_next/1` +* `{path_encode_fun, fun()}`: function used to encode the path. if +not set it will use `hackney_url:path_encode/1` the function takes the +binary path as entry and return a new encoded path. + * `{stream_to, pid()}`: If async is true or once, the response messages will be sent to this PID. diff --git a/doc/hackney_url.md b/doc/hackney_url.md index 1def6371..02e8b8ee 100644 --- a/doc/hackney_url.md +++ b/doc/hackney_url.md @@ -28,7 +28,8 @@ qs_vals() = [{binary(), binary() | true}]
fix_path/1
make_url/3 construct an url from a base url, a path and a list of -properties to give to the url.
normalize/1Normalizes the encoding of a Url.
parse_qs/1
parse_url/1Parse an url and return a #hackney_url record.
pathencode/1encode a URL path.
qs/1encode query properties to binary.
transport_scheme/1
unparse_url/1
urldecode/1Decode a URL encoded binary.
urldecode/2Decode a URL encoded binary.
urlencode/1URL encode a string binary.
urlencode/2URL encode a string binary.
+properties to give to the url.normalize/1Normalizes the encoding of a Url +use the hackney_url:pathencode/1 to encode an url.normalize/2Normalizes the encoding of a Url.parse_qs/1parse_url/1Parse an url and return a #hackney_url record.pathencode/1encode a URL path.qs/1encode query properties to binary.transport_scheme/1unparse_url/1urldecode/1Decode a URL encoded binary.urldecode/2Decode a URL encoded binary.urlencode/1URL encode a string binary.urlencode/2URL encode a string binary. @@ -57,7 +58,24 @@ properties to give to the url. ### normalize/1 ### -`normalize(Url) -> any()` +

+normalize(URL) -> NormalizedUrl
+
+ + + +Normalizes the encoding of a Url +use the hackney_url:pathencode/1 to encode an url + + + +### normalize/2 ### + +

+normalize(URL, Fun) -> NormalizedUrl
+
+ + Normalizes the encoding of a Url diff --git a/src/hackney.erl b/src/hackney.erl index fd8539fc..d4d5950e 100644 --- a/src/hackney.erl +++ b/src/hackney.erl @@ -221,6 +221,9 @@ request(Method, URL, Headers, Body) -> %% receive the other messages use the function %% `hackney:stream_next/1' %% +%%
  • `{path_encode_fun, fun()}': function used to encode the path. if +%% not set it will use `hackney_url:path_encode/1' the function takes the +%% binary path as entry and return a new encoded path.
  • %% %%
  • `{stream_to, pid()}': If async is true or once, the response %% messages will be sent to this PID.
  • @@ -295,8 +298,12 @@ request(Method, URL, Headers, Body) -> | {ok, client_ref()} | {error, term()}. request(Method, #hackney_url{}=URL0, Headers, Body, Options0) -> + PathEncodeFun = proplists:get_value(path_encode_fun, Options0, + fun hackney_url:encodepath/1), + + %% normalize the url encoding - URL = hackney_url:normalize(URL0), + URL = hackney_url:normalize(URL0, PathEncodeFun), ?report_trace("request", [{method, Method}, {url, URL}, diff --git a/src/hackney_url.erl b/src/hackney_url.erl index 5fe918d0..530512f8 100644 --- a/src/hackney_url.erl +++ b/src/hackney_url.erl @@ -21,7 +21,7 @@ make_url/3, fix_path/1, pathencode/1, - normalize/1]). + normalize/1, normalize/2]). -include("hackney_lib.hrl"). @@ -61,9 +61,21 @@ parse_url(URL, S) -> end. %% @doc Normalizes the encoding of a Url -normalize(Url) when is_list(Url) orelse is_binary(Url) -> - normalize(parse_url(Url)); -normalize(#hackney_url{}=Url) -> +%% use the hackney_url:pathencode/1 to encode an url +-spec normalize(URL) -> NormalizedUrl when + URL :: binary() | list() | hackney_url(), + NormalizedUrl :: hackney_url(). +normalize(Url) -> + normalize(Url, fun hackney_url:pathencode/1). + +%% @doc Normalizes the encoding of a Url +-spec normalize(URL, Fun) -> NormalizedUrl when + URL :: binary() | list() | hackney_url(), + Fun :: fun(), + NormalizedUrl :: hackney_url(). +normalize(Url, Fun) when is_list(Url) orelse is_binary(Url) -> + normalize(parse_url(Url), Fun); +normalize(#hackney_url{}=Url, Fun) when is_function(Fun, 1) -> #hackney_url{scheme=Scheme, host = Host0, port = Port,