[99s-extend] Proposal for Cowboy Routing
Thomas Allen
thomas at oinksoft.com
Tue Nov 13 17:10:04 CET 2012
On Tue, Nov 13, 2012 at 04:22:48PM +0100, Loïc Hoguin wrote:
> No, just check that cowboy_req:path/1 ends with $/, and if it
> doesn't then redirect.
OK, so what I'm going for is to actually check for a valid URL with the
slash. I got it to work in current cowboy, but shield your eyes ...
I do this "middleware" thing often ... this might be a misnomer as I
think some definitions of middleware specify that it be able to wrap the
request *and* the response. I digress ...
%%% foo_app.erl:
{ok, _} = cowboy:start_http(http, ?ACCEPTORS,
[{port, ?PORT}],
[{dispatch, Dispatch},
{onrequest, fun(Req) ->
foo_middleware:all(Dispatch, Req)
end}]
),
%% foo_middleware.erl:
-define(MIDDLEWARE, [
fun foo_middleware:slash/2,
fun foo_middleware:session/2,
fun foo_middleware:user/2
]).
all(Dispatch, Req) ->
lists:foldl(fun(F, CurReq) -> F(Dispatch, CurReq) end, Req,
?MIDDLEWARE).
%% ...
slash(Dispatch, Req) ->
{Path, _} = cowboy_req:path(Req),
case binary:last(Path) of
$/ -> Req;
_ ->
SlashPath = <<Path/bitstring, "/">>,
{Host, _} = cowboy_req:host(Req),
Match = cowboy_dispatcher:match(Dispatch, Host,
SlashPath),
case element(1, Match) of
ok ->
cowboy_req:reply(301,
[{<<"Location">>, SlashPath}], <<>>, Req);
error -> Req
end
end.
So, I assume that any path not ending in "/" won't match. Another
version of this could toss that assumption, but then you're performing
an extra match on every request ... much better to use a '_' rule in
that case.
One thing that is icky about using a fallback '_' handler, and the
reason I've elected to use onrequest for this example, is that I do not
see a way to access cowboy_protocol's state.dispatch to access these
rules. So, I enclose them in my `onrequest` fun. Would it be possible to
expose Dispatch? This has many applications, particularly for URL
reversing.
Perhaps I am missing several things ;^)
Thomas
More information about the Extend
mailing list