Does anyone know of anything like what I'm calling "HTTP stubs?"
Basically, it goes like this: You'd have an interface that says something like:
<httpinterface> <title>Oddmuse Interface</title> <description>yadda yadda yadda</description> <separator>;</separator> <action> <title>edit</title> <description>edit a wiki page</description> <method>GET</method> <arg> <title>contents</title> <type>string</type> <form>page</form> ... </arg> <arg> ... </arg> </action> <action> ... </action> </httpinterface>
Then, from the interface description, you could generate stubs, for Python, Perl, PHP, whatever languages, automatically.
You can also generate HTML form pages or page fragments.
You could also write skeletons or skeleton-adapters for various languages.
These skeletons could include built-in help documentation, so that "action=help" is implicitely defined for all these services. There'd also be response of the interface definition itself. (That is, you could dynamically query for the raw HTTP interace description.)
This is basically like SOAP, except for HTTP raw interface, which some people seem to prefer.
There's just so much tedium involved in making a simple raw HTTP web service, it feels like it shouldn't be there.
I remember some blogger mentioning something about raw HTTP interface standards, but I don't remember where,… If I recall right, nobody really responded to the call.
There seems to be something called HTTP-NG, but I can't say I really get it, after quickly looking over it.
If I were to write an interface definition, it would be in XML, and look something like this:
Something like that.
Here's what a one-function interface might look like:
<httpinterface> <title>Local Names Server</title> <short>Resolve names, manage cache</short> <description>The Local Names Server can use Local Names v1.1 namespace descriptions to resolve URLS. The interface lets you resolve names, and query and manage the namespace cache.</description> <actionkey>action</actionkey> <separator>&</separator> <action> <name>lookup</name> <short>Resolve a local name</short> <description>Resolve a local name. Namespace hopping is allowed. Namespace hops are designated by a separator in the lookup value.</description> <method>get</method> <example>?action=lookup&namespace=http://ln.taoriver.net/localnames.txt&separator=/&lookup=services/rfc/ftp</example> <arg> <name>namespace</name> <short>URL of namespace description</short> <description>URL of v1.1 Local Names namespace description. This is the namespace that resolution begins in.</description> <min>1</min> <max>1</max> <form>long</form> </arg> <arg> <name>lookup</name> <short>Lookup path</short> <description>Lookup path. This is the path that resolution follows. If the separator does not appear (path length 1,) then just look up this name in the namespace description. Otherwise, start traversing namespace links until reaching the final name in the final namespace.</description> <min>1</min> <form>long</form> </arg> <arg> <name>separator</name> <short>Lookup path separator</short> <description>Lookup path separator. This symbol, when appearing in the lookup path, separates names. All names but the last name namespaces, the last name names a name within a namespace.</description> <min>0</min> <max>1</max> <form>short</form> <default>/</default> </arg> <result> <short>Resulting URLs</short> <description>List of resulting URLs. Results that could not be found return as empty lines.</description> <type>string</type> <list/> </result> </action> </httpinterface>
Code that uses it might look like this:
server = httpinterface.HttpInterface("http://services.taoriver.net:9090/") for action in server.actions: print "%s -- %s" % (action.name, action.description) # Print action documentation urls = server.call("lookup", namespace="http://taoriver.net/tmp/gmail.txt", lookup="Lion Kimbro") urls2 = server.call("lookup", "http://taoriver.net/tmp/gmail.txt", ["Lion Kimbro", "Alex Schroeder", "Marshall Brain"])
In this case, what happens is:
It's also possible to automatically create HTML forms that submit to the web service.
It is also possible to automatically generate help documentation, too, on either the client, the server, or a 3rd party server that consults the 1st server for it's XML HTTP interface description.
It's my belief that this sort of thing is mildly useful.
At the very least, it's personally useful, because I like to make a lot of web services, but dislike the process of writing documentation, the process of putting the server together, the process of putting together Python stubs, yadda yadda yadda. This can automate all that.
That said, SOAP does pretty much exactly this, just in infinitely greater grace and detail.
So why don't I use SOAP?
Because all my friends prefer HTTP interfaces. They all go, "Ewwwwww… SOAP!" Or: "Ewwwww… XML-RPC!"
I honestly don't understand it.
But my friends seem to want HTTP, and if that's what they want, I'm happy to grant it.
So, what would you think?
Is this something I should work on? Or should I just stick with SOAP or XML-RPC?-
I'm not sure… Does this really save that much work? When I look at the XML config file, I wonder whether the corresponding Perl code plus docu pages on the wiki would be about the same size and don't require anything beyond a basic CGI library. If we really did it like you descibe it here, we might as well use SOAP. People like me like to use HTTP directly because it is lean and mean. Using httpinterface.HttpInterface?("http://services.taoriver.net:9090/") seems an attempt at saving work for other contributors where we're not even sure yet it will take off. Premature optimization and all that. For one developer this proposal adds complexity instead of reducing it.
The motivation for this is:
Doing it the "lean & mean" way, by hand, is extremely tedius.
Now, you've mentioned complexity. What complexity?
It's an XML format. I thought it was pretty straight-forward.
I can imagine tools. They would look something like:
class LocalNamesResolver: def lookup(namespace, lookup, separator): do_some_stuff() do_some_stuff() return result
if __name__ == '__main__': server_class = HttpStubsServer.HttpStubsServer httpd = server_class((HOST_NAME, PORT_NUMBER), LocalNamesResolver) httpd.serve_forever()
This would give you a self-documenting server (both for humans and machines,) an HTTP API, and the server.
If you wanted it to be a CGI, I imagine just a few lines at the bottom would make that work.
I don't know; It just seems like a really good idea to me.
I'm honestly perplexed by the frequency that people tell me that these kinds of ideas are bad.
I have to conclude that it's some form of StopEnergy, for the following two reasons:
Charles Babbage, Napoleon Hill, David Winer, and Tim Berner's Lee have all said these things. And many more.
So, please don't take it personally if I ignore it.
It honestly doesn't seem very complicated to me; And it honestly seems labor saving to me.
At the very least, on just a personal level, it makes it possible for me to write things that are extremely hard to write otherwise. (Writing them isn't hard. Writing them well and consistently is.)
I say we give it a try, then.
Thank you, Alex.
I'm getting to work on it, right now.
Define external redirect: HttpInterface