URL用Erlang编码
时间:2020-03-06 14:32:01 来源:igfitidea点击:
我正在使用erlang http:request将一些数据发布到远程服务。我有帖子在工作,但是帖子的body()中的数据按原样通过,没有任何url编码,这导致帖子在通过远程服务进行解析时失败。
为此,Erlang中是否有一个类似于Ruby中的CGI.escape的函数?
解决方案
AFAIK标准库中没有URL编码器。认为我从YAWS或者其他Erlang Web服务器之一"借用了"以下代码:
% 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,$&,[])). 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 ->url_encode/1 url_encode(Str) -> UrlEncodedStr Str = string() UrlEncodedStr = string()+ C; hexdigit(C) when C < 16 -> $A + (C - 10).
要回答我自己的问题...我在ibrowse中找到了这个库!
http://www.erlware.org/lib/5.6.3/ibrowse-1.4/ibrowse_lib.html#url_encode-1
> edoc_lib:escape_uri("[email protected]"). "luca%2bmore%40here.com"
对基于RFC 1738的字符串进行URL编码。返回平面列表。
我想我可以用它来进行编码,仍然使用http:
我们可以在此处找到YAWS urlencode和urldecode例程
它们非常简单,尽管注释表明所有标点字符的编码都不是100%完整。
我也遇到了HTTP模块中缺少此功能的问题。
事实证明,此功能实际上在erlang发行版中可用,我们只需要看起来就足够难了。
> CGI.escape("[email protected]") => "luca%2Bmore%40here.com" > URI.escape("[email protected]") => "[email protected]"
行为类似于Ruby中的CGI.escape,还有URI.escape,其行为略有不同:
%% @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)).
edoc_lib
这是一个完成任务的简单函数。它旨在直接与inets httpc一起使用。
httpc:request(post, {"http://localhost:3000/foo", [], "application/x-www-form-urlencoded", url_encode([{"username", "bob"}, {"password", "123456"}])} ,[],[]).
用法示例:
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 =< -> [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 == $_ -> [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].
这是edoc_lib:escape_uri函数的一个"分支",它对UTF-8的支持有所改进,并且还支持二进制文件。
##代码##请注意,由于使用unicode:characters_to_binary,因此只能在R13或者更高版本中使用。