fermata icon indicating copy to clipboard operation
fermata copied to clipboard

Split URL building from HTTP handling?

Open natevw opened this issue 6 years ago • 2 comments

Looking over #49 again it strikes me that perhaps folding the "method methods" (.get(cb)/.put(data, cb)/etc.) into the same namespace as the URL path components has sort of boxed us in re. things like clean Promise support.

Conceptually Fermata is two parts:

  • a "syntax" for building URLs
  • an HTTP request library

Perhaps they would be useful as separate pieces; when bundled together they'd hinge around the empty () call that currently just returns a string. You'd still build a URL with the current tricks var url = base.api.path.to('some-thing', {s:}) and have the nice HTTP plugin stack via .put({foo:42}, function (err, data, meta) { … }) pattern — but you'd need the () between your URL and the HTTP methods: url().get(cb).

One catch would be how to control the HTTP "plugin stack" apart from the URL. I think we could handle that by still allowing functions to be passed to the () — only now the function would be the HTTP plugin rather than the cb. Something like:

var f = require('fermata');

var serverUrl = f.url("https://example.com"),
    widgetsUrl = serverUrl.api({v:1}).user[name].widgets;

/*                          \         / <--- passing a plugin function
var widgetsHttp = widgetsUrl(f.PROMISE);
widgetsHttp.get().then(function (d) {
  // …
});

This isn't something I want to do lightly, because it's something of a fundamental shift in what Fermata is. How would this affect "wrappers" like fermata-couchdb with its var db = fermata.couchdb()('my-database')?

I've tried to position Fermata as the "un-wrapper for X", where X is any web API. Rather than wrapping [CouchDB]((https://github.com/natevw/fermata-couchdb), Twitter, Flickr, Chargify, etc. etc. each with their own special wrapper that tries to paper over the underlying API — often nearly re-inventing, then re-documenting it — Fermata provides plugins to set up the basics like JSON and OAuth, but otherwise leaves the server API as the JavaScript API.

Would splitting the "URL stuff" from the "HTTP stuff" jeopardize the "web API not-a-wrapper" goal?

natevw avatar Oct 16 '17 17:10 natevw

Wouldn't this address #28 too?

natevw avatar Jan 18 '18 23:01 natevw

As a solution to the plugin dilemma of the initial idea, perhaps the URL objects can be "pre-annotated" by a plugin?

The proposal here is basically that () returns a wrapper around the underlying transport. That transport can be an implicit part of the URL object, right?

E.g. if you create a URL using a plugin that includes OAuth or other special headers, that URL gets associated from the get-go with a transport plugin. The challenge then is simply what the "core API" would looks like for a plugin to make this association.

natevw avatar Jan 18 '18 23:01 natevw