%% 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).