summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/couchdb.tpl.in2
-rw-r--r--src/mochiweb/Makefile.am2
-rw-r--r--src/mochiweb/mochiweb_html.erl4
-rw-r--r--src/mochiweb/mochiweb_request.erl37
-rw-r--r--src/mochiweb/mochiweb_socket_server.erl23
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], &lt;&lt;"Not found."&gt;&gt;})</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