URL encoder à Erlang
Question
J'utilise erlang http: demande d'envoi de données à un service distant. La publication fonctionne, mais les données figurant dans le corps () de la publication sont transmises telles quelles, sans aucun codage d’URL, ce qui entraîne l’échec de la publication lorsqu’il est analysé par le service distant.
Existe-t-il une fonction dans Erlang similaire à CGI.escape dans Ruby?
Autres conseils
J'ai également rencontré le manque de cette fonctionnalité dans les modules HTTP.
Il s’avère que cette fonctionnalité est effectivement disponible dans la distribution erlang, vous devez juste y jeter un œil.
> edoc_lib:escape_uri("luca+more@here.com").
"luca%2bmore%40here.com"
Cela se comporte comme CGI.escape dans Ruby, il existe également URI.escape qui se comporte légèrement différemment:
> CGI.escape("luca+more@here.com")
=> "luca%2Bmore%40here.com"
> URI.escape("luca+more@here.com")
=> "luca+more@here.com"
Au moins dans la R15, il existe http_uri: encode / 1 qui fait le travail. De plus, je ne recommanderais pas d'utiliser edoc_lib: escape_uri pour traduire un '=' en% 3d au lieu de% 3D, ce qui m'a causé quelques problèmes.
Voici une fonction simple qui fait le travail. Il est conçu pour fonctionner directement avec Inets httpc.
%% @doc A function to URL encode form data.
%% @spec url_encode(formdata()).
-spec(url_encode(formdata()) -> string()).
url_encode(Data) ->
url_encode(Data,"").
url_encode([],Acc) ->
Acc;
url_encode([{Key,Value}|R],"") ->
url_encode(R, edoc_lib:escape_uri(Key) ++ "=" ++ edoc_lib:escape_uri(Value));
url_encode([{Key,Value}|R],Acc) ->
url_encode(R, Acc ++ "&" ++ edoc_lib:escape_uri(Key) ++ "=" ++ edoc_lib:escape_uri(Value)).
Exemple d'utilisation:
httpc:request(post, {"http://localhost:3000/foo", [],
"application/x-www-form-urlencoded",
url_encode([{"username", "bob"}, {"password", "123456"}])}
,[],[]).
Pour répondre à ma propre question ... j'ai trouvé cette bibliothèque dans ibrowse!
http: //www.erlware .org / lib / 5.6.3 / ibrowse-1.4 / ibrowse_lib.html # url_encode-1
url_encode/1
url_encode(Str) -> UrlEncodedStr
Str = string()
UrlEncodedStr = string()
URL: code une chaîne basée sur RFC 1738. Renvoie une liste simple.
Je suppose que je peux utiliser ceci pour encoder tout en utilisant http:
Si quelqu'un a besoin d'un code uri qui fonctionne avec utf-8 dans erlang:
https://gist.github.com/3796470
Ex.
Eshell V5.9.1 (abort with ^G)
1> c(encode_uri_rfc3986).
{ok,encode_uri_rfc3986}
2> encode_uri_rfc3986:encode("テスト").
"%e3%83%86%e3%82%b9%e3%83%88"
3> edoc_lib:escape_uri("テスト").
"%c3%86%c2%b9%c3%88" # output wrong: ƹÈ
Voici une "fourchette". de la fonction edoc_lib: escape_uri qui améliore le support UTF-8 et supporte également les fichiers binaires.
escape_uri(S) when is_list(S) ->
escape_uri(unicode:characters_to_binary(S));
escape_uri(<<C:8, Cs/binary>>) when C >= $a, C =< $z ->
[C] ++ escape_uri(Cs);
escape_uri(<<C:8, Cs/binary>>) when C >= $A, C =< $Z ->
[C] ++ escape_uri(Cs);
escape_uri(<<C:8, Cs/binary>>) when C >= <*>, C =< $9 ->
[C] ++ escape_uri(Cs);
escape_uri(<<C:8, Cs/binary>>) when C == $. ->
[C] ++ escape_uri(Cs);
escape_uri(<<C:8, Cs/binary>>) when C == $- ->
[C] ++ escape_uri(Cs);
escape_uri(<<C:8, Cs/binary>>) when C == Voici une "fourchette". de la fonction edoc_lib: escape_uri qui améliore le support UTF-8 et supporte également les fichiers binaires.
<*>
Notez que, en raison de l'utilisation de l'unicode: characters_to_binary, il ne fonctionnera que dans les versions R13 ou plus récentes.
->
[C] ++ escape_uri(Cs);
escape_uri(<<C:8, Cs/binary>>) ->
escape_byte(C) ++ escape_uri(Cs);
escape_uri(<<>>) ->
"".
escape_byte(C) ->
"%" ++ hex_octet(C).
hex_octet(N) when N =< 9 ->
[<*> + N];
hex_octet(N) when N > 15 ->
hex_octet(N bsr 4) ++ hex_octet(N band 15);
hex_octet(N) ->
[N - 10 + $a].
Notez que, en raison de l'utilisation de l'unicode: characters_to_binary, il ne fonctionnera que dans les versions R13 ou plus récentes.
% Utility function to convert a 'form' of name-value pairs into a URL encoded
% content string.
urlencode(Form) ->
RevPairs = lists:foldl(fun({K,V},Acc) -> [[quote_plus(K),$=,quote_plus(V)] | Acc] end, [],Form),
lists:flatten(revjoin(RevPairs,<*>amp;,[])).
quote_plus(Atom) when is_atom(Atom) ->
quote_plus(atom_to_list(Atom));
quote_plus(Int) when is_integer(Int) ->
quote_plus(integer_to_list(Int));
quote_plus(String) ->
quote_plus(String, []).
quote_plus([], Acc) ->
lists:reverse(Acc);
quote_plus([C | Rest], Acc) when ?QS_SAFE(C) ->
quote_plus(Rest, [C | Acc]);
quote_plus([$\s | Rest], Acc) ->
quote_plus(Rest, [<*> | Acc]);
quote_plus([C | Rest], Acc) ->
<<Hi:4, Lo:4>> = <<C>>,
quote_plus(Rest, [hexdigit(Lo), hexdigit(Hi), ?PERCENT | Acc]).
revjoin([], _Separator, Acc) ->
Acc;
revjoin([S | Rest],Separator,[]) ->
revjoin(Rest,Separator,[S]);
revjoin([S | Rest],Separator,Acc) ->
revjoin(Rest,Separator,[S,Separator | Acc]).
hexdigit(C) when C < 10 -> <*> + C;
hexdigit(C) when C < 16 -> $A + (C - 10).