diff options
-rw-r--r-- | bin/couchdb.tpl.in | 2 | ||||
-rw-r--r-- | src/mochiweb/Makefile.am | 2 | ||||
-rw-r--r-- | src/mochiweb/mochiweb_html.erl | 4 | ||||
-rw-r--r-- | src/mochiweb/mochiweb_request.erl | 37 | ||||
-rw-r--r-- | src/mochiweb/mochiweb_socket_server.erl | 23 |
5 files changed, 49 insertions, 19 deletions
diff --git a/bin/couchdb.tpl.in b/bin/couchdb.tpl.in index 77409ae0..d7d689a4 100644 --- a/bin/couchdb.tpl.in +++ b/bin/couchdb.tpl.in @@ -206,7 +206,7 @@ start_couchdb () { command="`%ICU_CONFIG% --invoke` \ %ERL% $interactive_option -smp auto -sasl errlog_type error \ -pa %localerlanglibdir%/couch-%version%/ebin \ - %localerlanglibdir%/mochiweb-r76/ebin \ + %localerlanglibdir%/mochiweb-r82/ebin \ -eval \"application:load(inets)\" \ -eval \"application:load(crypto)\" \ -eval \"application:load(couch)\" \ diff --git a/src/mochiweb/Makefile.am b/src/mochiweb/Makefile.am index 85109423..b7fbf18b 100644 --- a/src/mochiweb/Makefile.am +++ b/src/mochiweb/Makefile.am @@ -10,7 +10,7 @@ ## License for the specific language governing permissions and limitations under ## the License. -mochiwebebindir = $(localerlanglibdir)/mochiweb-r76/ebin +mochiwebebindir = $(localerlanglibdir)/mochiweb-r82/ebin mochiweb_file_collection = \ mochifmt.erl \ diff --git a/src/mochiweb/mochiweb_html.erl b/src/mochiweb/mochiweb_html.erl index 39ce51e6..59181686 100644 --- a/src/mochiweb/mochiweb_html.erl +++ b/src/mochiweb/mochiweb_html.erl @@ -101,7 +101,7 @@ to_html(Node) when is_tuple(Node) -> to_html(Tokens) when is_list(Tokens) -> to_html(Tokens, []). -%% @spec escape(string() | binary()) -> string() +%% @spec escape(string() | atom() | binary()) -> binary() %% @doc Escape a string such that it's safe for HTML (amp; lt; gt;). escape(B) when is_binary(B) -> escape(binary_to_list(B), []); @@ -110,7 +110,7 @@ escape(A) when is_atom(A) -> escape(S) when is_list(S) -> escape(S, []). -%% @spec escape_attr(S::string()) -> string() +%% @spec escape_attr(string() | binary() | atom() | integer() | float()) -> binary() %% @doc Escape a string such that it's safe for HTML attrs %% (amp; lt; gt; quot;). escape_attr(B) when is_binary(B) -> diff --git a/src/mochiweb/mochiweb_request.erl b/src/mochiweb/mochiweb_request.erl index ec41338e..311ed507 100644 --- a/src/mochiweb/mochiweb_request.erl +++ b/src/mochiweb/mochiweb_request.erl @@ -15,11 +15,11 @@ -export([send/1, recv/1, recv/2, recv_body/0, recv_body/1]). -export([start_response/1, start_response_length/1, start_raw_response/1]). -export([respond/1, ok/1]). --export([not_found/0]). +-export([not_found/0, not_found/1]). -export([parse_post/0, parse_qs/0]). -export([should_close/0, cleanup/0]). -export([parse_cookie/0, get_cookie_value/1]). --export([serve_file/2]). +-export([serve_file/2, serve_file/3]). -export([test/0]). -define(SAVE_QS, mochiweb_request_qs). @@ -276,9 +276,16 @@ respond({Code, ResponseHeaders, Body}) -> Response. %% @spec not_found() -> response() -%% @doc respond({404, [{"Content-Type", "text/plain"}], "Not found."}). +%% @doc Alias for <code>not_found([])</code>. not_found() -> - respond({404, [{"Content-Type", "text/plain"}], <<"Not found.">>}). + not_found([]). + +%% @spec not_found(ExtraHeaders) -> response() +%% @doc Alias for <code>respond({404, [{"Content-Type", "text/plain"} +%% | ExtraHeaders], <<"Not found.">>})</code>. +not_found(ExtraHeaders) -> + respond({404, [{"Content-Type", "text/plain"} | ExtraHeaders], + <<"Not found.">>}). %% @spec ok({value(), iodata()} | {value(), ioheaders(), iodata() | {file, IoDevice}}) -> %% response() @@ -326,7 +333,9 @@ should_close() -> %% unread data left on the socket, can't safely continue orelse (DidNotRecv andalso get_header_value("content-length") =/= undefined - andalso list_to_integer(get_header_value("content-length")) > 0). + andalso list_to_integer(get_header_value("content-length")) > 0) + orelse (DidNotRecv + andalso get_header_value("transfer-encoding") =:= "chunked"). %% @spec cleanup() -> ok %% @doc Clean up any junk in the process dictionary, required before continuing @@ -455,9 +464,14 @@ read_chunk(Length) -> %% @spec serve_file(Path, DocRoot) -> Response %% @doc Serve a file relative to DocRoot. serve_file(Path, DocRoot) -> + serve_file(Path, DocRoot, []). + +%% @spec serve_file(Path, DocRoot, ExtraHeaders) -> Response +%% @doc Serve a file relative to DocRoot. +serve_file(Path, DocRoot, ExtraHeaders) -> case mochiweb_util:safe_relative_path(Path) of undefined -> - not_found(); + not_found(ExtraHeaders); RelPath -> FullPath = filename:join([DocRoot, RelPath]), File = case filelib:is_dir(FullPath) of @@ -471,20 +485,23 @@ serve_file(Path, DocRoot) -> LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime), case get_header_value("if-modified-since") of LastModified -> - respond({304, [], ""}); + respond({304, ExtraHeaders, ""}); _ -> case file:open(File, [raw, binary]) of {ok, IoDevice} -> ContentType = mochiweb_util:guess_mime(File), - Res = ok({ContentType, [{"last-modified", LastModified}], {file, IoDevice}}), + Res = ok({ContentType, + [{"last-modified", LastModified} + | ExtraHeaders], + {file, IoDevice}}), file:close(IoDevice), Res; _ -> - not_found() + not_found(ExtraHeaders) end end; {error, _} -> - not_found() + not_found(ExtraHeaders) end end. diff --git a/src/mochiweb/mochiweb_socket_server.erl b/src/mochiweb/mochiweb_socket_server.erl index 0d538ac9..d4853dad 100644 --- a/src/mochiweb/mochiweb_socket_server.erl +++ b/src/mochiweb/mochiweb_socket_server.erl @@ -96,6 +96,14 @@ start_server(State=#mochiweb_socket_server{name=Name}) -> gen_server:start_link(Name, ?MODULE, State, []) end. +ipv6_supported() -> + case (catch inet:getaddr("localhost", inet6)) of + {ok, _Addr} -> + true; + {error, _} -> + false + end. + init(State=#mochiweb_socket_server{ip=Ip, port=Port, backlog=Backlog}) -> process_flag(trap_exit, true), BaseOpts = [binary, @@ -106,11 +114,16 @@ init(State=#mochiweb_socket_server{ip=Ip, port=Port, backlog=Backlog}) -> {active, false}, {nodelay, true}], Opts = case Ip of - any -> - BaseOpts; - Ip -> - [{ip, Ip} | BaseOpts] - end, + any -> + case ipv6_supported() of % IPv4, and IPv6 if supported + true -> [inet, inet6 | BaseOpts]; + _ -> BaseOpts + end; + {_, _, _, _} -> % IPv4 + [inet, {ip, Ip} | BaseOpts]; + {_, _, _, _, _, _, _, _} -> % IPv6 + [inet6, {ip, Ip} | BaseOpts] + end, case gen_tcp_listen(Port, Opts, State) of {stop, eacces} -> case Port < 1024 of |