%% vim: ts=4 sw=4 et
% Simple Bridge
% Copyright (c) 2008-2010 Rusty Klophaus
% Copyright (c) 2013-2014 Jesse Gumm
% See MIT-LICENSE for licensing information.
-module (webmachine_simple_bridge).
-behaviour (simple_bridge).
-include ("simple_bridge.hrl").
-export ([
init/1,
protocol/1,
host/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,
socket/1,
recv_from_socket/3,
protocol_version/1,
native_header_type/0
]).
-export([
build_response/2
]).
init(Req) ->
Req.
protocol(Req) ->
wrq:scheme(Req).
host(Req) ->
% @TODO: Can we get the absolute URI without all this?
BaseURI = wrq:base_uri(Req),
MochiHeaders = wrq:req_headers(Req),
Host = mochiweb_headers:get_value("host", MochiHeaders),
XForwardedFor = mochiweb_headers:get_value("x-forwarded-for", MochiHeaders),
simple_bridge_util:infer_host(BaseURI, Host, XForwardedFor).
request_method(Req) ->
wrq:method(Req).
path(Req) ->
wrq:path(Req).
uri(Req) ->
wrq:raw_path(Req).
peer_ip(Req) ->
{ok, Address} = inet_parse:address(wrq:peer(Req)),
Address.
peer_port(Req) ->
wrq:port(Req).
headers(Req) ->
Mochiheaders = wrq:req_headers(Req),
mochiweb_headers:to_list(Mochiheaders).
native_header_type() ->
list.
cookies(Req) ->
wrq:req_cookie(Req).
query_params(Req) ->
Value = wrq:req_qs(Req),
Value.
post_params(Req) ->
Body = wrq:req_body(Req),
Value = mochiweb_util:parse_qs(Body),
Value.
request_body(Req) ->
wrq:req_body(Req).
socket(Req) ->
%% If https://github.com/basho/webmachine/pull/175 is accepted, change to:
%% wrq:socket(Req).
%% 7th element of wm_reqdata record is wm_state, which contains another
%% record, but which can be interacted with through
%% webmachine_request:socket
%%
%% If this suddenly starts breaking, then we need to verify the record
%% structure of wm_reqdata.hrl
%%
%% https://github.com/basho/webmachine/blob/master/include/wm_reqdata.hrl
ReqState = element(7, Req),
{Socket, _} = webmachine_request:socket(ReqState),
Socket.
recv_from_socket(Length, Timeout, Req) ->
Socket = socket(Req),
case gen_tcp:recv(Socket, Length, Timeout) of
{ok, Data} -> Data;
_ -> exit(normal)
end.
protocol_version(Req) ->
wrq:version(Req).
build_response(Req, Res) ->
Code = Res#response.status_code,
case Res#response.data of
{data, Body} ->
Size = integer_to_list(erlang:iolist_size(Body)),
%% Assemble headers...
Headers = lists:flatten([
{content_length, Size},
[{X#header.name, X#header.value} || X <- Res#response.headers],
[create_cookie_header(X) || X <- Res#response.cookies]
]),
Req1 = wrq:set_response_code(Code, Req),
Req2 = wrq:set_resp_headers(Headers, Req1),
{ok, Body, Req2};
{file, Path} ->
%% We should really never get here, because Webmachine
%% works via a dispatch table mapping routes to
%% modules. For this case to happen, it means the dispatch
%% table mapped a route to a static file.
throw({unrouted_static_file, [
{requested_file, Path},
{description, "Simple Bridge for Webmachine is not set up to handle static files. Static files should be handled by Webmachine through the dispatch table."},
{see_also, [
"https://github.com/nitrogen/simple_bridge/blob/master/src/webmachine/webmachine_simple_bridge_sup.erl",
"https://github.com/nitrogen/simple_bridge/blob/master/etc/webmachine.config"
]}
]})
end.
create_cookie_header(Cookie) ->
simple_bridge_util:create_cookie_header(Cookie).