http://git-wip-us.apache.org/repos/asf/couchdb/blob/49f12c82/src/mochiweb/mochiweb_response.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_response.erl b/src/mochiweb/mochiweb_response.erl index ab8ee61..c2a94d9 100644 --- a/src/mochiweb/mochiweb_response.erl +++ b/src/mochiweb/mochiweb_response.erl @@ -3,39 +3,47 @@ %% @doc Response abstraction. --module(mochiweb_response, [Request, Code, Headers]). +-module(mochiweb_response). -author('[email protected]'). -define(QUIP, "Any of you quaids got a smint?"). --export([get_header_value/1, get/1, dump/0]). --export([send/1, write_chunk/1]). +-export([new/3, get_header_value/2, get/2, dump/1]). +-export([send/2, write_chunk/2]). -%% @spec get_header_value(string() | atom() | binary()) -> string() | undefined +%% @type response() = {atom(), [Request, Code, Headers]} + +%% @spec new(Request, Code, Headers) -> response() +%% @doc Create a new mochiweb_response instance. +new(Request, Code, Headers) -> + {?MODULE, [Request, Code, Headers]}. + +%% @spec get_header_value(string() | atom() | binary(), response()) -> +%% string() | undefined %% @doc Get the value of the given response header. -get_header_value(K) -> +get_header_value(K, {?MODULE, [_Request, _Code, Headers]}) -> mochiweb_headers:get_value(K, Headers). -%% @spec get(request | code | headers) -> term() +%% @spec get(request | code | headers, response()) -> term() %% @doc Return the internal representation of the given field. -get(request) -> +get(request, {?MODULE, [Request, _Code, _Headers]}) -> Request; -get(code) -> +get(code, {?MODULE, [_Request, Code, _Headers]}) -> Code; -get(headers) -> +get(headers, {?MODULE, [_Request, _Code, Headers]}) -> Headers. -%% @spec dump() -> {mochiweb_request, [{atom(), term()}]} +%% @spec dump(response()) -> {mochiweb_request, [{atom(), term()}]} %% @doc Dump the internal representation to a "human readable" set of terms %% for debugging/inspection purposes. -dump() -> +dump({?MODULE, [Request, Code, Headers]}) -> [{request, Request:dump()}, {code, Code}, {headers, mochiweb_headers:to_list(Headers)}]. -%% @spec send(iodata()) -> ok +%% @spec send(iodata(), response()) -> ok %% @doc Send data over the socket if the method is not HEAD. -send(Data) -> +send(Data, {?MODULE, [Request, _Code, _Headers]}) -> case Request:get(method) of 'HEAD' -> ok; @@ -43,22 +51,22 @@ send(Data) -> Request:send(Data) end. -%% @spec write_chunk(iodata()) -> ok +%% @spec write_chunk(iodata(), response()) -> ok %% @doc Write a chunk of a HTTP chunked response. If Data is zero length, %% then the chunked response will be finished. -write_chunk(Data) -> +write_chunk(Data, {?MODULE, [Request, _Code, _Headers]}=THIS) -> case Request:get(version) of Version when Version >= {1, 1} -> Length = iolist_size(Data), - send([io_lib:format("~.16b\r\n", [Length]), Data, <<"\r\n">>]); + send([io_lib:format("~.16b\r\n", [Length]), Data, <<"\r\n">>], THIS); _ -> - send(Data) + send(Data, THIS) end. %% %% Tests %% --include_lib("eunit/include/eunit.hrl"). -ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). -endif.
http://git-wip-us.apache.org/repos/asf/couchdb/blob/49f12c82/src/mochiweb/mochiweb_socket.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_socket.erl b/src/mochiweb/mochiweb_socket.erl index ad27204..76b018c 100644 --- a/src/mochiweb/mochiweb_socket.erl +++ b/src/mochiweb/mochiweb_socket.erl @@ -4,11 +4,10 @@ -module(mochiweb_socket). --export([listen/4, accept/1, after_accept/1, recv/3, send/2, close/1, port/1, peername/1, +-export([listen/4, accept/1, recv/3, send/2, close/1, port/1, peername/1, setopts/2, type/1]). -define(ACCEPT_TIMEOUT, 2000). --define(SSL_ACCEPT_TIMEOUT, 30000). listen(Ssl, Port, Opts, SslOpts) -> case Ssl of @@ -26,9 +25,14 @@ listen(Ssl, Port, Opts, SslOpts) -> accept({ssl, ListenSocket}) -> % There's a bug in ssl:transport_accept/2 at the moment, which is the % reason for the try...catch block. Should be fixed in OTP R14. - try ssl:transport_accept(ListenSocket, ?ACCEPT_TIMEOUT) of + try ssl:transport_accept(ListenSocket) of {ok, Socket} -> - {ok, {ssl, Socket}}; + case ssl:ssl_accept(Socket) of + ok -> + {ok, {ssl, Socket}}; + {error, _} = Err -> + Err + end; {error, _} = Err -> Err catch @@ -38,9 +42,6 @@ accept({ssl, ListenSocket}) -> accept(ListenSocket) -> gen_tcp:accept(ListenSocket, ?ACCEPT_TIMEOUT). -after_accept({ssl, Socket}) -> ssl:ssl_accept(Socket, ?SSL_ACCEPT_TIMEOUT); -after_accept(_Socket) -> ok. - recv({ssl, Socket}, Length, Timeout) -> ssl:recv(Socket, Length, Timeout); recv(Socket, Length, Timeout) -> http://git-wip-us.apache.org/repos/asf/couchdb/blob/49f12c82/src/mochiweb/mochiweb_socket_server.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_socket_server.erl b/src/mochiweb/mochiweb_socket_server.erl index ff0d8f3..029f195 100644 --- a/src/mochiweb/mochiweb_socket_server.erl +++ b/src/mochiweb/mochiweb_socket_server.erl @@ -9,7 +9,7 @@ -include("internal.hrl"). --export([start/1, stop/1]). +-export([start/1, start_link/1, stop/1]). -export([init/1, handle_call/3, handle_cast/2, terminate/2, code_change/3, handle_info/2]). -export([get/2, set/3]). @@ -33,10 +33,22 @@ -define(is_old_state(State), not is_record(State, mochiweb_socket_server)). -start(State=#mochiweb_socket_server{}) -> - start_server(State); +start_link(Options) -> + start_server(start_link, parse_options(Options)). + start(Options) -> - start(parse_options(Options)). + case lists:keytake(link, 1, Options) of + {value, {_Key, false}, Options1} -> + start_server(start, parse_options(Options1)); + _ -> + %% TODO: https://github.com/mochi/mochiweb/issues/58 + %% [X] Phase 1: Add new APIs (Sep 2011) + %% [_] Phase 2: Add deprecation warning + %% [_] Phase 3: Change default to {link, false} and ignore link + %% [_] Phase 4: Add deprecation warning for {link, _} option + %% [_] Phase 5: Remove support for {link, _} option + start_link(Options) + end. get(Name, Property) -> gen_server:call(Name, {get, Property}). @@ -61,6 +73,8 @@ stop(Options) -> %% Internal API +parse_options(State=#mochiweb_socket_server{}) -> + State; parse_options(Options) -> parse_options(Options, #mochiweb_socket_server{}). @@ -116,22 +130,22 @@ parse_options([{profile_fun, ProfileFun} | Rest], State) when is_function(Profil parse_options(Rest, State#mochiweb_socket_server{profile_fun=ProfileFun}). -start_server(State=#mochiweb_socket_server{ssl=Ssl, name=Name}) -> - case Ssl of - true -> - application:start(crypto), - application:start(public_key), - application:start(ssl); - false -> - void - end, +start_server(F, State=#mochiweb_socket_server{ssl=Ssl, name=Name}) -> + ok = prep_ssl(Ssl), case Name of undefined -> - gen_server:start_link(?MODULE, State, []); + gen_server:F(?MODULE, State, []); _ -> - gen_server:start_link(Name, ?MODULE, State, []) + gen_server:F(Name, ?MODULE, State, []) end. +prep_ssl(true) -> + ok = mochiweb:ensure_started(crypto), + ok = mochiweb:ensure_started(public_key), + ok = mochiweb:ensure_started(ssl); +prep_ssl(false) -> + ok. + ensure_int(N) when is_integer(N) -> N; ensure_int(S) when is_list(S) -> @@ -165,27 +179,7 @@ init(State=#mochiweb_socket_server{ip=Ip, port=Port, backlog=Backlog, nodelay=No {_, _, _, _, _, _, _, _} -> % IPv6 [inet6, {ip, Ip} | BaseOpts] end, - case listen(Port, Opts, State) of - {stop, eacces} -> - case Port < 1024 of - true -> - case catch fdsrv:start() of - {ok, _} -> - case fdsrv:bind_socket(tcp, Port) of - {ok, Fd} -> - listen(Port, [{fd, Fd} | Opts], State); - _ -> - {stop, fdsrv_bind_failed} - end; - _ -> - {stop, fdsrv_start_failed} - end; - false -> - {stop, eacces} - end; - Other -> - Other - end. + listen(Port, Opts, State). new_acceptor_pool(Listen, State=#mochiweb_socket_server{acceptor_pool=Pool, @@ -271,15 +265,8 @@ handle_cast(stop, State) -> terminate(Reason, State) when ?is_old_state(State) -> terminate(Reason, upgrade_state(State)); -terminate(_Reason, #mochiweb_socket_server{listen=Listen, port=Port}) -> - mochiweb_socket:close(Listen), - case Port < 1024 of - true -> - catch fdsrv:stop(), - ok; - false -> - ok - end. +terminate(_Reason, #mochiweb_socket_server{listen=Listen}) -> + mochiweb_socket:close(Listen). code_change(_OldVsn, State, _Extra) -> State. @@ -337,8 +324,8 @@ handle_info(Info, State) -> %% %% Tests %% --include_lib("eunit/include/eunit.hrl"). -ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). upgrade_state_test() -> OldState = {mochiweb_socket_server, @@ -361,4 +348,3 @@ upgrade_state_test() -> ?assertEqual(CmpState, State). -endif. - http://git-wip-us.apache.org/repos/asf/couchdb/blob/49f12c82/src/mochiweb/mochiweb_util.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/mochiweb_util.erl b/src/mochiweb/mochiweb_util.erl index 6b88818..4d39990 100644 --- a/src/mochiweb/mochiweb_util.erl +++ b/src/mochiweb/mochiweb_util.erl @@ -9,7 +9,7 @@ -export([path_split/1]). -export([urlsplit/1, urlsplit_path/1, urlunsplit/1, urlunsplit_path/1]). -export([guess_mime/1, parse_header/1]). --export([shell_quote/1, cmd/1, cmd_string/1, cmd_port/2, cmd_status/1]). +-export([shell_quote/1, cmd/1, cmd_string/1, cmd_port/2, cmd_status/1, cmd_status/2]). -export([record_to_proplist/2, record_to_proplist/3]). -export([safe_relative_path/1, partition/2]). -export([parse_qvalues/1, pick_accepted_encodings/3]). @@ -124,11 +124,17 @@ cmd_string(Argv) -> string:join([shell_quote(X) || X <- Argv], " "). %% @spec cmd_status([string()]) -> {ExitStatus::integer(), Stdout::binary()} -%% @doc Accumulate the output and exit status from the given application, will be -%% spawned with cmd_port/2. +%% @doc Accumulate the output and exit status from the given application, +%% will be spawned with cmd_port/2. cmd_status(Argv) -> + cmd_status(Argv, []). + +%% @spec cmd_status([string()], [atom()]) -> {ExitStatus::integer(), Stdout::binary()} +%% @doc Accumulate the output and exit status from the given application, +%% will be spawned with cmd_port/2. +cmd_status(Argv, Options) -> Port = cmd_port(Argv, [exit_status, stderr_to_stdout, - use_stdio, binary]), + use_stdio, binary | Options]), try cmd_loop(Port, []) after catch port_close(Port) end. @@ -578,8 +584,8 @@ make_io(Io) when is_list(Io); is_binary(Io) -> %% %% Tests %% --include_lib("eunit/include/eunit.hrl"). -ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). make_io_test() -> ?assertEqual( http://git-wip-us.apache.org/repos/asf/couchdb/blob/49f12c82/src/mochiweb/reloader.erl ---------------------------------------------------------------------- diff --git a/src/mochiweb/reloader.erl b/src/mochiweb/reloader.erl index c0f5de8..8266b33 100644 --- a/src/mochiweb/reloader.erl +++ b/src/mochiweb/reloader.erl @@ -59,7 +59,7 @@ handle_cast(_Req, State) -> %% @doc gen_server callback. handle_info(doit, State) -> Now = stamp(), - doit(State#state.last, Now), + _ = doit(State#state.last, Now), {noreply, State#state{last = Now}}; handle_info(_Info, State) -> {noreply, State}. @@ -156,6 +156,6 @@ stamp() -> %% %% Tests %% --include_lib("eunit/include/eunit.hrl"). -ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). -endif.
