mirror of
https://github.com/correl/urilib.git
synced 2024-11-25 11:09:57 +00:00
WIP commit
This commit is contained in:
parent
f16b0be421
commit
7b05c0c2b5
4 changed files with 192 additions and 13 deletions
2
Makefile
2
Makefile
|
@ -5,7 +5,7 @@ all: get-deps compile
|
|||
|
||||
build-plt:
|
||||
@dialyzer --build_plt --output_plt ~/.$(PROJECT).plt \
|
||||
--apps kernel stdlib erts
|
||||
--apps kernel stdlib erts inets edoc
|
||||
|
||||
clean:
|
||||
@( $(REBAR) clean )
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
{application, urilib, [
|
||||
{description, "RFC-3986 URI Library"},
|
||||
{vsn, "0.1.0"},
|
||||
{registered, []},
|
||||
{registered, [urilib]},
|
||||
{applications, [
|
||||
kernel,
|
||||
stdlib,
|
||||
inets,
|
||||
edoc
|
||||
]},
|
||||
{mod, {urilib, []}},
|
||||
|
|
132
src/urilib.erl
132
src/urilib.erl
|
@ -7,7 +7,6 @@
|
|||
-module(urilib).
|
||||
|
||||
-export([build/1,
|
||||
parse/1,
|
||||
parse_uri/1,
|
||||
parse_url/1,
|
||||
encode/1,
|
||||
|
@ -30,22 +29,60 @@
|
|||
%% @doc Returns a URI from the record passed in.
|
||||
%%
|
||||
%% @end
|
||||
build(_URL) ->
|
||||
ok.
|
||||
|
||||
|
||||
-spec parse(string()) -> #uri{}.
|
||||
parse(URL) -> parse_uri(URL).
|
||||
build(#uri{scheme=Scheme, userinfo=UserInfo, authority=Authority,
|
||||
path=Path, query=QArgs, fragment=Fragment}) ->
|
||||
U1 = url_add_scheme(Scheme),
|
||||
U2 = url_maybe_add_user(UserInfo, U1),
|
||||
U3 = url_add_host_and_port(Scheme,
|
||||
Authority#authority.host,
|
||||
Authority#authority.port, U2),
|
||||
U4 = url_add_path(Path, U3),
|
||||
U5 = url_maybe_add_qargs(QArgs, U4),
|
||||
url_maybe_add_fragment(Fragment, U5).
|
||||
|
||||
|
||||
-spec parse_uri(string()) -> #uri{}.
|
||||
parse_uri(_URL) ->
|
||||
ok.
|
||||
%% @spec parse_uri(URI) -> ParsedURI.
|
||||
%% where
|
||||
%% URI = string()
|
||||
%% ParsedURI = #uri{}
|
||||
%% @doc Parse a URI string returning the parsed data as a record
|
||||
%% @end
|
||||
parse_uri(URI) ->
|
||||
case http_uri:parse(URI, [{scheme_defaults, http_uri:scheme_defaults()}, {fragment, true}]) of
|
||||
{ok, {Scheme, UserInfo, Host, Port, Path, Query, Fragment}} ->
|
||||
#uri{scheme=Scheme,
|
||||
userinfo=parse_userinfo(UserInfo),
|
||||
authority=#authority{host=Host,
|
||||
port=Port},
|
||||
path=Path,
|
||||
query=parse_query(Query),
|
||||
fragment=Fragment};
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
|
||||
-spec parse_url(string()) -> #url{}.
|
||||
parse_url(_URL) ->
|
||||
ok.
|
||||
%% @spec parse_url(URL) -> ParsedURL.
|
||||
%% where
|
||||
%% URI = string()
|
||||
%% ParsedURL = #url{}
|
||||
%% @doc Parse a URL string returning the parsed data as a record
|
||||
%% @end
|
||||
parse_url(URL) ->
|
||||
case http_uri:parse(URL, [{scheme_defaults, http_uri:scheme_defaults()}, {fragment, true}]) of
|
||||
{ok, {Scheme, UserInfo, Host, Port, Path, Query, Fragment}} ->
|
||||
User = parse_userinfo(UserInfo),
|
||||
#url{scheme=Scheme,
|
||||
username=User#userinfo.username,
|
||||
password=User#userinfo.password,
|
||||
host=Host,
|
||||
port=Port,
|
||||
path=Path,
|
||||
query=parse_query(Query),
|
||||
fragment=Fragment};
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
|
||||
-spec encode(string()) -> string().
|
||||
|
@ -97,3 +134,76 @@ decode(Value) ->
|
|||
%% @end
|
||||
decode_plus(Value) ->
|
||||
string:join([http_uri:decode(V) || V <- string:tokens(Value, "+")], " ").
|
||||
|
||||
|
||||
-spec parse_query(string()) -> [].
|
||||
%% @private
|
||||
parse_query([]) -> [];
|
||||
parse_query(Query) ->
|
||||
case re:split(Query, "[&|?]", [{return, list}]) of
|
||||
[""] -> [];
|
||||
QArgs -> [split_query_arg(Arg) || Arg <- QArgs, Arg =/= []]
|
||||
end.
|
||||
|
||||
|
||||
-spec parse_userinfo(string()) -> #userinfo{}.
|
||||
%% @private
|
||||
parse_userinfo([]) -> #userinfo{};
|
||||
parse_userinfo(Value) ->
|
||||
case string:tokens(Value, ":") of
|
||||
[User, Password] -> #userinfo{username=User, password=Password};
|
||||
[User] -> #userinfo{username=User}
|
||||
end.
|
||||
|
||||
|
||||
-spec split_query_arg(string()) -> {string(), string()}.
|
||||
%% @private
|
||||
split_query_arg(Argument) ->
|
||||
[K, V] = string:tokens(Argument, "="),
|
||||
{K, V}.
|
||||
|
||||
|
||||
%% @private
|
||||
url_add_scheme(Scheme) ->
|
||||
string:concat(atom_to_list(Scheme), "://").
|
||||
|
||||
|
||||
%% @private
|
||||
url_maybe_add_user([], URL) -> URL;
|
||||
url_maybe_add_user(User, URL) ->
|
||||
string:concat(URL, string:concat(User, "@")).
|
||||
|
||||
|
||||
%% @private
|
||||
url_add_host_and_port(http, Host, 80, URL) ->
|
||||
string:concat(URL, Host);
|
||||
|
||||
|
||||
%% @private
|
||||
url_add_host_and_port(https, Host, 443, URL) ->
|
||||
string:concat(URL, Host);
|
||||
url_add_host_and_port(_, Host, Port, URL) ->
|
||||
string:concat(URL, string:join([Host, integer_to_list(Port)], ":")).
|
||||
|
||||
|
||||
%% @private
|
||||
url_add_path(Path, URL) ->
|
||||
Escaped = string:join([edoc_lib:escape_uri(P) || P <- string:tokens(Path, "/")], "/"),
|
||||
string:join([URL, Escaped], "/").
|
||||
|
||||
|
||||
%% @private
|
||||
url_maybe_add_qargs([], URL) -> URL;
|
||||
url_maybe_add_qargs(QArgs, URL) ->
|
||||
QStr = string:join([string:join([encode_plus(K), encode_plus(V)], "=") || {K,V} <- QArgs], "&"),
|
||||
string:join([URL, QStr], "?").
|
||||
|
||||
|
||||
%% @private
|
||||
url_maybe_add_fragment([], URL) -> URL;
|
||||
url_maybe_add_fragment(Value, URL) ->
|
||||
Fragment = case string:left(Value, 1) of
|
||||
"#" -> edoc_lib:escape_uri(string:sub_string(Value, 2));
|
||||
_ -> edoc_lib:escape_uri(Value)
|
||||
end,
|
||||
string:join([URL, Fragment], "#").
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
-include("urilib.hrl").
|
||||
|
||||
decode_test() ->
|
||||
Value = "foo%2fbar%20baz",
|
||||
|
@ -27,3 +28,70 @@ encode_plus1_test() ->
|
|||
Value = "foo/bar baz",
|
||||
Expect = "foo%2fbar+baz",
|
||||
?assertEqual(Expect, urilib:encode_plus(Value)).
|
||||
|
||||
parse_uri_variation1_test() ->
|
||||
URI = "amqp://guest:rabbitmq@rabbitmq:5672/%2f?heartbeat=5",
|
||||
Expect = #uri{scheme=amqp,
|
||||
userinfo=#userinfo{username="guest",
|
||||
password="rabbitmq"},
|
||||
authority=#authority{host="rabbitmq", port=5672},
|
||||
path="/%2f",
|
||||
query=[{"heartbeat", "5"}],
|
||||
fragment=[]},
|
||||
?assertEqual(Expect, urilib:parse_uri(URI)).
|
||||
|
||||
parse_uri_variation2_test() ->
|
||||
URI = "http://www.google.com/search?foo=bar#baz",
|
||||
Expect = #uri{scheme=http,
|
||||
userinfo=#userinfo{},
|
||||
authority=#authority{host="www.google.com", port=80},
|
||||
path="/search",
|
||||
query=[{"foo", "bar"}],
|
||||
fragment="#baz"},
|
||||
?assertEqual(Expect, urilib:parse_uri(URI)).
|
||||
|
||||
parse_uri_variation3_test() ->
|
||||
URI = "https://www.google.com/search",
|
||||
Expect = #uri{scheme=https,
|
||||
userinfo=#userinfo{},
|
||||
authority=#authority{host="www.google.com", port=443},
|
||||
path="/search",
|
||||
query=[],
|
||||
fragment=[]},
|
||||
?assertEqual(Expect, urilib:parse_uri(URI)).
|
||||
|
||||
parse_url_variation1_test() ->
|
||||
URL = "amqp://guest:rabbitmq@rabbitmq:5672/%2f?heartbeat=5",
|
||||
Expect = #url{scheme=amqp,
|
||||
username="guest",
|
||||
password="rabbitmq",
|
||||
host="rabbitmq",
|
||||
port=5672,
|
||||
path="/%2f",
|
||||
query=[{"heartbeat", "5"}],
|
||||
fragment=[]},
|
||||
?assertEqual(Expect, urilib:parse_url(URL)).
|
||||
|
||||
parse_url_variation2_test() ->
|
||||
URL = "http://www.google.com/search?foo=bar#baz",
|
||||
Expect = #url{scheme=http,
|
||||
username=undefined,
|
||||
password=undefined,
|
||||
host="www.google.com",
|
||||
port=80,
|
||||
path="/search",
|
||||
query=[{"foo", "bar"}],
|
||||
fragment="#baz"},
|
||||
?assertEqual(Expect, urilib:parse_url(URL)).
|
||||
|
||||
parse_url_variation3_test() ->
|
||||
URL = "https://www.google.com/search",
|
||||
Expect = #url{scheme=https,
|
||||
username=undefined,
|
||||
password=undefined,
|
||||
host="www.google.com",
|
||||
port=443,
|
||||
path="/search",
|
||||
query=[],
|
||||
fragment=[]},
|
||||
?assertEqual(Expect, urilib:parse_url(URL)).
|
||||
|
|
Loading…
Reference in a new issue