(Thanks indolering for pointing me to this thread.)
As I said to indolering, I'm very appreciative of the idea of collaborating on a technical specification / "standard" of sorts for this, even though I'm skeptical on the outset of reaching any consensus. Thank you phelix, however, for attempting it.
One guiding principle that I try to follow in all of my work is KISS, and all related concepts and corollaries around the idea that "simple is better", and "unnecessary complexity is exactly that." It's against the fire of that benchmark that I hope we can evaluate all proposals.
That said, I want to point out that when I did /[namespace]/[key] I didn't plan on stopping there. It was always my intention to make the API as powerful as possible, while at the same time ensuring that it contains
zero extraneous elements.
Let me illustrate what I mean by that by taking this API as an example (slightly modified for accuracy from the original example):
/?action=name_show&name=d%2Ffoobar
That can be represented (as already acknowledged) by a simple: /d/foobar
Why is this better? From the perspective of the API user, it's better simply because it's simpler and much easier to use. The original involves so many extraneous and unnecessary concepts for using it:
- Knowing the RPC name of the namecoind method (why should they care? No reason.)
- Calling the URL with GET parameters and having to form that query string
- URL encoding the request
Complexity with no advantages over simply asking for /d/foobar.
Say we want to do something more complicated, that cannot be expressed with a simple request for /d/foobar.
Say we want to create a new name, the equivalent of calling:
Followed by the corresponding:
Code: Select all
name_firstupdate <name> <rand> [<tx>] <value>
Here the namecoind RPC API introduces complexity that we don't need to expose to the users of DNSChain's (or indolering's solution.. not sure what it's called) API.
Notice that we can spare having to make two API calls and simply make it *one* API call. Notice also that there is no reason whatsoever for our users to have to worry about the values of <rand> or <tx>, so there's no reason for us to complicate our API or place that burden on them.
What's the minimum API? The minimum info is:
1. An action. (In this case, a way to indicate that we're creating a new name)
2. The key. (Let's use d/foobar)
3. The value. (Let's just label this as <json-string>)
HTTP already provides us with the means to express (1) because it has,
exactly for this purpose, its own verbs.
Thus, the API could be as simple as:
Simply create a POST request with the resource URL as the key, and the JSON as the body of the POST message.
The response can be some kind of unique key that confirms that the transaction happened, and that we can use later on to check the status of our registration.
The server, meanwhile, handles *for us* all of the ugly details that are of no importance to us:
1. It calls `name_new`
2. It waits the minimum amount of time necessary to then call `name_firstupdate` with the <json-string> that was passed in, and with the values for <rand> and <tx>.
That's *might* be all that's needed. To create a simple-yet-powerful API we have to start with the simplest possible API, and build it up in the smallest increments necessary to facilitate more powerful features. To do that we need a more complex use-case to explore.
Incremental, minimal complexity
If further complexity is required, we can implement it by building off of this solid and simple foundation. People who want the complexity will be exposed to it, and those who don't want it never have to see or deal with it.
Say we want our server to be notified the *second* that `name_firstupdate` succeeds. For this we'll need:
1. An endpoint for the DNSChain server to call back.
2. (Optional) format of the response with JSON being the default.
We can easily implement this on top of our existing example by taking a page from Twitter's wonderful API, where they have to deal with similar situations. It requires just one small modification:
Code: Select all
POST /d/foobar[.json|.xml]
json=<json-string-urlencoded>&callback=<URL-of-our-callback>
Two notes:
1. The [.json|.xml] indicates an optional extension to specify the format that the callback will receive
2. The one small modification is not that actually, as (1) is backwards compatible with the API. The one modification was the use of URL-encoded parameters to pass in the JSON, as well as all our other parameters (in this case, a callback URL).
More on responses
The discussion above about the response format is also interesting and needs to be address.
Again: what is the simplest, most elegant, and yet powerful way of presenting the response data? What are the various possible approaches?
Above we saw one possible approach: 100% JSON with a mandatory top-level format.
Another possible approach is to store some of that meta data (like response signature) in the HTTP response headers.
Which approach is the best? I can't tell offhand, it would need to be analyzed in detail with a tabulated pros & cons chart.
Some of the pros of ignoring HTTP headers and doing 100% JSON:
- Arguably simpler.
- Arguably more flexible and allows for meta-data to contain large chunks of data (what's the size limit on an HTTP response header?)
Some of the cons of 100% JSON:
- Less readable for human developers / more unwieldy. Headers allow us to focus on the response data itself, instead of the meta data that we (humans) do not care about (that's for the machine to care about).
- Possibly could result in more arguments among standards bodies about what the format actually should be (therefore hinting at a mandatory "version" key in the top-level).
The pros and cons for HTTP headers are basically the inverse of the above. Of course, I'm probably missing some, so please feel free to think about this and add your own!