瀏覽代碼

Use Erlang's OTP base64 module (available since R12B02) and avoid duplicated base64

encoding/decoding code in ibrowse_lib.erl and ibrowse_http_client.erl.

OTP's base64 module is also more efficient (C implementation):

1> Data = crypto:rand_bytes(4096).
<<205,174,13,169,97,159,110,161,71,43,226,153,42,101,243,
  83,11,96,23,161,253,251,129,240,163,216,58,175,190,...>>
2>
2> timer:tc(ibrowse_lib, encode_base64, [Data]).
{2920,
 <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>}
3> timer:tc(ibrowse_lib, encode_base64, [Data]).
{1221,
 <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>}
4> timer:tc(ibrowse_lib, encode_base64, [Data]).
{1436,
 <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>}
5> timer:tc(ibrowse_lib, encode_base64, [Data]).
{1195,
 <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>}
6>
6> timer:tc(base64, encode, [Data]).
{1846,
 <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>}
7> timer:tc(base64, encode, [Data]).
{743,
 <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>}
8> timer:tc(base64, encode, [Data]).
{737,
 <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>}
9> timer:tc(base64, encode, [Data]).
{656,
 <<"za4NqWGfbqFHK+KZKmXzUwtgF6H9+4Hwo9g6r77h2EF1/Xk1oKOIOmnAkgtv41LPXg37fp2dlr45C8qCA9/8zrcc9F5zr2JT0eVPTrh5aahl"...>>}
pull/16/head
Filipe David Manana 15 年之前
父節點
當前提交
1bdc1185c6
共有 2 個檔案被更改,包括 5 行新增86 行删除
  1. +1
    -21
      src/ibrowse_http_client.erl
  2. +4
    -65
      src/ibrowse_lib.erl

+ 1
- 21
src/ibrowse_http_client.erl 查看文件

@ -765,27 +765,7 @@ add_proxy_auth_headers(#state{proxy_auth_digest = Auth_digest}, Headers) ->
http_auth_digest([], []) ->
[];
http_auth_digest(Username, Password) ->
encode_base64(Username ++ [$: | Password]).
encode_base64([]) ->
[];
encode_base64([A]) ->
[e(A bsr 2), e((A band 3) bsl 4), $=, $=];
encode_base64([A,B]) ->
[e(A bsr 2), e(((A band 3) bsl 4) bor (B bsr 4)), e((B band 15) bsl 2), $=];
encode_base64([A,B,C|Ls]) ->
encode_base64_do(A,B,C, Ls).
encode_base64_do(A,B,C, Rest) ->
BB = (A bsl 16) bor (B bsl 8) bor C,
[e(BB bsr 18), e((BB bsr 12) band 63),
e((BB bsr 6) band 63), e(BB band 63)|encode_base64(Rest)].
e(X) when X >= 0, X < 26 -> X+65;
e(X) when X>25, X<52 -> X+71;
e(X) when X>51, X<62 -> X-4;
e(62) -> $+;
e(63) -> $/;
e(X) -> exit({bad_encode_base64_token, X}).
ibrowse_lib:encode_base64(Username ++ [$: | Password]).
make_request(Method, Headers, AbsPath, RelPath, Body, Options,
#state{use_proxy = UseProxy}) ->

+ 4
- 65
src/ibrowse_lib.erl 查看文件

@ -177,79 +177,18 @@ dec2hex(M,N,Ack) -> dec2hex(M-1,N bsr 4,[d2h(N band 15)|Ack]).
%% In = string() | binary()
%% Out = string() | binary()
encode_base64(List) when is_list(List) ->
encode_base64_1(list_to_binary(List));
binary_to_list(base64:encode(List));
encode_base64(Bin) when is_binary(Bin) ->
List = encode_base64_1(Bin),
list_to_binary(List).
encode_base64_1(<<A:6, B:6, C:6, D:6, Rest/binary>>) ->
[int_to_b64(A), int_to_b64(B),
int_to_b64(C), int_to_b64(D) | encode_base64_1(Rest)];
encode_base64_1(<<A:6, B:6, C:4>>) ->
[int_to_b64(A), int_to_b64(B), int_to_b64(C bsl 2), $=];
encode_base64_1(<<A:6, B:2>>) ->
[int_to_b64(A), int_to_b64(B bsl 4), $=, $=];
encode_base64_1(<<>>) ->
[].
base64:encode(Bin).
%% @doc Implements the base64 decoding algorithm. The output data type matches in the input data type.
%% @spec decode_base64(In) -> Out | exit({error, invalid_input})
%% In = string() | binary()
%% Out = string() | binary()
decode_base64(List) when is_list(List) ->
decode_base64_1(List, []);
binary_to_list(base64:decode(List));
decode_base64(Bin) when is_binary(Bin) ->
List = decode_base64_1(binary_to_list(Bin), []),
list_to_binary(List).
decode_base64_1([H | T], Acc) when ((H == $\t) or
(H == 32) or
(H == $\r) or
(H == $\n)) ->
decode_base64_1(T, Acc);
decode_base64_1([$=, $=], Acc) ->
lists:reverse(Acc);
decode_base64_1([$=, _ | _], _Acc) ->
exit({error, invalid_input});
decode_base64_1([A1, B1, $=, $=], Acc) ->
A = b64_to_int(A1),
B = b64_to_int(B1),
Oct1 = (A bsl 2) bor (B bsr 4),
decode_base64_1([], [Oct1 | Acc]);
decode_base64_1([A1, B1, C1, $=], Acc) ->
A = b64_to_int(A1),
B = b64_to_int(B1),
C = b64_to_int(C1),
Oct1 = (A bsl 2) bor (B bsr 4),
Oct2 = ((B band 16#f) bsl 6) bor (C bsr 2),
decode_base64_1([], [Oct2, Oct1 | Acc]);
decode_base64_1([A1, B1, C1, D1 | T], Acc) ->
A = b64_to_int(A1),
B = b64_to_int(B1),
C = b64_to_int(C1),
D = b64_to_int(D1),
Oct1 = (A bsl 2) bor (B bsr 4),
Oct2 = ((B band 16#f) bsl 4) bor (C bsr 2),
Oct3 = ((C band 2#11) bsl 6) bor D,
decode_base64_1(T, [Oct3, Oct2, Oct1 | Acc]);
decode_base64_1([], Acc) ->
lists:reverse(Acc).
%% Taken from httpd_util.erl
int_to_b64(X) when X >= 0, X =< 25 -> X + $A;
int_to_b64(X) when X >= 26, X =< 51 -> X - 26 + $a;
int_to_b64(X) when X >= 52, X =< 61 -> X - 52 + $0;
int_to_b64(62) -> $+;
int_to_b64(63) -> $/.
%% Taken from httpd_util.erl
b64_to_int(X) when X >= $A, X =< $Z -> X - $A;
b64_to_int(X) when X >= $a, X =< $z -> X - $a + 26;
b64_to_int(X) when X >= $0, X =< $9 -> X - $0 + 52;
b64_to_int($+) -> 62;
b64_to_int($/) -> 63.
base64:decode(Bin).
get_value(Tag, TVL, DefVal) ->
case lists:keysearch(Tag, 1, TVL) of

Loading…
取消
儲存