http://git-wip-us.apache.org/repos/asf/couchdb/blob/6fdb9e07/src/mochiweb/mochiweb.app.in ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb.app.in b/src/mochiweb/mochiweb.app.in deleted file mode 100644 index 6a4a314..0000000 --- a/src/mochiweb/mochiweb.app.in +++ /dev/null @@ -1,32 +0,0 @@ -{application, mochiweb, - [{description, "MochiMedia Web Server"}, - {vsn, "1.4.1"}, - {modules, [ - mochihex, - mochijson, - mochijson2, - mochinum, - mochiweb, - mochiweb_app, - mochiweb_charref, - mochiweb_cookies, - mochiweb_echo, - mochiweb_headers, - mochiweb_html, - mochiweb_http, - mochiweb_multipart, - mochiweb_request, - mochiweb_response, - mochiweb_skel, - mochiweb_socket_server, - mochiweb_sup, - mochiweb_util, - reloader, - mochifmt, - mochifmt_std, - mochifmt_records - ]}, - {registered, []}, - {mod, {mochiweb_app, []}}, - {env, []}, - {applications, [kernel, stdlib]}]}.
http://git-wip-us.apache.org/repos/asf/couchdb/blob/6fdb9e07/src/mochiweb/mochiweb.app.src ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb.app.src b/src/mochiweb/mochiweb.app.src deleted file mode 100644 index 37a21fb..0000000 --- a/src/mochiweb/mochiweb.app.src +++ /dev/null @@ -1,9 +0,0 @@ -%% This is generated from src/mochiweb.app.src -{application, mochiweb, - [{description, "MochiMedia Web Server"}, - {vsn, "1.4.1"}, - {modules, []}, - {registered, []}, - {mod, {mochiweb_app, []}}, - {env, []}, - {applications, [kernel, stdlib, crypto, inets]}]}. http://git-wip-us.apache.org/repos/asf/couchdb/blob/6fdb9e07/src/mochiweb/mochiweb.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb.erl b/src/mochiweb/mochiweb.erl deleted file mode 100644 index 3118028..0000000 --- a/src/mochiweb/mochiweb.erl +++ /dev/null @@ -1,289 +0,0 @@ -%% @author Bob Ippolito <[email protected]> -%% @copyright 2007 Mochi Media, Inc. - -%% @doc Start and stop the MochiWeb server. - --module(mochiweb). --author('[email protected]'). - --export([start/0, stop/0]). --export([new_request/1, new_response/1]). --export([all_loaded/0, all_loaded/1, reload/0]). - -%% @spec start() -> ok -%% @doc Start the MochiWeb server. -start() -> - ensure_started(crypto), - application:start(mochiweb). - -%% @spec stop() -> ok -%% @doc Stop the MochiWeb server. -stop() -> - Res = application:stop(mochiweb), - application:stop(crypto), - Res. - -reload() -> - [c:l(Module) || Module <- all_loaded()]. - -all_loaded() -> - all_loaded(filename:dirname(code:which(?MODULE))). - -all_loaded(Base) when is_atom(Base) -> - []; -all_loaded(Base) -> - FullBase = Base ++ "/", - F = fun ({_Module, Loaded}, Acc) when is_atom(Loaded) -> - Acc; - ({Module, Loaded}, Acc) -> - case lists:prefix(FullBase, Loaded) of - true -> - [Module | Acc]; - false -> - Acc - end - end, - lists:foldl(F, [], code:all_loaded()). - - -%% @spec new_request({Socket, Request, Headers}) -> MochiWebRequest -%% @doc Return a mochiweb_request data structure. -new_request({Socket, {Method, {abs_path, Uri}, Version}, Headers}) -> - mochiweb_request:new(Socket, - Method, - Uri, - Version, - mochiweb_headers:make(Headers)); -% this case probably doesn't "exist". -new_request({Socket, {Method, {absoluteURI, _Protocol, _Host, _Port, Uri}, - Version}, Headers}) -> - mochiweb_request:new(Socket, - Method, - Uri, - Version, - mochiweb_headers:make(Headers)); -%% Request-URI is "*" -%% From http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 -new_request({Socket, {Method, '*'=Uri, Version}, Headers}) -> - mochiweb_request:new(Socket, - Method, - Uri, - Version, - mochiweb_headers:make(Headers)). - -%% @spec new_response({Request, integer(), Headers}) -> MochiWebResponse -%% @doc Return a mochiweb_response data structure. -new_response({Request, Code, Headers}) -> - mochiweb_response:new(Request, - Code, - mochiweb_headers:make(Headers)). - -%% Internal API - -ensure_started(App) -> - case application:start(App) of - ok -> - ok; - {error, {already_started, App}} -> - ok - end. - - -%% -%% Tests -%% --include_lib("eunit/include/eunit.hrl"). --ifdef(TEST). - --record(treq, {path, body= <<>>, xreply= <<>>}). - -ssl_cert_opts() -> - EbinDir = filename:dirname(code:which(?MODULE)), - CertDir = filename:join([EbinDir, "..", "support", "test-materials"]), - CertFile = filename:join(CertDir, "test_ssl_cert.pem"), - KeyFile = filename:join(CertDir, "test_ssl_key.pem"), - [{certfile, CertFile}, {keyfile, KeyFile}]. - -with_server(Transport, ServerFun, ClientFun) -> - ServerOpts0 = [{ip, "127.0.0.1"}, {port, 0}, {loop, ServerFun}], - ServerOpts = case Transport of - plain -> - ServerOpts0; - ssl -> - ServerOpts0 ++ [{ssl, true}, {ssl_opts, ssl_cert_opts()}] - end, - {ok, Server} = mochiweb_http:start(ServerOpts), - Port = mochiweb_socket_server:get(Server, port), - Res = (catch ClientFun(Transport, Port)), - mochiweb_http:stop(Server), - Res. - -request_test() -> - R = mochiweb_request:new(z, z, "/foo/bar/baz%20wibble+quux?qs=2", z, []), - "/foo/bar/baz wibble quux" = R:get(path), - ok. - -single_http_GET_test() -> - do_GET(plain, 1). - -single_https_GET_test() -> - do_GET(ssl, 1). - -multiple_http_GET_test() -> - do_GET(plain, 3). - -multiple_https_GET_test() -> - do_GET(ssl, 3). - -hundred_http_GET_test() -> - do_GET(plain, 100). - -hundred_https_GET_test() -> - do_GET(ssl, 100). - -single_128_http_POST_test() -> - do_POST(plain, 128, 1). - -single_128_https_POST_test() -> - do_POST(ssl, 128, 1). - -single_2k_http_POST_test() -> - do_POST(plain, 2048, 1). - -single_2k_https_POST_test() -> - do_POST(ssl, 2048, 1). - -single_100k_http_POST_test() -> - do_POST(plain, 102400, 1). - -single_100k_https_POST_test() -> - do_POST(ssl, 102400, 1). - -multiple_100k_http_POST_test() -> - do_POST(plain, 102400, 3). - -multiple_100K_https_POST_test() -> - do_POST(ssl, 102400, 3). - -hundred_128_http_POST_test() -> - do_POST(plain, 128, 100). - -hundred_128_https_POST_test() -> - do_POST(ssl, 128, 100). - -do_GET(Transport, Times) -> - PathPrefix = "/whatever/", - ReplyPrefix = "You requested: ", - ServerFun = fun (Req) -> - Reply = ReplyPrefix ++ Req:get(path), - Req:ok({"text/plain", Reply}) - end, - TestReqs = [begin - Path = PathPrefix ++ integer_to_list(N), - ExpectedReply = list_to_binary(ReplyPrefix ++ Path), - #treq{path=Path, xreply=ExpectedReply} - end || N <- lists:seq(1, Times)], - ClientFun = new_client_fun('GET', TestReqs), - ok = with_server(Transport, ServerFun, ClientFun), - ok. - -do_POST(Transport, Size, Times) -> - ServerFun = fun (Req) -> - Body = Req:recv_body(), - Headers = [{"Content-Type", "application/octet-stream"}], - Req:respond({201, Headers, Body}) - end, - TestReqs = [begin - Path = "/stuff/" ++ integer_to_list(N), - Body = crypto:rand_bytes(Size), - #treq{path=Path, body=Body, xreply=Body} - end || N <- lists:seq(1, Times)], - ClientFun = new_client_fun('POST', TestReqs), - ok = with_server(Transport, ServerFun, ClientFun), - ok. - -new_client_fun(Method, TestReqs) -> - fun (Transport, Port) -> - client_request(Transport, Port, Method, TestReqs) - end. - -client_request(Transport, Port, Method, TestReqs) -> - Opts = [binary, {active, false}, {packet, http}], - SockFun = case Transport of - plain -> - {ok, Socket} = gen_tcp:connect("127.0.0.1", Port, Opts), - fun (recv) -> - gen_tcp:recv(Socket, 0); - ({recv, Length}) -> - gen_tcp:recv(Socket, Length); - ({send, Data}) -> - gen_tcp:send(Socket, Data); - ({setopts, L}) -> - inet:setopts(Socket, L) - end; - ssl -> - {ok, Socket} = ssl:connect("127.0.0.1", Port, [{ssl_imp, new} | Opts]), - fun (recv) -> - ssl:recv(Socket, 0); - ({recv, Length}) -> - ssl:recv(Socket, Length); - ({send, Data}) -> - ssl:send(Socket, Data); - ({setopts, L}) -> - ssl:setopts(Socket, L) - end - end, - client_request(SockFun, Method, TestReqs). - -client_request(SockFun, _Method, []) -> - {the_end, {error, closed}} = {the_end, SockFun(recv)}, - ok; -client_request(SockFun, Method, - [#treq{path=Path, body=Body, xreply=ExReply} | Rest]) -> - Request = [atom_to_list(Method), " ", Path, " HTTP/1.1\r\n", - client_headers(Body, Rest =:= []), - "\r\n", - Body], - ok = SockFun({send, Request}), - case Method of - 'GET' -> - {ok, {http_response, {1,1}, 200, "OK"}} = SockFun(recv); - 'POST' -> - {ok, {http_response, {1,1}, 201, "Created"}} = SockFun(recv) - end, - ok = SockFun({setopts, [{packet, httph}]}), - {ok, {http_header, _, 'Server', _, "MochiWeb" ++ _}} = SockFun(recv), - {ok, {http_header, _, 'Date', _, _}} = SockFun(recv), - {ok, {http_header, _, 'Content-Type', _, _}} = SockFun(recv), - {ok, {http_header, _, 'Content-Length', _, ConLenStr}} = SockFun(recv), - ContentLength = list_to_integer(ConLenStr), - {ok, http_eoh} = SockFun(recv), - ok = SockFun({setopts, [{packet, raw}]}), - {payload, ExReply} = {payload, drain_reply(SockFun, ContentLength, <<>>)}, - ok = SockFun({setopts, [{packet, http}]}), - client_request(SockFun, Method, Rest). - -client_headers(Body, IsLastRequest) -> - ["Host: localhost\r\n", - case Body of - <<>> -> - ""; - _ -> - ["Content-Type: application/octet-stream\r\n", - "Content-Length: ", integer_to_list(byte_size(Body)), "\r\n"] - end, - case IsLastRequest of - true -> - "Connection: close\r\n"; - false -> - "" - end]. - -drain_reply(_SockFun, 0, Acc) -> - Acc; -drain_reply(SockFun, Length, Acc) -> - Sz = erlang:min(Length, 1024), - {ok, B} = SockFun({recv, Sz}), - drain_reply(SockFun, Length - Sz, <<Acc/bytes, B/bytes>>). - --endif. http://git-wip-us.apache.org/repos/asf/couchdb/blob/6fdb9e07/src/mochiweb/mochiweb_acceptor.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_acceptor.erl b/src/mochiweb/mochiweb_acceptor.erl deleted file mode 100644 index 893f99b..0000000 --- a/src/mochiweb/mochiweb_acceptor.erl +++ /dev/null @@ -1,49 +0,0 @@ -%% @author Bob Ippolito <[email protected]> -%% @copyright 2010 Mochi Media, Inc. - -%% @doc MochiWeb acceptor. - --module(mochiweb_acceptor). --author('[email protected]'). - --include("internal.hrl"). - --export([start_link/3, init/3]). - -start_link(Server, Listen, Loop) -> - proc_lib:spawn_link(?MODULE, init, [Server, Listen, Loop]). - -init(Server, Listen, Loop) -> - T1 = now(), - case catch mochiweb_socket:accept(Listen) of - {ok, Socket} -> - gen_server:cast(Server, {accepted, self(), timer:now_diff(now(), T1)}), - case mochiweb_socket:after_accept(Socket) of - ok -> call_loop(Loop, Socket); - {error, _} -> exit(normal) - end; - {error, closed} -> - exit(normal); - {error, timeout} -> - init(Server, Listen, Loop); - Other -> - error_logger:error_report( - [{application, mochiweb}, - "Accept failed error", - lists:flatten(io_lib:format("~p", [Other]))]), - exit({error, accept_failed}) - end. - -call_loop({M, F}, Socket) -> - M:F(Socket); -call_loop({M, F, A}, Socket) -> - erlang:apply(M, F, [Socket | A]); -call_loop(Loop, Socket) -> - Loop(Socket). - -%% -%% Tests -%% --include_lib("eunit/include/eunit.hrl"). --ifdef(TEST). --endif. http://git-wip-us.apache.org/repos/asf/couchdb/blob/6fdb9e07/src/mochiweb/mochiweb_app.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_app.erl b/src/mochiweb/mochiweb_app.erl deleted file mode 100644 index 5d67787..0000000 --- a/src/mochiweb/mochiweb_app.erl +++ /dev/null @@ -1,27 +0,0 @@ -%% @author Bob Ippolito <[email protected]> -%% @copyright 2007 Mochi Media, Inc. - -%% @doc Callbacks for the mochiweb application. - --module(mochiweb_app). --author('[email protected]'). - --behaviour(application). --export([start/2,stop/1]). - -%% @spec start(_Type, _StartArgs) -> ServerRet -%% @doc application start callback for mochiweb. -start(_Type, _StartArgs) -> - mochiweb_sup:start_link(). - -%% @spec stop(_State) -> ServerRet -%% @doc application stop callback for mochiweb. -stop(_State) -> - ok. - -%% -%% Tests -%% --include_lib("eunit/include/eunit.hrl"). --ifdef(TEST). --endif. http://git-wip-us.apache.org/repos/asf/couchdb/blob/6fdb9e07/src/mochiweb/mochiweb_charref.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_charref.erl b/src/mochiweb/mochiweb_charref.erl deleted file mode 100644 index 99cd550..0000000 --- a/src/mochiweb/mochiweb_charref.erl +++ /dev/null @@ -1,308 +0,0 @@ -%% @author Bob Ippolito <[email protected]> -%% @copyright 2007 Mochi Media, Inc. - -%% @doc Converts HTML 4 charrefs and entities to codepoints. --module(mochiweb_charref). --export([charref/1]). - -%% External API. - -%% @spec charref(S) -> integer() | undefined -%% @doc Convert a decimal charref, hex charref, or html entity to a unicode -%% codepoint, or return undefined on failure. -%% The input should not include an ampersand or semicolon. -%% charref("#38") = 38, charref("#x26") = 38, charref("amp") = 38. -charref(B) when is_binary(B) -> - charref(binary_to_list(B)); -charref([$#, C | L]) when C =:= $x orelse C =:= $X -> - try erlang:list_to_integer(L, 16) - catch - error:badarg -> undefined - end; -charref([$# | L]) -> - try list_to_integer(L) - catch - error:badarg -> undefined - end; -charref(L) -> - entity(L). - -%% Internal API. - -entity("nbsp") -> 160; -entity("iexcl") -> 161; -entity("cent") -> 162; -entity("pound") -> 163; -entity("curren") -> 164; -entity("yen") -> 165; -entity("brvbar") -> 166; -entity("sect") -> 167; -entity("uml") -> 168; -entity("copy") -> 169; -entity("ordf") -> 170; -entity("laquo") -> 171; -entity("not") -> 172; -entity("shy") -> 173; -entity("reg") -> 174; -entity("macr") -> 175; -entity("deg") -> 176; -entity("plusmn") -> 177; -entity("sup2") -> 178; -entity("sup3") -> 179; -entity("acute") -> 180; -entity("micro") -> 181; -entity("para") -> 182; -entity("middot") -> 183; -entity("cedil") -> 184; -entity("sup1") -> 185; -entity("ordm") -> 186; -entity("raquo") -> 187; -entity("frac14") -> 188; -entity("frac12") -> 189; -entity("frac34") -> 190; -entity("iquest") -> 191; -entity("Agrave") -> 192; -entity("Aacute") -> 193; -entity("Acirc") -> 194; -entity("Atilde") -> 195; -entity("Auml") -> 196; -entity("Aring") -> 197; -entity("AElig") -> 198; -entity("Ccedil") -> 199; -entity("Egrave") -> 200; -entity("Eacute") -> 201; -entity("Ecirc") -> 202; -entity("Euml") -> 203; -entity("Igrave") -> 204; -entity("Iacute") -> 205; -entity("Icirc") -> 206; -entity("Iuml") -> 207; -entity("ETH") -> 208; -entity("Ntilde") -> 209; -entity("Ograve") -> 210; -entity("Oacute") -> 211; -entity("Ocirc") -> 212; -entity("Otilde") -> 213; -entity("Ouml") -> 214; -entity("times") -> 215; -entity("Oslash") -> 216; -entity("Ugrave") -> 217; -entity("Uacute") -> 218; -entity("Ucirc") -> 219; -entity("Uuml") -> 220; -entity("Yacute") -> 221; -entity("THORN") -> 222; -entity("szlig") -> 223; -entity("agrave") -> 224; -entity("aacute") -> 225; -entity("acirc") -> 226; -entity("atilde") -> 227; -entity("auml") -> 228; -entity("aring") -> 229; -entity("aelig") -> 230; -entity("ccedil") -> 231; -entity("egrave") -> 232; -entity("eacute") -> 233; -entity("ecirc") -> 234; -entity("euml") -> 235; -entity("igrave") -> 236; -entity("iacute") -> 237; -entity("icirc") -> 238; -entity("iuml") -> 239; -entity("eth") -> 240; -entity("ntilde") -> 241; -entity("ograve") -> 242; -entity("oacute") -> 243; -entity("ocirc") -> 244; -entity("otilde") -> 245; -entity("ouml") -> 246; -entity("divide") -> 247; -entity("oslash") -> 248; -entity("ugrave") -> 249; -entity("uacute") -> 250; -entity("ucirc") -> 251; -entity("uuml") -> 252; -entity("yacute") -> 253; -entity("thorn") -> 254; -entity("yuml") -> 255; -entity("fnof") -> 402; -entity("Alpha") -> 913; -entity("Beta") -> 914; -entity("Gamma") -> 915; -entity("Delta") -> 916; -entity("Epsilon") -> 917; -entity("Zeta") -> 918; -entity("Eta") -> 919; -entity("Theta") -> 920; -entity("Iota") -> 921; -entity("Kappa") -> 922; -entity("Lambda") -> 923; -entity("Mu") -> 924; -entity("Nu") -> 925; -entity("Xi") -> 926; -entity("Omicron") -> 927; -entity("Pi") -> 928; -entity("Rho") -> 929; -entity("Sigma") -> 931; -entity("Tau") -> 932; -entity("Upsilon") -> 933; -entity("Phi") -> 934; -entity("Chi") -> 935; -entity("Psi") -> 936; -entity("Omega") -> 937; -entity("alpha") -> 945; -entity("beta") -> 946; -entity("gamma") -> 947; -entity("delta") -> 948; -entity("epsilon") -> 949; -entity("zeta") -> 950; -entity("eta") -> 951; -entity("theta") -> 952; -entity("iota") -> 953; -entity("kappa") -> 954; -entity("lambda") -> 955; -entity("mu") -> 956; -entity("nu") -> 957; -entity("xi") -> 958; -entity("omicron") -> 959; -entity("pi") -> 960; -entity("rho") -> 961; -entity("sigmaf") -> 962; -entity("sigma") -> 963; -entity("tau") -> 964; -entity("upsilon") -> 965; -entity("phi") -> 966; -entity("chi") -> 967; -entity("psi") -> 968; -entity("omega") -> 969; -entity("thetasym") -> 977; -entity("upsih") -> 978; -entity("piv") -> 982; -entity("bull") -> 8226; -entity("hellip") -> 8230; -entity("prime") -> 8242; -entity("Prime") -> 8243; -entity("oline") -> 8254; -entity("frasl") -> 8260; -entity("weierp") -> 8472; -entity("image") -> 8465; -entity("real") -> 8476; -entity("trade") -> 8482; -entity("alefsym") -> 8501; -entity("larr") -> 8592; -entity("uarr") -> 8593; -entity("rarr") -> 8594; -entity("darr") -> 8595; -entity("harr") -> 8596; -entity("crarr") -> 8629; -entity("lArr") -> 8656; -entity("uArr") -> 8657; -entity("rArr") -> 8658; -entity("dArr") -> 8659; -entity("hArr") -> 8660; -entity("forall") -> 8704; -entity("part") -> 8706; -entity("exist") -> 8707; -entity("empty") -> 8709; -entity("nabla") -> 8711; -entity("isin") -> 8712; -entity("notin") -> 8713; -entity("ni") -> 8715; -entity("prod") -> 8719; -entity("sum") -> 8721; -entity("minus") -> 8722; -entity("lowast") -> 8727; -entity("radic") -> 8730; -entity("prop") -> 8733; -entity("infin") -> 8734; -entity("ang") -> 8736; -entity("and") -> 8743; -entity("or") -> 8744; -entity("cap") -> 8745; -entity("cup") -> 8746; -entity("int") -> 8747; -entity("there4") -> 8756; -entity("sim") -> 8764; -entity("cong") -> 8773; -entity("asymp") -> 8776; -entity("ne") -> 8800; -entity("equiv") -> 8801; -entity("le") -> 8804; -entity("ge") -> 8805; -entity("sub") -> 8834; -entity("sup") -> 8835; -entity("nsub") -> 8836; -entity("sube") -> 8838; -entity("supe") -> 8839; -entity("oplus") -> 8853; -entity("otimes") -> 8855; -entity("perp") -> 8869; -entity("sdot") -> 8901; -entity("lceil") -> 8968; -entity("rceil") -> 8969; -entity("lfloor") -> 8970; -entity("rfloor") -> 8971; -entity("lang") -> 9001; -entity("rang") -> 9002; -entity("loz") -> 9674; -entity("spades") -> 9824; -entity("clubs") -> 9827; -entity("hearts") -> 9829; -entity("diams") -> 9830; -entity("quot") -> 34; -entity("amp") -> 38; -entity("lt") -> 60; -entity("gt") -> 62; -entity("OElig") -> 338; -entity("oelig") -> 339; -entity("Scaron") -> 352; -entity("scaron") -> 353; -entity("Yuml") -> 376; -entity("circ") -> 710; -entity("tilde") -> 732; -entity("ensp") -> 8194; -entity("emsp") -> 8195; -entity("thinsp") -> 8201; -entity("zwnj") -> 8204; -entity("zwj") -> 8205; -entity("lrm") -> 8206; -entity("rlm") -> 8207; -entity("ndash") -> 8211; -entity("mdash") -> 8212; -entity("lsquo") -> 8216; -entity("rsquo") -> 8217; -entity("sbquo") -> 8218; -entity("ldquo") -> 8220; -entity("rdquo") -> 8221; -entity("bdquo") -> 8222; -entity("dagger") -> 8224; -entity("Dagger") -> 8225; -entity("permil") -> 8240; -entity("lsaquo") -> 8249; -entity("rsaquo") -> 8250; -entity("euro") -> 8364; -entity(_) -> undefined. - - -%% -%% Tests -%% --include_lib("eunit/include/eunit.hrl"). --ifdef(TEST). - -exhaustive_entity_test() -> - T = mochiweb_cover:clause_lookup_table(?MODULE, entity), - [?assertEqual(V, entity(K)) || {K, V} <- T]. - -charref_test() -> - 1234 = charref("#1234"), - 255 = charref("#xfF"), - 255 = charref(<<"#XFf">>), - 38 = charref("amp"), - 38 = charref(<<"amp">>), - undefined = charref("not_an_entity"), - undefined = charref("#not_an_entity"), - undefined = charref("#xnot_an_entity"), - ok. - --endif. http://git-wip-us.apache.org/repos/asf/couchdb/blob/6fdb9e07/src/mochiweb/mochiweb_cookies.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_cookies.erl b/src/mochiweb/mochiweb_cookies.erl deleted file mode 100644 index ee91d0c..0000000 --- a/src/mochiweb/mochiweb_cookies.erl +++ /dev/null @@ -1,309 +0,0 @@ -%% @author Emad El-Haraty <[email protected]> -%% @copyright 2007 Mochi Media, Inc. - -%% @doc HTTP Cookie parsing and generating (RFC 2109, RFC 2965). - --module(mochiweb_cookies). --export([parse_cookie/1, cookie/3, cookie/2]). - --define(QUOTE, $\"). - --define(IS_WHITESPACE(C), - (C =:= $\s orelse C =:= $\t orelse C =:= $\r orelse C =:= $\n)). - -%% RFC 2616 separators (called tspecials in RFC 2068) --define(IS_SEPARATOR(C), - (C < 32 orelse - C =:= $\s orelse C =:= $\t orelse - C =:= $( orelse C =:= $) orelse C =:= $< orelse C =:= $> orelse - C =:= $@ orelse C =:= $, orelse C =:= $; orelse C =:= $: orelse - C =:= $\\ orelse C =:= $\" orelse C =:= $/ orelse - C =:= $[ orelse C =:= $] orelse C =:= $? orelse C =:= $= orelse - C =:= ${ orelse C =:= $})). - -%% @type proplist() = [{Key::string(), Value::string()}]. -%% @type header() = {Name::string(), Value::string()}. - -%% @spec cookie(Key::string(), Value::string()) -> header() -%% @doc Short-hand for <code>cookie(Key, Value, [])</code>. -cookie(Key, Value) -> - cookie(Key, Value, []). - -%% @spec cookie(Key::string(), Value::string(), Options::[Option]) -> header() -%% where Option = {max_age, integer()} | {local_time, {date(), time()}} -%% | {domain, string()} | {path, string()} -%% | {secure, true | false} | {http_only, true | false} -%% -%% @doc Generate a Set-Cookie header field tuple. -cookie(Key, Value, Options) -> - Cookie = [any_to_list(Key), "=", quote(Value), "; Version=1"], - %% Set-Cookie: - %% Comment, Domain, Max-Age, Path, Secure, Version - %% Set-Cookie2: - %% Comment, CommentURL, Discard, Domain, Max-Age, Path, Port, Secure, - %% Version - ExpiresPart = - case proplists:get_value(max_age, Options) of - undefined -> - ""; - RawAge -> - When = case proplists:get_value(local_time, Options) of - undefined -> - calendar:universal_time(); - LocalTime -> - erlang:localtime_to_universaltime(LocalTime) - end, - Age = case RawAge < 0 of - true -> - 0; - false -> - RawAge - end, - ["; Expires=", age_to_cookie_date(Age, When), - "; Max-Age=", quote(Age)] - end, - SecurePart = - case proplists:get_value(secure, Options) of - true -> - "; Secure"; - _ -> - "" - end, - DomainPart = - case proplists:get_value(domain, Options) of - undefined -> - ""; - Domain -> - ["; Domain=", quote(Domain)] - end, - PathPart = - case proplists:get_value(path, Options) of - undefined -> - ""; - Path -> - ["; Path=", quote(Path)] - end, - HttpOnlyPart = - case proplists:get_value(http_only, Options) of - true -> - "; HttpOnly"; - _ -> - "" - end, - CookieParts = [Cookie, ExpiresPart, SecurePart, DomainPart, PathPart, HttpOnlyPart], - {"Set-Cookie", lists:flatten(CookieParts)}. - - -%% Every major browser incorrectly handles quoted strings in a -%% different and (worse) incompatible manner. Instead of wasting time -%% writing redundant code for each browser, we restrict cookies to -%% only contain characters that browsers handle compatibly. -%% -%% By replacing the definition of quote with this, we generate -%% RFC-compliant cookies: -%% -%% quote(V) -> -%% Fun = fun(?QUOTE, Acc) -> [$\\, ?QUOTE | Acc]; -%% (Ch, Acc) -> [Ch | Acc] -%% end, -%% [?QUOTE | lists:foldr(Fun, [?QUOTE], V)]. - -%% Convert to a string and raise an error if quoting is required. -quote(V0) -> - V = any_to_list(V0), - lists:all(fun(Ch) -> Ch =:= $/ orelse not ?IS_SEPARATOR(Ch) end, V) - orelse erlang:error({cookie_quoting_required, V}), - V. - -add_seconds(Secs, UniversalTime) -> - Greg = calendar:datetime_to_gregorian_seconds(UniversalTime), - calendar:gregorian_seconds_to_datetime(Greg + Secs). - -age_to_cookie_date(Age, UniversalTime) -> - couch_util:rfc1123_date(add_seconds(Age, UniversalTime)). - -%% @spec parse_cookie(string()) -> [{K::string(), V::string()}] -%% @doc Parse the contents of a Cookie header field, ignoring cookie -%% attributes, and return a simple property list. -parse_cookie("") -> - []; -parse_cookie(Cookie) -> - parse_cookie(Cookie, []). - -%% Internal API - -parse_cookie([], Acc) -> - lists:reverse(Acc); -parse_cookie(String, Acc) -> - {{Token, Value}, Rest} = read_pair(String), - Acc1 = case Token of - "" -> - Acc; - "$" ++ _ -> - Acc; - _ -> - [{Token, Value} | Acc] - end, - parse_cookie(Rest, Acc1). - -read_pair(String) -> - {Token, Rest} = read_token(skip_whitespace(String)), - {Value, Rest1} = read_value(skip_whitespace(Rest)), - {{Token, Value}, skip_past_separator(Rest1)}. - -read_value([$= | Value]) -> - Value1 = skip_whitespace(Value), - case Value1 of - [?QUOTE | _] -> - read_quoted(Value1); - _ -> - read_token(Value1) - end; -read_value(String) -> - {"", String}. - -read_quoted([?QUOTE | String]) -> - read_quoted(String, []). - -read_quoted([], Acc) -> - {lists:reverse(Acc), []}; -read_quoted([?QUOTE | Rest], Acc) -> - {lists:reverse(Acc), Rest}; -read_quoted([$\\, Any | Rest], Acc) -> - read_quoted(Rest, [Any | Acc]); -read_quoted([C | Rest], Acc) -> - read_quoted(Rest, [C | Acc]). - -skip_whitespace(String) -> - F = fun (C) -> ?IS_WHITESPACE(C) end, - lists:dropwhile(F, String). - -read_token(String) -> - F = fun (C) -> not ?IS_SEPARATOR(C) end, - lists:splitwith(F, String). - -skip_past_separator([]) -> - []; -skip_past_separator([$; | Rest]) -> - Rest; -skip_past_separator([$, | Rest]) -> - Rest; -skip_past_separator([_ | Rest]) -> - skip_past_separator(Rest). - -any_to_list(V) when is_list(V) -> - V; -any_to_list(V) when is_atom(V) -> - atom_to_list(V); -any_to_list(V) when is_binary(V) -> - binary_to_list(V); -any_to_list(V) when is_integer(V) -> - integer_to_list(V). - -%% -%% Tests -%% --include_lib("eunit/include/eunit.hrl"). --ifdef(TEST). - -quote_test() -> - %% ?assertError eunit macro is not compatible with coverage module - try quote(":wq") - catch error:{cookie_quoting_required, ":wq"} -> ok - end, - ?assertEqual( - "foo", - quote(foo)), - ok. - -parse_cookie_test() -> - %% RFC example - C1 = "$Version=\"1\"; Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"; - Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"; - Shipping=\"FedEx\"; $Path=\"/acme\"", - ?assertEqual( - [{"Customer","WILE_E_COYOTE"}, - {"Part_Number","Rocket_Launcher_0001"}, - {"Shipping","FedEx"}], - parse_cookie(C1)), - %% Potential edge cases - ?assertEqual( - [{"foo", "x"}], - parse_cookie("foo=\"\\x\"")), - ?assertEqual( - [], - parse_cookie("=")), - ?assertEqual( - [{"foo", ""}, {"bar", ""}], - parse_cookie(" foo ; bar ")), - ?assertEqual( - [{"foo", ""}, {"bar", ""}], - parse_cookie("foo=;bar=")), - ?assertEqual( - [{"foo", "\";"}, {"bar", ""}], - parse_cookie("foo = \"\\\";\";bar ")), - ?assertEqual( - [{"foo", "\";bar"}], - parse_cookie("foo=\"\\\";bar")), - ?assertEqual( - [], - parse_cookie([])), - ?assertEqual( - [{"foo", "bar"}, {"baz", "wibble"}], - parse_cookie("foo=bar , baz=wibble ")), - ok. - -domain_test() -> - ?assertEqual( - {"Set-Cookie", - "Customer=WILE_E_COYOTE; " - "Version=1; " - "Domain=acme.com; " - "HttpOnly"}, - cookie("Customer", "WILE_E_COYOTE", - [{http_only, true}, {domain, "acme.com"}])), - ok. - -local_time_test() -> - {"Set-Cookie", S} = cookie("Customer", "WILE_E_COYOTE", - [{max_age, 111}, {secure, true}]), - ?assertMatch( - ["Customer=WILE_E_COYOTE", - " Version=1", - " Expires=" ++ _, - " Max-Age=111", - " Secure"], - string:tokens(S, ";")), - ok. - -cookie_test() -> - C1 = {"Set-Cookie", - "Customer=WILE_E_COYOTE; " - "Version=1; " - "Path=/acme"}, - C1 = cookie("Customer", "WILE_E_COYOTE", [{path, "/acme"}]), - C1 = cookie("Customer", "WILE_E_COYOTE", - [{path, "/acme"}, {badoption, "negatory"}]), - C1 = cookie('Customer', 'WILE_E_COYOTE', [{path, '/acme'}]), - C1 = cookie(<<"Customer">>, <<"WILE_E_COYOTE">>, [{path, <<"/acme">>}]), - - {"Set-Cookie","=NoKey; Version=1"} = cookie("", "NoKey", []), - {"Set-Cookie","=NoKey; Version=1"} = cookie("", "NoKey"), - LocalTime = calendar:universal_time_to_local_time({{2007, 5, 15}, {13, 45, 33}}), - C2 = {"Set-Cookie", - "Customer=WILE_E_COYOTE; " - "Version=1; " - "Expires=Tue, 15 May 2007 13:45:33 GMT; " - "Max-Age=0"}, - C2 = cookie("Customer", "WILE_E_COYOTE", - [{max_age, -111}, {local_time, LocalTime}]), - C3 = {"Set-Cookie", - "Customer=WILE_E_COYOTE; " - "Version=1; " - "Expires=Wed, 16 May 2007 13:45:50 GMT; " - "Max-Age=86417"}, - C3 = cookie("Customer", "WILE_E_COYOTE", - [{max_age, 86417}, {local_time, LocalTime}]), - ok. - --endif. http://git-wip-us.apache.org/repos/asf/couchdb/blob/6fdb9e07/src/mochiweb/mochiweb_cover.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_cover.erl b/src/mochiweb/mochiweb_cover.erl deleted file mode 100644 index 6a14ef5..0000000 --- a/src/mochiweb/mochiweb_cover.erl +++ /dev/null @@ -1,75 +0,0 @@ -%% @author Bob Ippolito <[email protected]> -%% @copyright 2010 Mochi Media, Inc. - -%% @doc Workarounds for various cover deficiencies. --module(mochiweb_cover). --export([get_beam/1, get_abstract_code/1, - get_clauses/2, clause_lookup_table/1]). --export([clause_lookup_table/2]). - -%% Internal - -get_beam(Module) -> - {Module, Beam, _Path} = code:get_object_code(Module), - Beam. - -get_abstract_code(Beam) -> - {ok, {_Module, - [{abstract_code, - {raw_abstract_v1, L}}]}} = beam_lib:chunks(Beam, [abstract_code]), - L. - -get_clauses(Function, Code) -> - [L] = [Clauses || {function, _, FName, _, Clauses} - <- Code, FName =:= Function], - L. - -clause_lookup_table(Module, Function) -> - clause_lookup_table( - get_clauses(Function, - get_abstract_code(get_beam(Module)))). - -clause_lookup_table(Clauses) -> - lists:foldr(fun clause_fold/2, [], Clauses). - -clause_fold({clause, _, - [InTerm], - _Guards=[], - [OutTerm]}, - Acc) -> - try [{erl_parse:normalise(InTerm), erl_parse:normalise(OutTerm)} | Acc] - catch error:_ -> Acc - end; -clause_fold(_, Acc) -> - Acc. - -%% -%% Tests -%% --include_lib("eunit/include/eunit.hrl"). --ifdef(TEST). -foo_table(a) -> b; -foo_table("a") -> <<"b">>; -foo_table(123) -> {4, 3, 2}; -foo_table([list]) -> []; -foo_table([list1, list2]) -> [list1, list2, list3]; -foo_table(ignored) -> some, code, ignored; -foo_table(Var) -> Var. - -foo_table_test() -> - T = clause_lookup_table(?MODULE, foo_table), - [?assertEqual(V, foo_table(K)) || {K, V} <- T]. - -clause_lookup_table_test() -> - ?assertEqual(b, foo_table(a)), - ?assertEqual(ignored, foo_table(ignored)), - ?assertEqual('Var', foo_table('Var')), - ?assertEqual( - [{a, b}, - {"a", <<"b">>}, - {123, {4, 3, 2}}, - {[list], []}, - {[list1, list2], [list1, list2, list3]}], - clause_lookup_table(?MODULE, foo_table)). - --endif. http://git-wip-us.apache.org/repos/asf/couchdb/blob/6fdb9e07/src/mochiweb/mochiweb_echo.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_echo.erl b/src/mochiweb/mochiweb_echo.erl deleted file mode 100644 index 6f7872b..0000000 --- a/src/mochiweb/mochiweb_echo.erl +++ /dev/null @@ -1,38 +0,0 @@ -%% @author Bob Ippolito <[email protected]> -%% @copyright 2007 Mochi Media, Inc. - -%% @doc Simple and stupid echo server to demo mochiweb_socket_server. - --module(mochiweb_echo). --author('[email protected]'). --export([start/0, stop/0, loop/1]). - -stop() -> - mochiweb_socket_server:stop(?MODULE). - -start() -> - mochiweb_socket_server:start([{name, ?MODULE}, - {port, 6789}, - {ip, "127.0.0.1"}, - {max, 1}, - {loop, {?MODULE, loop}}]). - -loop(Socket) -> - case mochiweb_socket:recv(Socket, 0, 30000) of - {ok, Data} -> - case mochiweb_socket:send(Socket, Data) of - ok -> - loop(Socket); - _ -> - exit(normal) - end; - _Other -> - exit(normal) - end. - -%% -%% Tests -%% --include_lib("eunit/include/eunit.hrl"). --ifdef(TEST). --endif. http://git-wip-us.apache.org/repos/asf/couchdb/blob/6fdb9e07/src/mochiweb/mochiweb_headers.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_headers.erl b/src/mochiweb/mochiweb_headers.erl deleted file mode 100644 index 4fce983..0000000 --- a/src/mochiweb/mochiweb_headers.erl +++ /dev/null @@ -1,299 +0,0 @@ -%% @author Bob Ippolito <[email protected]> -%% @copyright 2007 Mochi Media, Inc. - -%% @doc Case preserving (but case insensitive) HTTP Header dictionary. - --module(mochiweb_headers). --author('[email protected]'). --export([empty/0, from_list/1, insert/3, enter/3, get_value/2, lookup/2]). --export([delete_any/2, get_primary_value/2]). --export([default/3, enter_from_list/2, default_from_list/2]). --export([to_list/1, make/1]). --export([from_binary/1]). - -%% @type headers(). -%% @type key() = atom() | binary() | string(). -%% @type value() = atom() | binary() | string() | integer(). - -%% @spec empty() -> headers() -%% @doc Create an empty headers structure. -empty() -> - gb_trees:empty(). - -%% @spec make(headers() | [{key(), value()}]) -> headers() -%% @doc Construct a headers() from the given list. -make(L) when is_list(L) -> - from_list(L); -%% assume a tuple is already mochiweb_headers. -make(T) when is_tuple(T) -> - T. - -%% @spec from_binary(iolist()) -> headers() -%% @doc Transforms a raw HTTP header into a mochiweb headers structure. -%% -%% The given raw HTTP header can be one of the following: -%% -%% 1) A string or a binary representing a full HTTP header ending with -%% double CRLF. -%% Examples: -%% ``` -%% "Content-Length: 47\r\nContent-Type: text/plain\r\n\r\n" -%% <<"Content-Length: 47\r\nContent-Type: text/plain\r\n\r\n">>''' -%% -%% 2) A list of binaries or strings where each element represents a raw -%% HTTP header line ending with a single CRLF. -%% Examples: -%% ``` -%% [<<"Content-Length: 47\r\n">>, <<"Content-Type: text/plain\r\n">>] -%% ["Content-Length: 47\r\n", "Content-Type: text/plain\r\n"] -%% ["Content-Length: 47\r\n", <<"Content-Type: text/plain\r\n">>]''' -%% -from_binary(RawHttpHeader) when is_binary(RawHttpHeader) -> - from_binary(RawHttpHeader, []); -from_binary(RawHttpHeaderList) -> - from_binary(list_to_binary([RawHttpHeaderList, "\r\n"])). - -from_binary(RawHttpHeader, Acc) -> - case erlang:decode_packet(httph, RawHttpHeader, []) of - {ok, {http_header, _, H, _, V}, Rest} -> - from_binary(Rest, [{H, V} | Acc]); - _ -> - make(Acc) - end. - -%% @spec from_list([{key(), value()}]) -> headers() -%% @doc Construct a headers() from the given list. -from_list(List) -> - lists:foldl(fun ({K, V}, T) -> insert(K, V, T) end, empty(), List). - -%% @spec enter_from_list([{key(), value()}], headers()) -> headers() -%% @doc Insert pairs into the headers, replace any values for existing keys. -enter_from_list(List, T) -> - lists:foldl(fun ({K, V}, T1) -> enter(K, V, T1) end, T, List). - -%% @spec default_from_list([{key(), value()}], headers()) -> headers() -%% @doc Insert pairs into the headers for keys that do not already exist. -default_from_list(List, T) -> - lists:foldl(fun ({K, V}, T1) -> default(K, V, T1) end, T, List). - -%% @spec to_list(headers()) -> [{key(), string()}] -%% @doc Return the contents of the headers. The keys will be the exact key -%% that was first inserted (e.g. may be an atom or binary, case is -%% preserved). -to_list(T) -> - F = fun ({K, {array, L}}, Acc) -> - L1 = lists:reverse(L), - lists:foldl(fun (V, Acc1) -> [{K, V} | Acc1] end, Acc, L1); - (Pair, Acc) -> - [Pair | Acc] - end, - lists:reverse(lists:foldl(F, [], gb_trees:values(T))). - -%% @spec get_value(key(), headers()) -> string() | undefined -%% @doc Return the value of the given header using a case insensitive search. -%% undefined will be returned for keys that are not present. -get_value(K, T) -> - case lookup(K, T) of - {value, {_, V}} -> - expand(V); - none -> - undefined - end. - -%% @spec get_primary_value(key(), headers()) -> string() | undefined -%% @doc Return the value of the given header up to the first semicolon using -%% a case insensitive search. undefined will be returned for keys -%% that are not present. -get_primary_value(K, T) -> - case get_value(K, T) of - undefined -> - undefined; - V -> - lists:takewhile(fun (C) -> C =/= $; end, V) - end. - -%% @spec lookup(key(), headers()) -> {value, {key(), string()}} | none -%% @doc Return the case preserved key and value for the given header using -%% a case insensitive search. none will be returned for keys that are -%% not present. -lookup(K, T) -> - case gb_trees:lookup(normalize(K), T) of - {value, {K0, V}} -> - {value, {K0, expand(V)}}; - none -> - none - end. - -%% @spec default(key(), value(), headers()) -> headers() -%% @doc Insert the pair into the headers if it does not already exist. -default(K, V, T) -> - K1 = normalize(K), - V1 = any_to_list(V), - try gb_trees:insert(K1, {K, V1}, T) - catch - error:{key_exists, _} -> - T - end. - -%% @spec enter(key(), value(), headers()) -> headers() -%% @doc Insert the pair into the headers, replacing any pre-existing key. -enter(K, V, T) -> - K1 = normalize(K), - V1 = any_to_list(V), - gb_trees:enter(K1, {K, V1}, T). - -%% @spec insert(key(), value(), headers()) -> headers() -%% @doc Insert the pair into the headers, merging with any pre-existing key. -%% A merge is done with Value = V0 ++ ", " ++ V1. -insert(K, V, T) -> - K1 = normalize(K), - V1 = any_to_list(V), - try gb_trees:insert(K1, {K, V1}, T) - catch - error:{key_exists, _} -> - {K0, V0} = gb_trees:get(K1, T), - V2 = merge(K1, V1, V0), - gb_trees:update(K1, {K0, V2}, T) - end. - -%% @spec delete_any(key(), headers()) -> headers() -%% @doc Delete the header corresponding to key if it is present. -delete_any(K, T) -> - K1 = normalize(K), - gb_trees:delete_any(K1, T). - -%% Internal API - -expand({array, L}) -> - mochiweb_util:join(lists:reverse(L), ", "); -expand(V) -> - V. - -merge("set-cookie", V1, {array, L}) -> - {array, [V1 | L]}; -merge("set-cookie", V1, V0) -> - {array, [V1, V0]}; -merge(_, V1, V0) -> - V0 ++ ", " ++ V1. - -normalize(K) when is_list(K) -> - string:to_lower(K); -normalize(K) when is_atom(K) -> - normalize(atom_to_list(K)); -normalize(K) when is_binary(K) -> - normalize(binary_to_list(K)). - -any_to_list(V) when is_list(V) -> - V; -any_to_list(V) when is_atom(V) -> - atom_to_list(V); -any_to_list(V) when is_binary(V) -> - binary_to_list(V); -any_to_list(V) when is_integer(V) -> - integer_to_list(V). - -%% -%% Tests. -%% --include_lib("eunit/include/eunit.hrl"). --ifdef(TEST). - -make_test() -> - Identity = make([{hdr, foo}]), - ?assertEqual( - Identity, - make(Identity)). - -enter_from_list_test() -> - H = make([{hdr, foo}]), - ?assertEqual( - [{baz, "wibble"}, {hdr, "foo"}], - to_list(enter_from_list([{baz, wibble}], H))), - ?assertEqual( - [{hdr, "bar"}], - to_list(enter_from_list([{hdr, bar}], H))), - ok. - -default_from_list_test() -> - H = make([{hdr, foo}]), - ?assertEqual( - [{baz, "wibble"}, {hdr, "foo"}], - to_list(default_from_list([{baz, wibble}], H))), - ?assertEqual( - [{hdr, "foo"}], - to_list(default_from_list([{hdr, bar}], H))), - ok. - -get_primary_value_test() -> - H = make([{hdr, foo}, {baz, <<"wibble;taco">>}]), - ?assertEqual( - "foo", - get_primary_value(hdr, H)), - ?assertEqual( - undefined, - get_primary_value(bar, H)), - ?assertEqual( - "wibble", - get_primary_value(<<"baz">>, H)), - ok. - -set_cookie_test() -> - H = make([{"set-cookie", foo}, {"set-cookie", bar}, {"set-cookie", baz}]), - ?assertEqual( - [{"set-cookie", "foo"}, {"set-cookie", "bar"}, {"set-cookie", "baz"}], - to_list(H)), - ok. - -headers_test() -> - H = ?MODULE:make([{hdr, foo}, {"Hdr", "bar"}, {'Hdr', 2}]), - [{hdr, "foo, bar, 2"}] = ?MODULE:to_list(H), - H1 = ?MODULE:insert(taco, grande, H), - [{hdr, "foo, bar, 2"}, {taco, "grande"}] = ?MODULE:to_list(H1), - H2 = ?MODULE:make([{"Set-Cookie", "foo"}]), - [{"Set-Cookie", "foo"}] = ?MODULE:to_list(H2), - H3 = ?MODULE:insert("Set-Cookie", "bar", H2), - [{"Set-Cookie", "foo"}, {"Set-Cookie", "bar"}] = ?MODULE:to_list(H3), - "foo, bar" = ?MODULE:get_value("set-cookie", H3), - {value, {"Set-Cookie", "foo, bar"}} = ?MODULE:lookup("set-cookie", H3), - undefined = ?MODULE:get_value("shibby", H3), - none = ?MODULE:lookup("shibby", H3), - H4 = ?MODULE:insert("content-type", - "application/x-www-form-urlencoded; charset=utf8", - H3), - "application/x-www-form-urlencoded" = ?MODULE:get_primary_value( - "content-type", H4), - H4 = ?MODULE:delete_any("nonexistent-header", H4), - H3 = ?MODULE:delete_any("content-type", H4), - HB = <<"Content-Length: 47\r\nContent-Type: text/plain\r\n\r\n">>, - H_HB = ?MODULE:from_binary(HB), - H_HB = ?MODULE:from_binary(binary_to_list(HB)), - "47" = ?MODULE:get_value("Content-Length", H_HB), - "text/plain" = ?MODULE:get_value("Content-Type", H_HB), - L_H_HB = ?MODULE:to_list(H_HB), - 2 = length(L_H_HB), - true = lists:member({'Content-Length', "47"}, L_H_HB), - true = lists:member({'Content-Type', "text/plain"}, L_H_HB), - HL = [ <<"Content-Length: 47\r\n">>, <<"Content-Type: text/plain\r\n">> ], - HL2 = [ "Content-Length: 47\r\n", <<"Content-Type: text/plain\r\n">> ], - HL3 = [ <<"Content-Length: 47\r\n">>, "Content-Type: text/plain\r\n" ], - H_HL = ?MODULE:from_binary(HL), - H_HL = ?MODULE:from_binary(HL2), - H_HL = ?MODULE:from_binary(HL3), - "47" = ?MODULE:get_value("Content-Length", H_HL), - "text/plain" = ?MODULE:get_value("Content-Type", H_HL), - L_H_HL = ?MODULE:to_list(H_HL), - 2 = length(L_H_HL), - true = lists:member({'Content-Length', "47"}, L_H_HL), - true = lists:member({'Content-Type', "text/plain"}, L_H_HL), - [] = ?MODULE:to_list(?MODULE:from_binary(<<>>)), - [] = ?MODULE:to_list(?MODULE:from_binary(<<"">>)), - [] = ?MODULE:to_list(?MODULE:from_binary(<<"\r\n">>)), - [] = ?MODULE:to_list(?MODULE:from_binary(<<"\r\n\r\n">>)), - [] = ?MODULE:to_list(?MODULE:from_binary("")), - [] = ?MODULE:to_list(?MODULE:from_binary([<<>>])), - [] = ?MODULE:to_list(?MODULE:from_binary([<<"">>])), - [] = ?MODULE:to_list(?MODULE:from_binary([<<"\r\n">>])), - [] = ?MODULE:to_list(?MODULE:from_binary([<<"\r\n\r\n">>])), - ok. - --endif.
