summaryrefslogtreecommitdiff
path: root/src/mochiweb/mochiweb_request.erl
diff options
context:
space:
mode:
authorAdam Kocoloski <kocolosk@apache.org>2009-11-21 17:01:50 +0000
committerAdam Kocoloski <kocolosk@apache.org>2009-11-21 17:01:50 +0000
commit3a4fad07cb5097598eefd0cd7f588c5881a61c8f (patch)
tree6945d805eb72a37a5b27ae14a7ec2d1e8690fdac /src/mochiweb/mochiweb_request.erl
parenta2ebd6155b8171befd8f55b42c48bc563bb330b0 (diff)
upgrade mochiweb to r113, use hooks instead of forking mochijson2. COUCHDB-474
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@882941 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/mochiweb/mochiweb_request.erl')
-rw-r--r--src/mochiweb/mochiweb_request.erl119
1 files changed, 79 insertions, 40 deletions
diff --git a/src/mochiweb/mochiweb_request.erl b/src/mochiweb/mochiweb_request.erl
index e8f0a67c..fc296f40 100644
--- a/src/mochiweb/mochiweb_request.erl
+++ b/src/mochiweb/mochiweb_request.erl
@@ -190,8 +190,13 @@ stream_body(MaxChunkSize, ChunkFun, FunState) ->
stream_body(MaxChunkSize, ChunkFun, FunState, undefined).
stream_body(MaxChunkSize, ChunkFun, FunState, MaxBodyLength) ->
-
- case get_header_value("expect") of
+ Expect = case get_header_value("expect") of
+ undefined ->
+ undefined;
+ Value when is_list(Value) ->
+ string:to_lower(Value)
+ end,
+ case Expect of
"100-continue" ->
start_raw_response({100, gb_trees:empty()});
_Else ->
@@ -214,7 +219,7 @@ stream_body(MaxChunkSize, ChunkFun, FunState, MaxBodyLength) ->
MaxBodyLength when is_integer(MaxBodyLength), MaxBodyLength < Length ->
exit({body_too_large, content_length});
_ ->
- stream_unchunked_body(Length, MaxChunkSize, ChunkFun, FunState)
+ stream_unchunked_body(Length, ChunkFun, FunState)
end;
Length ->
exit({length_not_integer, Length})
@@ -449,13 +454,20 @@ stream_chunked_body(MaxChunkSize, Fun, FunState) ->
stream_chunked_body(MaxChunkSize, Fun, NewState)
end.
-stream_unchunked_body(0, _MaxChunkSize, Fun, FunState) ->
+stream_unchunked_body(0, Fun, FunState) ->
Fun({0, <<>>}, FunState);
-stream_unchunked_body(Length, _, Fun, FunState) when Length > 0 ->
+stream_unchunked_body(Length, Fun, FunState) when Length > 0 ->
Bin = recv(0),
- BinSize = size(Bin),
- NewState = Fun({BinSize, Bin}, FunState),
- stream_unchunked_body(Length - BinSize, 0, Fun, NewState).
+ BinSize = byte_size(Bin),
+ if BinSize > Length ->
+ <<OurBody:Length/binary, Extra/binary>> = Bin,
+ gen_tcp:unrecv(Socket, Extra),
+ NewState = Fun({Length, OurBody}, FunState),
+ stream_unchunked_body(0, Fun, NewState);
+ true ->
+ NewState = Fun({BinSize, Bin}, FunState),
+ stream_unchunked_body(Length - BinSize, Fun, NewState)
+ end.
%% @spec read_chunk_length() -> integer()
@@ -521,40 +533,69 @@ serve_file(Path, DocRoot, ExtraHeaders) ->
not_found(ExtraHeaders);
RelPath ->
FullPath = filename:join([DocRoot, RelPath]),
- File = case filelib:is_dir(FullPath) of
- true ->
- filename:join([FullPath, "index.html"]);
- false ->
- FullPath
- end,
- case file:read_file_info(File) of
- {ok, FileInfo} ->
- LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime),
- case get_header_value("if-modified-since") of
- LastModified ->
- respond({304, ExtraHeaders, ""});
- _ ->
- case file:open(File, [raw, binary]) of
- {ok, IoDevice} ->
- ContentType = mochiweb_util:guess_mime(File),
- Res = ok({ContentType,
- [{"last-modified", LastModified}
- | ExtraHeaders],
- {file, IoDevice}}),
- file:close(IoDevice),
- Res;
- _ ->
- not_found(ExtraHeaders)
- end
- end;
- {error, _} ->
- not_found(ExtraHeaders)
+ case filelib:is_dir(FullPath) of
+ true ->
+ maybe_redirect(RelPath, FullPath, ExtraHeaders);
+ false ->
+ maybe_serve_file(FullPath, ExtraHeaders)
end
end.
-
%% Internal API
+%% This has the same effect as the DirectoryIndex directive in httpd
+directory_index(FullPath) ->
+ filename:join([FullPath, "index.html"]).
+
+maybe_redirect([], FullPath, ExtraHeaders) ->
+ maybe_serve_file(directory_index(FullPath), ExtraHeaders);
+
+maybe_redirect(RelPath, FullPath, ExtraHeaders) ->
+ case string:right(RelPath, 1) of
+ "/" ->
+ maybe_serve_file(directory_index(FullPath), ExtraHeaders);
+ _ ->
+ Host = mochiweb_headers:get_value("host", Headers),
+ Location = "http://" ++ Host ++ "/" ++ RelPath ++ "/",
+ LocationBin = list_to_binary(Location),
+ MoreHeaders = [{"Location", Location},
+ {"Content-Type", "text/html"} | ExtraHeaders],
+ Top = <<"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
+ "<html><head>"
+ "<title>301 Moved Permanently</title>"
+ "</head><body>"
+ "<h1>Moved Permanently</h1>"
+ "<p>The document has moved <a href=\"">>,
+ Bottom = <<">here</a>.</p></body></html>\n">>,
+ Body = <<Top/binary, LocationBin/binary, Bottom/binary>>,
+ respond({301, MoreHeaders, Body})
+ end.
+
+maybe_serve_file(File, ExtraHeaders) ->
+ case file:read_file_info(File) of
+ {ok, FileInfo} ->
+ LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime),
+ case get_header_value("if-modified-since") of
+ LastModified ->
+ respond({304, ExtraHeaders, ""});
+ _ ->
+ case file:open(File, [raw, binary]) of
+ {ok, IoDevice} ->
+ ContentType = mochiweb_util:guess_mime(File),
+ Res = ok({ContentType,
+ [{"last-modified", LastModified}
+ | ExtraHeaders],
+ {file, IoDevice}}),
+ file:close(IoDevice),
+ Res;
+ _ ->
+ not_found(ExtraHeaders)
+ end
+ end;
+ {error, _} ->
+ not_found(ExtraHeaders)
+ end.
+
server_headers() ->
[{"Server", "MochiWeb/1.0 (" ++ ?QUIP ++ ")"},
{"Date", httpd_util:rfc1123_date()}].
@@ -639,7 +680,6 @@ range_parts({file, IoDevice}, Ranges) ->
end,
LocNums, Data),
{Bodies, Size};
-
range_parts(Body0, Ranges) ->
Body = iolist_to_binary(Body0),
Size = size(Body),
@@ -706,7 +746,6 @@ test_range() ->
[{none, 20}] = parse_range_request("bytes=-20"),
io:format(".. ok ~n"),
-
%% invalid, single ranges
io:format("Testing parse_range_request with invalid ranges~n"),
io:format("1"),
@@ -734,7 +773,7 @@ test_range() ->
io:format(".. ok~n"),
Body = <<"012345678901234567890123456789012345678901234567890123456789">>,
- BodySize = size(Body), %% 60
+ BodySize = byte_size(Body), %% 60
BodySize = 60,
%% these values assume BodySize =:= 60