I just implemented the concept described in that post in my web.d, and earlier in the week, implemented automatic Javascript bindings generation.
Here's a live demo: http://arsdnet.net/apidemo.html This is the server side implementation: http://arsdnet.net/apidemo.d Do not adjust your text editor - it's actually a mere 14 lines long. You just write D functions. Most the work is done in the helper modules http://arsdnet.net/dcode/web.d Depends on: http://arsdnet.net/dcode/cgi.d http://arsdnet.net/dcode/dom.d (btw the struct members are all static due to a decision decision I think I've changed my mind on, but haven't changed the code yet. I think a class would be better though - can slash a lot of the __traits(compiles) if I just use virtual functions.) There's other features available in web.d not used here, like automatic and hookable html form generation, output format post processing, initialization functions, etc. You can also accept a Cgi and ReflectionInfo object in the initializer if you want to do more traditional web things or see what you have in that struct. (Originally, the idea was to autogenerate websites, so there's a lot of code for datatype -> html, html templates, html forms, etc. All that still works, of course: http://arsdnet.net/cgi-bin/apidemo/foo But I've been playing with program access recently, since I actually prefer the traditional method of making the pages on the whole. Since they can exist side by side in the same executable, it's pretty awesome still.) Anyway, FancyMain just calls three other functions, wrapped up in a main: auto reflection = prepareReflection!(T)(cgi); run(cgi, reflection); ReflectionInfo stores piles of info about your passed object. All functions (and still to do: enums and structs) are checked out. Their return type, name, and arguments - both names and types - are stored. A template also generates a wrapper function that makes the call from cgi info. run() takes the cgi pathinfo and get/post data to call the wrapper. It also catches exceptions to either handle automatically in the case of html or wrap up for the other system in case of json. run() also does a little piece of magic. If the path requested is functions.js... it uses the reflection info to generate a javascript object that mimics the D struct, along with some other info: http://arsdnet.net/cgi-bin/apidemo/functions.js (See the bottom for the D function wrappers. There's quite a bit of javascript there that I just wrote in web.d straight up.) Note how the JS object name matches the D struct name too, and the argument names match up. also, if it's compiled in debug mode, the Javascript is made in debug mode, giving better error messages, etc. I might write an automatic PHP too, but php can actually call the api functions without needing a code generator - it has a feature similar to D's opDispatch. Using web.d's positional argument support, it can just forward to the server without knowing anything. (Some vendor's implementations of javascript have this too, but you can't depend on it, so the codegen is better.) There's a bunch of helper callbacks there too, to make using the function return value easier in the async environment. You can see that in apidemo.html - in the end, it does appendTo(), which takes the returned string, treats it as html, and appends it to the given element. I'm planning on adding better typechecking there - if you return a Html() or Element in D, it is html. If it's a string, it should do append text instead. The static types are there - let's use them. Anyway, enough blabbing. The interesting thing here is what all D could do to make this work. When I get around to writing my article, I'll discuss what it can do again, but also go into how much of a pain it is to do this kind of thing in PHP and other popular languages for both calling and implementing the web api. D's built in documentation naturally helps here too. All the stuff is generated from the same place, so it's easy to doc too. I saw a php thing that tries to do the same, for example, but you had to do things just write, had to manually register the functions, and couldn't just write javascript normally... and, of course, it's php. Ugh.
