From 3a4fad07cb5097598eefd0cd7f588c5881a61c8f Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Sat, 21 Nov 2009 17:01:50 +0000 Subject: 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 --- src/mochiweb/mochiweb_request.erl | 119 +++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 40 deletions(-) (limited to 'src/mochiweb/mochiweb_request.erl') 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 -> + <> = 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 = <<"" + "" + "301 Moved Permanently" + "" + "

Moved Permanently

" + "

The document has moved >, + Bottom = <<">here.

\n">>, + Body = <>, + 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 -- cgit v1.2.3