couchdb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Chris Anderson <jch...@apache.org>
Subject Re: Webmachine dispatcher example
Date Wed, 06 May 2009 20:15:04 GMT
Including the CouchDB dev list here, as there's so much valuable information.

The topic is how to do sane rewriting of URLs under some design doc
path, so we can have flexible URLs for CouchDB, without breaking the
normal API contract we want to hold, as a database.

The goal is that a URL like

/db/_design/myapp/_rewrite/api/products/toasters

could be processed internally as if it were a request to

/db/_design/myapp/_list/products-index/all-products?prefix="toasters"&group_level=1&format=xml

Then you could use a (non-CouchDB) proxy to chop the beginning parts
off the path, so clients would only see:

/api/products/toasters

This is mostly helpful for supporting legacy applications with a
pure-CouchDB backend, but it's a nice bit of flexibility to offer
users in general.


On Wed, May 6, 2009 at 12:54 PM, Justin Sheehy <justin@iago.org> wrote:
> Hi Chris and Jason,
>
> On Tue, May 5, 2009 at 10:52 PM, Chris Anderson <jchris@apache.org> wrote:
>
>> Jason's been looking into how to build an internal rewriter for
>> CouchDB, so that applications can control their URLs. After your
>> Webmachine talk it got obvious to me that you've probably got code
>> that'd fit right into what we need.
>
> Sounds like a good possible fit indeed.  :-)
>
> At the end of this email is an example almost directly cut-and-pasted
> from an existing client application's dispatch configuration.  One of
> the important tricks you might notice there is the use of pattern-
> matching to decide not just which resource to dispatch to, but also
> what arguments to pass to that resource's init/1 function.
>
> The key to using this (outside webmachine itself) is that the
> dispatcher, given a list of dispatch terms and a request path,
> either produces a term indicating no match or else a 6-tuple:
>
> {Mod, ModOpts, PathTokens, Bindings, AppRoot, StringPath}
>
> Mod here is the atom from the 2nd element of the matching term.
>
> ModOpts is the 3rd element, used in webmachine as args to init/1.
>
> PathTokens and StringPath are the same thing in different forms,
> the path portion matched by '*' either split on "/" or left intact.
>
> Bindings is the dict of bindings indicated by atom terms in the spec,
> bound to the matching terms in the request path.
>
> AppRoot is rarely interesting and useful only for some legacy apps,
> and is generally something like "../.."; it could be deprecated and
> I suspect no one would notice.
>
> WIth this you could easily write out very different patterns which
> dispatched to the same resource, but provided it with different
> inputs.  That sounds like basically what you're looking for.
>
> An admitted downside to the current dispatch code in webmachine
> is that it is a bit more tied in to webmachine's structure than it really
> needs to be -- for purely historical reasons from webmachine's
> original non-public application.  I could happily be convinced to
> rework webmachine_dispatcher just a little bit so that it still supports
> existing webmachine installations but is also useful as a standalone
> module in other applications.
>
> I suspect that with that, and a little work in couch, you could use our
> dispatcher either for all of your URLs or for just ones under your _rewrite
> space.  I'm happy to help you get there; it shouldn't be hard.
>
> I suspect that the hardest part may be deciding exactly what you want
> to expose in terms of rewriting capability via the HTTP/JSON path.
>
>> So any examples of a relatively complex set of dispatch terms would be
>> helpful in this endeavor. Good work on Webmachine! If we weren't set
>> on letting untrusted users write applications (hence the JavaScript)
>> we'd be all over it.
>
> Here's the example you asked for.  I can happily add more details or
> explanation if you want.  Real applications on top of webmachine are
> nearly always a combination of Erlang and Javascript, by the way.
>
> Responding to you made me realize that I really do want to make the
> dispatcher more suitable for outside use, so I'll get on that shortly.
> (I'll fit it around Real Work over the next few days)
>
> I'm happy to chat as much more about this as you wish and to help
> develop the rewriting feature from the dispatch point of view.
>
> Cheers,
>
> -Justin
>
>
>
> {["pageconfig", pageid, "role", roleid], page_config_resource, []}.
> {["api","research"], proxy_resource, [{host_env, research_host},{path, "/r"}]}.
> {["api","news"], proxy_resource, [{host_env,rd_host},{path,"/rd/sig_dev"}]}.
> {["api", "gpe", "news"],proxy_resource, [{host_env,gpipe_host},{path,"/gpe"}]}.
> {["devuse", "metrics"],              metrics_resource,         []}.
> {["devuse", "metrics", bcust_key],   metrics_resource,         []}.
> {["api", "d12n", "search"], d12n_resource, [{mode, search}]}.
> {["api", "d12n", "detail"], d12n_resource, [{mode, detail}]}.
> {["api", "coweb", cokey], coweb_resource, []}.
> {["xavier", "list", '*'], xavier_resource, [{xaviertype, list}]}.
> {["favicon.ico"], fs_resource, [{root, "priv/www/images/favicon.ico"}]}.
> {["japi", bucket, key], japi_resource, ["japi", object]}.
> {["japi", bucket], japi_resource, ["japi", container]}.
> {["jaywalker", bucket, key, '*'], jaywalker_resource, []}.
> {['*'],  fs_resource, [{root, "priv/www"}]}.
>

Cool, this looks like it'd actually be really simple to integrate.

We'd essentially have a single module:function, perhaps
rewrite:internal_request or some such, that would take as an argument,
whatever it is that the dispatcher gives it, so from the JSON side,
each matcher could be something like (ignoring edge cases):

{ "match" : ["api", "products", "*"],
  "rewrite" : ["_list", "all-products", "products-api", {"prefix" :
"*", "group_level" : 1, "format" : "xml"}]
}

On the first _rewrite request we could "compile" this JSON down to the
term format the Webmachine dispatcher needs, and then use it for
rewrites until the design doc is changed.

Disclaimer: I've got other fish to fry, so I can't spend much time on
this feature, other than basic sanity-checking and guidance as far as
trying to make it something CouchDB can support without causing
trouble elsewhere in the API.

Chris

-- 
Chris Anderson
http://jchrisa.net
http://couch.io

Mime
View raw message