Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add support for Cowboy. #9

Merged
merged 1 commit into from

3 participants

@olcai

This adds support for the Cowboy web server.

It is basically a straight port using the logic in the Mochiweb module, adapting it to Cowboy's request interface.

@olcai olcai Add support for Cowboy.
Also updates README with info regarding Cowboy.
89dc8b9
@tgrk

This looks really nice! Is there any chance it will be merged into main repo?

@tonyg tonyg merged commit 89dc8b9 into tonyg:master
@tonyg
Owner

Oops! This slipped through the cracks. @olcai, thank you for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 15, 2012
  1. @olcai

    Add support for Cowboy.

    olcai authored
    Also updates README with info regarding Cowboy.
This page is out of date. Refresh to see the latest.
View
8 README.md
@@ -32,6 +32,13 @@ See
to learn how to delegate incoming Mochiweb HTTP requests to the
JSON-RPC service dispatcher.
+### Using Cowboy
+
+See
+[rfc4627\_jsonrpc\_cowboy.erl](http://tonyg.github.com/erlang-rfc4627/doc/rfc4627_jsonrpc_cowboy.html)
+to learn how to delegate incoming Cowboy HTTP requests to the
+JSON-RPC service dispatcher.
+
## Running the example test service that comes with the source code
Included with the Erlang RFC4627 source code is a small Inets-based
@@ -88,6 +95,7 @@ contributions from others:
- Eugene Volchek
- Simon MacMullen
- Andrey Khozov
+ - Erik Timan
## Copyright and Licence
View
1  ebin/rfc4627_jsonrpc.app
@@ -9,6 +9,7 @@
rfc4627_jsonrpc_http,
rfc4627_jsonrpc_inets,
rfc4627_jsonrpc_mochiweb,
+ rfc4627_jsonrpc_cowboy,
rfc4627_jsonrpc_registry
]},
{registered, []},
View
113 src/rfc4627_jsonrpc_cowboy.erl
@@ -0,0 +1,113 @@
+%% JSON-RPC for Cowboy
+%%---------------------------------------------------------------------------
+%% @author Erik Timan <dev@timan.info>
+%% @author Tony Garnock-Jones <tonygarnockjones@gmail.com>
+%% @author LShift Ltd. <query@lshift.net>
+%% @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd.
+%% @license
+%%
+%% Permission is hereby granted, free of charge, to any person
+%% obtaining a copy of this software and associated documentation
+%% files (the "Software"), to deal in the Software without
+%% restriction, including without limitation the rights to use, copy,
+%% modify, merge, publish, distribute, sublicense, and/or sell copies
+%% of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+%%
+%% The above copyright notice and this permission notice shall be
+%% included in all copies or substantial portions of the Software.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+%% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+%% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+%% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+%% SOFTWARE.
+%%---------------------------------------------------------------------------
+%%
+%% @reference the <a href="http://github.com/extend/cowboy/">Cowboy github page</a>
+%%
+%% @doc Support for serving JSON-RPC via Cowboy.
+%%
+%% Familiarity with writing Cowboy applications is assumed.
+%%
+%% == Basic Usage ==
+%%
+%% <ul>
+%% <li>Register your JSON-RPC services as usual.</li>
+%% <li>Decide on your `AliasPrefix' (see {@link rfc4627_jsonrpc_http:invoke_service_method/4}).</li>
+%% <li>When a Cowboy request arrives at your application, call {@link handle/2} with your `AliasPrefix' and the request.</li>
+%% </ul>
+%%
+%% It's as simple as that - if the request's URI path matches the
+%% `AliasPrefix', it will be decoded and the JSON-RPC service it names
+%% will be invoked.
+
+-module(rfc4627_jsonrpc_cowboy).
+
+-export([handle/2]).
+
+normalize(X) when is_atom(X) ->
+ string:to_lower(atom_to_list(X));
+normalize(X) when is_binary(X) ->
+ string:to_lower(binary_to_list(X));
+normalize(X) when is_list(X) ->
+ string:to_lower(X).
+
+%% @spec (string(), #http_req{}) -> no_match | {ok, #http_req{}}
+%%
+%% @doc If the request matches `AliasPrefix', the corresponding
+%% JSON-RPC service is invoked, and an `{ok, #http_req{}}' is returned;
+%% otherwise, `no_match' is returned.
+%%
+%% Call this function from your Cowboy HTTP handler's `handle'
+%% function, as follows:
+%%
+%% ```
+%% Req2 = case rfc4627_jsonrpc_cowboy:handle("/rpc", Req) of
+%% no_match ->
+%% handle_non_jsonrpc_request(Req);
+%% {ok, Reponse} ->
+%% Response
+%% end
+%% '''
+%%
+%% where `handle_non_jsonrpc_request' does the obvious thing for
+%% non-JSON-RPC requests.
+handle(AliasPrefix, Req) ->
+ {BinaryPath, _} = cowboy_http_req:raw_path(Req),
+ Path = binary_to_list(BinaryPath),
+ {QSVals, _} = cowboy_http_req:qs_vals(Req),
+ QueryObj = {obj, [{binary_to_list(K), V} || {K,V} <- QSVals]},
+ {Hdrs, _} = cowboy_http_req:headers(Req),
+ HeaderObj = {obj, [{normalize(K), V} || {K,V} <- Hdrs]},
+ {PeerAddr, _} = cowboy_http_req:peer_addr(Req),
+ Peer = list_to_binary(inet_parse:ntoa(PeerAddr)),
+ {Method, _} = cowboy_http_req:method(Req),
+ RequestInfo = {obj, [{"http_method", list_to_binary(atom_to_list(Method))},
+ {"http_query_parameters", QueryObj},
+ {"http_headers", HeaderObj},
+ {"remote_peername", Peer},
+ {"scheme", <<"http">>}]},
+ {ok, Body, _} = cowboy_http_req:body(Req),
+
+ case rfc4627_jsonrpc_http:invoke_service_method(AliasPrefix,
+ Path,
+ RequestInfo,
+ Body) of
+ no_match ->
+ no_match;
+ {ok, ResultEnc, ResponseInfo} ->
+ {obj, ResponseHeaderFields} =
+ rfc4627:get_field(ResponseInfo, "http_headers", {obj, []}),
+ StatusCode =
+ rfc4627:get_field(ResponseInfo, "http_status_code", 200),
+ Headers = [{list_to_binary(K), V} || {K,V} <- ResponseHeaderFields],
+ RespType = [{<<"Content-Type">>, rfc4627:mime_type()}],
+ cowboy_http_req:reply(StatusCode,
+ Headers ++ RespType,
+ ResultEnc,
+ Req)
+ end.
Something went wrong with that request. Please try again.