Permalink
Browse files

Merge remote-tracking branch 'origin/from-boss'

  • Loading branch information...
choptastic committed May 30, 2012
2 parents 52da9c7 + 4aa2102 commit 736a094a42964e91ae1c5b2c377f556f5572015f
@@ -5,15 +5,11 @@
init/1,
request_method/1, path/1, uri/1,
peer_ip/1, peer_port/1,
- headers/1, cookies/1,
- query_params/1, post_params/1, request_body/1
+ headers/1, header/2, cookies/1,
+ query_params/1, post_params/1, request_body/1,
+ socket/1, recv_from_socket/3
]).
-
-%% @todo could not figure out how to get the socket from misultin
-%% so could not implement socket/1, recv_from_socket/3 that are
-%% present in other request modules
-
init(Req) ->
Req.
@@ -28,36 +24,70 @@ uri(Req) ->
Req:get(uri).
peer_ip(Req) ->
- Req:get(peer_addr).
+ case Req:get(peer_addr) of
+ {ok, IP} -> IP;
+ IP -> IP
+ end.
peer_port(Req) ->
Req:get(peer_port).
+header(connection, Req) ->
+ misultin_utility:get_key_value('Connection', Req:get(headers));
+header(accept, Req) ->
+ misultin_utility:get_key_value('Accept', Req:get(headers));
+header(host, Req) ->
+ misultin_utility:get_key_value('Host', Req:get(headers));
+header(if_modified_since, Req) ->
+ misultin_utility:get_key_value('If-Modified-Since', Req:get(headers));
+header(if_match, Req) ->
+ misultin_utility:get_key_value('If-Match', Req:get(headers));
+header(if_none_match, Req) ->
+ misultin_utility:get_key_value('If-None-Match', Req:get(headers));
+header(if_range, Req) ->
+ misultin_utility:get_key_value('If-Range', Req:get(headers));
+header(if_unmodified_since, Req) ->
+ misultin_utility:get_key_value('If-Unmodified-Since', Req:get(headers));
+header(range, Req) ->
+ misultin_utility:get_key_value('Range', Req:get(headers));
+header(referer, Req) ->
+ misultin_utility:get_key_value('Referer', Req:get(headers));
+header(user_agent, Req) ->
+ misultin_utility:get_key_value('User-Agent', Req:get(headers));
+header(accept_ranges, Req) ->
+ misultin_utility:get_key_value('Accept-Ranges', Req:get(headers));
+header(cookie, Req) ->
+ misultin_utility:get_key_value('Cookie', Req:get(headers));
+header(keep_alive, Req) ->
+ misultin_utility:get_key_value('Keep-Alive', Req:get(headers));
+header(location, Req) ->
+ misultin_utility:get_key_value('Location', Req:get(headers));
+header(content_length, Req) ->
+ misultin_utility:get_key_value('Content-Length', Req:get(headers));
+header(content_type, Req) ->
+ misultin_utility:get_key_value('Content-Type', Req:get(headers));
+header(content_encoding, Req) ->
+ misultin_utility:get_key_value('Content-Encoding', Req:get(headers));
+header(authorization, Req) ->
+ misultin_utility:get_key_value('Authorization', Req:get(headers));
+header(x_forwarded_for, Req) ->
+ misultin_utility:get_key_value('X-Forwarded-For', Req:get(headers));
+header(transfer_encoding, Req) ->
+ misultin_utility:get_key_value('Transfer-Encoding', Req:get(headers));
+header(accept_language, Req) ->
+ misultin_utility:get_key_value('Accept-Language', Req:get(headers));
+header(Header, Req) ->
+ misultin_utility:get_key_value(Header, Req:get(headers)).
+
headers(Req) ->
- Headers = Req:get(headers),
- F = fun(Header) -> proplists:get_value(Header, Headers) end,
- Headers1 = [
- {connection, F('Connection')},
- {accept, F('Accept')},
- {host, F('Host')},
- {if_modified_since, F('If-Modified-Since')},
- {if_match, F('If-Match')},
- {if_none_match, F('If-Range')},
- {if_unmodified_since, F('If-Unmodified-Since')},
- {range, F('Range')},
- {referer, F('Referer')},
- {user_agent, F('User-Agent')},
- {accept_ranges, F('Accept-Ranges')},
- {cookie, F('Cookie')},
- {keep_alive, F('Keep-Alive')},
- {location, F('Location')},
- {content_length, F('Content-Length')},
- {content_type, F('Content-Type')},
- {content_encoding, F('Content-Encoding')},
- {authorization, F('Authorization')},
- {transfer_encoding, F('Transfer-Encoding')}
+ Headers1 = [ connection, accept, host, if_modified_since,
+ if_match, if_none_match, if_range, if_unmodified_since,
+ range, referer, user_agent, accept_language, accept_ranges, cookie,
+ keep_alive, location, content_length, content_type,
+ content_encoding, authorization, x_forwarded_for, transfer_encoding
],
- [{K, V} || {K, V} <- Headers1, V /= undefined].
+ Headers2 = lists:map(fun(H) -> {H, header(H, Req)} end, Headers1),
+ [{K, V} || {K, V} <- Headers2, V /= undefined].
cookies(Req) ->
Headers = headers(Req),
@@ -81,3 +111,15 @@ post_params(Req) ->
request_body(Req) ->
Req:get(body).
+
+socket(Req) ->
+ Req:get(socket).
+
+recv_from_socket(Length, Timeout, Req) ->
+ Socket = socket(Req),
+ case gen_tcp:recv(Socket, Length, Timeout) of
+ {ok, Data} ->
+ Data;
+ _Other ->
+ exit(normal)
+ end.
@@ -1,9 +1,12 @@
-module (misultin_response_bridge).
-behaviour (simple_bridge_response).
-include_lib ("simple_bridge.hrl").
--export ([build_response/2]).
+-export ([build_response/2,init/1]).
-build_response(Req, Res) ->
+init({Req,DocRoot}) ->
+ {Req,DocRoot}.
+
+build_response({Req, DocRoot}, Res) ->
% Some values...
Code = Res#response.statuscode,
case Res#response.data of
@@ -18,7 +21,7 @@ build_response(Req, Res) ->
% Send the misultin response...
Req:respond(Code, Headers, Body);
{file, Path} ->
- Req:file([Path])
+ Req:file([DocRoot, Path])
end.
create_cookie_header(Cookie) ->
@@ -9,81 +9,123 @@
init/1,
request_method/1, path/1, uri/1,
peer_ip/1, peer_port/1,
- headers/1, cookies/1,
+ headers/1, header/2, cookies/1,
query_params/1, post_params/1, request_body/1,
socket/1, recv_from_socket/3
]).
-%% Mochiweb's max request size is 1MB, let's updated it to 1GB
--define(MAX_BODY_SIZE, (1024*1024*1024)).
+%% Max Body of 10MB by default
+-define(MAX_RECV_BODY,(1024*1024*10)).
-init({Req, DocRoot}) ->
- {Req, DocRoot}.
+init(Req) ->
+ Req.
-request_method({Req, _DocRoot}) ->
+request_method(Req) ->
Req:get(method).
-path({Req, _DocRoot}) ->
+path(Req) ->
RawPath = Req:get(raw_path),
{Path, _, _} = mochiweb_util:urlsplit_path(RawPath),
Path.
-uri({Req, _DocRoot}) ->
+uri(Req) ->
Req:get(raw_path).
-peer_ip({Req, _DocRoot}) ->
- Socket = Req:get(socket),
- {ok, {IP, _Port}} = inet:peername(Socket),
- IP.
+peer_ip(Req) ->
+ case Req:get(socket) of
+ false -> {127, 0, 0, 1};
+ Socket ->
+ {ok, {IP, _Port}} = mochiweb_socket:peername(Socket),
+ IP
+ end.
-peer_port({Req, _DocRoot}) ->
+peer_port(Req) ->
Socket = Req:get(socket),
- {ok, {_IP, Port}} = inet:peername(Socket),
+ {ok, {_IP, Port}} = mochiweb_socket:peername(Socket),
Port.
+
+header(connection, Req) ->
+ Req:get_header_value("connection");
+header(accept, Req) ->
+ Req:get_header_value("accept");
+header(host, Req) ->
+ Req:get_header_value("host");
+header(if_modified_since, Req) ->
+ Req:get_header_value("if-modified-since");
+header(if_match, Req) ->
+ Req:get_header_value("if-match");
+header(if_none_match, Req) ->
+ Req:get_header_value("if-none-match");
+header(if_unmodified_since, Req) ->
+ Req:get_header_value("if-unmodified-since");
+header(if_range, Req) ->
+ Req:get_header_value("if-range");
+header(range, Req) ->
+ Req:get_header_value("range");
+header(user_agent, Req) ->
+ Req:get_header_value("user-agent");
+header(accept_language, Req) ->
+ Req:get_header_value("accept-language");
+header(accept_ranges, Req) ->
+ Req:get_header_value("accept-ranges");
+header(cookie, Req) ->
+ Req:get_header_value("cookie");
+header(keep_alive, Req) ->
+ Req:get_header_value("keep-alive");
+header(location, Req) ->
+ Req:get_header_value("location");
+header(content_length, Req) ->
+ Req:get_header_value("content-length");
+header(content_type, Req) ->
+ Req:get_header_value("content-type");
+header(content_encoding, Req) ->
+ Req:get_header_value("content-encoding");
+header(authorization, Req) ->
+ Req:get_header_value("authorization");
+header(x_forwarded_for, Req) ->
+ Req:get_header_value("x-forwarded-for");
+header(transfer_encoding, Req) ->
+ Req:get_header_value("transfer-encoding");
+header(Header, Req) ->
+ Req:get_header_value(Header).
-headers({Req, _DocRoot}) ->
- F = fun(Header) -> Req:get_header_value(Header) end,
- Headers1 = [
- {connection, F("connection")},
- {accept, F("accept")},
- {host, F("host")},
- {if_modified_since, F("if-modified-since")},
- {if_match, F("if-match")},
- {if_none_match, F("if-range")},
- {if_unmodified_since, F("if-unmodified-since")},
- {range, F("range")},
- {referer, F("referer")},
- {user_agent, F("user-agent")},
- {accept_ranges, F("accept-ranges")},
- {cookie, F("cookie")},
- {keep_alive, F("keep-alive")},
- {location, F("location")},
- {content_length, F("content-length")},
- {content_type, F("content-type")},
- {content_encoding, F("content-encoding")},
- {authorization, F("authorization")},
- {x_forwarded_for, F("x-forwarded-for")},
- {transfer_encoding, F("transfer-encoding")}
+headers(Req) ->
+ Headers = [connection, accept, host, if_modified_since,
+ connection, accept, host, if_modified_since, if_match,
+ if_none_match, if_unmodified_since, if_range, range,
+ referer, user_agent, accept_language, accept_ranges,
+ cookie, keep_alive, location, content_length, content_type,
+ content_encoding, authorization, x_forwarded_for, transfer_encoding
],
+ Headers1 = lists:map(fun(H) -> {H, header(H, Req)} end, Headers),
[{K, V} || {K, V} <- Headers1, V /= undefined].
-cookies({Req, _DocRoot}) ->
+cookies(Req) ->
Req:parse_cookie().
-query_params({Req, _DocRoot}) ->
+query_params(Req) ->
Req:parse_qs().
-post_params({Req, _DocRoot}) ->
+post_params(Req) ->
Req:parse_post().
-request_body({Req, _DocRoot}) ->
- Req:recv_body(?MAX_BODY_SIZE).
+request_body(Req) ->
+ MaxBody = case application:get_env(mochiweb,max_request_size) of
+ undefined ->
+ ?MAX_RECV_BODY;
+ Max when is_integer(Max) ->
+ Max;
+ Other ->
+ error_logger:warning_msg("Mochiweb Simple Bridge Configuration Error! Unknown value for 'mochiweb' application variable 'max_request_size': ~p. Expected: integer() or undefined. Using Default of ~p~n",[Other,?MAX_RECV_BODY]),
+ ?MAX_RECV_BODY
+ end,
+ Req:recv_body(MaxBody).
-socket({Req, _DocRoot}) ->
+socket(Req) ->
Req:get(socket).
-recv_from_socket(Length, Timeout, {Req, DocRoot}) ->
- Socket = socket({Req, DocRoot}),
+recv_from_socket(Length, Timeout, Req) ->
+ Socket = socket(Req),
case gen_tcp:recv(Socket, Length, Timeout) of
{ok, Data} ->
put(mochiweb_request_recv, true),
@@ -22,7 +22,8 @@ build_response({Req, DocRoot}, Res) ->
[create_cookie_header(X) || X <- Res#response.cookies]
]),
- % Ensure content type...
+ %
+ % Ensure content type...
F = fun(Key) -> lists:keymember(Key, 1, Headers) end,
HasContentType = lists:any(F, ["content-type", "Content-Type", "CONTENT-TYPE"]),
Headers2 = case HasContentType of
@@ -34,13 +35,14 @@ build_response({Req, DocRoot}, Res) ->
Req:respond({Code, Headers2, Body});
{file, Path} ->
%% Calculate expire date far into future...
- Seconds = calendar:datetime_to_gregorian_seconds(calendar:local_time()),
- TenYears = 10 * 365 * 24 * 60 * 60,
- Seconds1 = calendar:gregorian_seconds_to_datetime(Seconds + TenYears),
- ExpireDate = httpd_util:rfc1123_date(Seconds1),
+ %% This method copied from Evan Miller's implementation
+ {{Y, _, _}, _} = calendar:local_time(),
+
+ ExpireDate = httpd_util:rfc1123_date(),
+ ExpireDate1 = re:replace(ExpireDate, " \\d\\d\\d\\d ", io_lib:format(" ~4.4.0w ", [Y + 10])),
%% Create the response telling Mochiweb to serve the file...
- Headers = [{"Expires", ExpireDate}],
+ Headers = [{"Expires", ExpireDate1}],
Req:serve_file(tl(Path), DocRoot, Headers)
end.
Oops, something went wrong.

0 comments on commit 736a094

Please sign in to comment.