Skip to content
Browse files

Initial commit

  • Loading branch information...
0 parents commit c2c445a356a9f503944a277158ad83a8b95122bb @rustyio rustyio committed May 9, 2009
3 .gitmodules
@@ -0,0 +1,3 @@
+[submodule "lib/etap"]
+ path = lib/etap
+ url = git://github.com/ngerakines/etap.git
10 Emakefile
@@ -0,0 +1,10 @@
+% Compile Nitrogen Files.
+{ './src/*', [ debug_info,
+ { i, "./include" },
+ { outdir, "./ebin" }
+]}.
+
+{ './src/*/*', [ debug_info,
+ { i, "./include" },
+ { outdir, "./ebin" }
+]}.
14 Makefile
@@ -0,0 +1,14 @@
+all: compile
+
+compile:
+ mkdir -p ebin
+ erl \
+ -pa ./ebin \
+ -make
+
+clean:
+ rm -rf ./ebin/*.*
+
+test:
+ git submodule update --init lib/etap
+ make -C lib/etap
1 ebin/.gitignore
@@ -0,0 +1 @@
+
BIN ebin/mochiweb_request_bridge.beam
Binary file not shown.
BIN ebin/request_bridge.beam
Binary file not shown.
BIN ebin/request_bridge_wrapper.beam
Binary file not shown.
BIN ebin/response_bridge.beam
Binary file not shown.
BIN ebin/response_bridge_wrapper.beam
Binary file not shown.
3 include/simplebridge.inc
@@ -0,0 +1,3 @@
+-record(response, { statuscode=200, headers=[], cookies=[], data=[] }).
+-record(cookie, { name, value, path="/", minutes_to_live=20 }).
+-record(header, { name, value }).
171 src/platforms/inets_request_bridge.erl.txt
@@ -0,0 +1,171 @@
+% Erlang Web Bridge
+% Copyright (c) 2008-2009 Rusty Klophaus
+% See MIT-LICENSE for licensing information.
+
+-module (wf_platform_inets).
+-include ("httpd.hrl").
+-export ([
+ get_platform/0,
+
+ get_raw_path/0,
+ get_querystring/0,
+ get_request_method/0,
+ get_request_body/0,
+
+ get_headers/0,
+ get_header/1,
+
+ parse_get_args/0,
+ parse_post_args/0,
+
+ get_cookie/1,
+ create_cookie/4,
+
+ create_header/2,
+
+ build_response/0,
+
+ get_socket/0,
+ recv_from_socket/2
+]).
+
+get_platform() -> inets.
+
+%%% PATH, METHOD, AND ARGS %%%
+
+get_raw_path() ->
+ Info = wf_platform:get_request(),
+ Info#mod.request_uri.
+
+get_querystring() ->
+ Info = wf_platform:get_request(),
+ {_Path, QueryString} = httpd_util:split_path(Info#mod.request_uri),
+ case QueryString of
+ [] -> [];
+ _ -> tl(QueryString)
+ end.
+
+get_request_method() ->
+ Info = wf_platform:get_request(),
+ wf:to_atom(Info#mod.method).
+
+get_request_body() ->
+ Req = wf_platform:get_request(),
+ Req#mod.entity_body.
+
+parse_get_args() ->
+ QueryString = get_querystring(),
+ Query = httpd:parse_query(QueryString),
+ [{Key, Value} || {Key, Value} <- Query, Key /= []].
+
+parse_post_args() ->
+ Info = wf_platform:get_request(),
+ Query = httpd:parse_query(Info#mod.entity_body),
+ [{Key, Value} || {Key, Value} <- Query, Key /= []].
+
+
+%%% HEADERS
+
+get_headers() ->
+ Info = wf_platform:get_request(),
+ Headers = Info#mod.parsed_header,
+ F = fun(Header) -> proplists:get_value(Header, Headers) end,
+ [
+ {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")}
+ ].
+
+get_header(Header) ->
+ Headers = get_headers(),
+ proplists:get_value(Header, Headers).
+
+%%% COOKIES %%%
+
+get_cookie(Key) ->
+ Key1 = wf:to_list(Key),
+ Info = wf_platform:get_request(),
+ Headers = Info#mod.parsed_header,
+ CookieData = proplists:get_value("cookie", Headers, ""),
+ F = fun(Cookie) ->
+ case string:tokens(Cookie, "=") of
+ [] -> [];
+ L ->
+ X = string:strip(hd(L)),
+ Y = string:join(tl(L), "="),
+ {X, Y}
+ end
+ end,
+ Cookies = [F(X) || X <- string:tokens(CookieData, ";")],
+ proplists:get_value(Key1, Cookies).
+
+create_cookie(Key, Value, Path, MinutesToLive) ->
+ SecondsToLive = MinutesToLive * 60,
+ Expire = to_cookie_expire(SecondsToLive),
+ {"Set-Cookie", wf:f("~s=~s; Path=~s; Expires=~s", [Key, Value, Path, Expire])}.
+
+to_cookie_expire(SecondsToLive) ->
+ Seconds = calendar:datetime_to_gregorian_seconds(calendar:local_time()),
+ DateTime = calendar:gregorian_seconds_to_datetime(Seconds + SecondsToLive),
+ httpd_util:rfc1123_date(DateTime).
+
+
+
+%%% HEADERS %%%
+create_header(Key, Value) ->
+ {Key, Value}.
+
+
+%%% RESPONSE %%%
+
+build_response() ->
+ % Get vars...
+ Info = wf_platform:get_request(),
+ ResponseCode = get(wf_response_code),
+ ContentType = get(wf_content_type),
+ Body = get(wf_response_body),
+ Size = integer_to_list(httpd_util:flatlength(Body)),
+
+ % Assemble headers...
+ Headers = lists:flatten([
+ {code, ResponseCode},
+ {content_type, ContentType},
+ {content_length, Size},
+ get(wf_headers)
+ ]),
+
+ % Send the inets response...
+ {proceed,[
+ {response, {response, Headers, Body}},
+ {mime_type, ContentType} | Info#mod.data
+ ]}.
+
+
+%%% SOCKETS %%%
+
+get_socket() ->
+ Info = wf_platform:get_request(),
+ Info#mod.socket.
+
+recv_from_socket(Length, Timeout) ->
+ Socket = get_socket(),
+ case gen_tcp:recv(Socket, Length, Timeout) of
+ {ok, Data} -> Data;
+ _ -> exit(normal)
+ end.
45 src/platforms/mochiweb_request_bridge.erl
@@ -0,0 +1,45 @@
+% Simple Erlang Web Bridge
+% Copyright (c) 2008-2009 Rusty Klophaus
+% See MIT-LICENSE for licensing information.
+
+-module (mochiweb_request_bridge).
+-behaviour (request_bridge).
+-export ([
+ init/1,
+ request_method/1, url/1, protocol/1, hostname/1, port/1, path/1, querystring/1,
+ peer_ip/1, peer_port/1
+]).
+
+
+init(Req) ->
+ Req.
+
+request_method(Req) ->
+ Req:get(method).
+
+url(_Req) ->
+ ok.
+
+protocol(_Req) ->
+ ok.
+
+hostname(_Req) ->
+ ok.
+
+port(_Req) ->
+ ok.
+
+path(_Req) ->
+ ok.
+
+querystring(Req) ->
+ Req = wf_platform:get_request(),
+ RawPath = Req:get(raw_path),
+ {_, QueryString, _} = mochiweb_util:urlsplit_path(RawPath),
+ QueryString.
+
+peer_ip(_Req) ->
+ ok.
+
+peer_port(_Req) ->
+ ok.
144 src/platforms/yaws_request_bridge.erl.txt
@@ -0,0 +1,144 @@
+% Erlang Web Bridge
+% Copyright (c) 2008-2009 Rusty Klophaus
+% See MIT-LICENSE for licensing information.
+
+-module (wf_platform_yaws).
+-include ("yaws_api.hrl").
+-export ([
+ get_platform/0,
+
+ get_raw_path/0,
+ get_querystring/0,
+ get_request_method/0,
+ get_request_body/0,
+
+ parse_get_args/0,
+ parse_post_args/0,
+
+ get_cookie/1,
+ create_cookie/4,
+
+ create_header/2,
+ get_headers/0,
+ get_header/1,
+
+ build_response/0,
+
+ get_socket/0,
+ recv_from_socket/2
+]).
+
+get_platform() -> yaws.
+
+%%% PATH, METHOD, AND ARGS %%%
+
+get_raw_path() ->
+ Arg = wf_platform:get_request(),
+ wf:f("~s?~s", [Arg#arg.server_path, wf:to_list(Arg#arg.querydata)]).
+
+get_querystring() ->
+ Arg = wf_platform:get_request(),
+ Arg#arg.querydata.
+
+get_request_method() ->
+ Arg = wf_platform:get_request(),
+ (Arg#arg.req)#http_request.method.
+
+get_request_body() ->
+ Arg = wf_platform:get_request(),
+ case Arg#arg.clidata of
+ {partial, Data} -> Data;
+ Data -> Data
+ end.
+
+parse_get_args() ->
+ Arg = wf_platform:get_request(),
+ yaws_api:parse_query(Arg).
+
+parse_post_args() ->
+ Arg = wf_platform:get_request(),
+ yaws_api:parse_post(Arg).
+
+
+
+%%% COOKIES %%%
+
+get_cookie(Key) ->
+ Arg = wf_platform:get_request(),
+ Key1 = wf:to_list(Key),
+ Headers = Arg#arg.headers,
+ yaws_api:find_cookie_val(Key1, Headers#headers.cookie).
+
+create_cookie(Key, Value, Path, MinutesToLive) ->
+ SecondsToLive = MinutesToLive * 60,
+ Expire = to_cookie_expire(SecondsToLive),
+ yaws_api:setcookie(Key, Value, Path, Expire).
+
+to_cookie_expire(SecondsToLive) ->
+ Seconds = calendar:datetime_to_gregorian_seconds(calendar:local_time()),
+ DateTime = calendar:gregorian_seconds_to_datetime(Seconds + SecondsToLive),
+ httpd_util:rfc1123_date(DateTime).
+
+
+
+%%% HEADERS %%%
+
+create_header(Key, Value) ->
+ {header, {Key, Value}}.
+
+get_headers() ->
+ Arg = wf_platform:get_request(),
+ Headers = Arg#arg.headers,
+ [
+ {connection, Headers#headers.connection},
+ {accept, Headers#headers.accept},
+ {host, Headers#headers.host},
+ {if_modified_since, Headers#headers.if_modified_since},
+ {if_match, Headers#headers.if_match},
+ {if_none_match, Headers#headers.if_range},
+ {if_unmodified_since, Headers#headers.if_unmodified_since},
+ {range, Headers#headers.range},
+ {referer, Headers#headers.referer},
+ {user_agent, Headers#headers.user_agent},
+ {accept_ranges, Headers#headers.accept_ranges},
+ {cookie, Headers#headers.cookie},
+ {keep_alive, Headers#headers.keep_alive},
+ {location, Headers#headers.location},
+ {content_length, Headers#headers.content_length},
+ {content_type, Headers#headers.content_type},
+ {content_encoding, Headers#headers.content_encoding},
+ {authorization, Headers#headers.authorization},
+ {transfer_encoding, Headers#headers.transfer_encoding}
+ ].
+
+get_header(Header) ->
+ Headers = get_headers(),
+ proplists:get_value(Header, Headers).
+
+%%% RESPONSE %%%
+
+build_response() ->
+ % Get vars...
+ ContentType = get(wf_content_type),
+ Body = get(wf_response_body),
+
+ % Send the yaws response...
+ lists:flatten([
+ {status, get(wf_response_code)},
+ get(wf_headers),
+ {content, ContentType, Body}
+ ]).
+
+
+%%% SOCKETS %%%
+
+get_socket() ->
+ Arg = wf_platform:get_request(),
+ Arg#arg.clisock.
+
+recv_from_socket(Length, Timeout) ->
+ Socket = get_socket(),
+ case gen_tcp:recv(Socket, Length, Timeout) of
+ {ok, Data} -> Data;
+ _ -> exit(normal)
+ end.
43 src/request_bridge.erl
@@ -0,0 +1,43 @@
+% Simple Erlang Web Bridge
+% Copyright (c) 2008-2009 Rusty Klophaus
+% See MIT-LICENSE for licensing information.
+
+-module (request_bridge).
+-export ([
+ make/2,
+ behaviour_info/1
+]).
+
+make(Module, Req) ->
+ Req1 = Module:init(Req),
+ request_bridge_wrapper:new(Module, Req1).
+
+behaviour_info(callbacks) -> [
+ % Init
+ {init, 1},
+
+ % GET, POST, etc.
+ {request_method, 1},
+
+ % URL PARTS
+ % protocol://hostname:port/path/pathinfo?query
+ {url, 1},
+ {protocol, 1},
+ {hostname, 1},
+ {port, 1},
+ {path, 1},
+ {querystring, 1},
+
+ % % Data Sent from Client
+ % {headers, 1},
+ % {cookies, 1},
+ % {query_params, 1},
+ % {post_params, 1},
+ % {request_body, 2},
+
+ % Client Information
+ {peer_ip, 1},
+ {peer_port, 1}
+];
+
+behaviour_info(_) -> undefined.
17 src/request_bridge_wrapper.erl
@@ -0,0 +1,17 @@
+% Simple Erlang Web Bridge
+% Copyright (c) 2008-2009 Rusty Klophaus
+% See MIT-LICENSE for licensing information.
+
+-module (request_bridge_wrapper, [Mod, Req]).
+-compile(export_all).
+
+request_method() -> Mod:request_method(Req).
+url() -> Mod:url(Req).
+protocol() -> Mod:protocol(Req).
+hostname() -> Mod:hostname(Req).
+port() -> Mod:port(Req).
+path() -> Mod:path(Req).
+querystring() -> Mod:querystring(Req).
+
+peer_ip() -> Mod:peer_ip(Req).
+peer_port() -> Mod:peer_port(Req).
20 src/response_bridge.erl
@@ -0,0 +1,20 @@
+% Simple Erlang Web Bridge
+% Copyright (c) 2008-2009 Rusty Klophaus
+% See MIT-LICENSE for licensing information.
+
+
+-module (response_bridge).
+-include ("simplebridge.inc").
+-export ([
+ make/1,
+ behaviour_info/1
+]).
+
+make(Mod) ->
+ response_bridge_wrapper:new(Mod, #response{}).
+
+behaviour_info(callbacks) -> [
+ {build_response, 0}
+];
+
+behaviour_info(_) -> ok.
41 src/response_bridge_wrapper.erl
@@ -0,0 +1,41 @@
+% Simple Erlang Web Bridge
+% Copyright (c) 2008-2009 Rusty Klophaus
+% See MIT-LICENSE for licensing information.
+
+-module (response_bridge_wrapper, [Mod, Res]).
+-include ("simplebridge.inc").
+-compile(export_all).
+
+set_status_code(StatusCode) ->
+ Res1 = Res#response { statuscode=StatusCode },
+ response_bridge:make(Mod, Res1).
+
+header(Name, Value) ->
+ Header = #header { name=Name, value=Value },
+ Headers = Res#response.headers,
+ Headers1 = [X || X <- Headers, X#header.name /= Name],
+ Headers2 = [Header|Headers1],
+ Res1 = Res#response { headers=Headers2 },
+ response_bridge:make(Mod, Res1).
+
+clear_headers() ->
+ Res1 = Res#response { headers=[] },
+ response_bridge:make(Mod, Res1).
+
+cookie(Name, Value, Path, MinutesToLive) ->
+ Cookie = #cookie { name=Name, value=Value, path=Path, minutes_to_live=MinutesToLive },
+ Cookies = Res#response.cookies,
+ Cookies1 = [X || X <- Cookies, X#cookie.name /= Name],
+ Cookies2 = [Cookie|Cookies1],
+ Res1 = Res#response { cookies=Cookies2 },
+ response_bridge:make(Mod, Res1).
+
+clear_cookies() ->
+ Res1 = Res#response { cookies=[] },
+ response_bridge:make(Mod, Res1).
+
+data(Data) ->
+ Res1 = Res#response { data=Data },
+ response_bridge:make(Mod, Res1).
+
+build_response() -> Mod:build_response(Res).

0 comments on commit c2c445a

Please sign in to comment.
Something went wrong with that request. Please try again.