Вопрос

I would like to use to create a RESTful web application.

What are the most actively maintained and contributed projects that are worth considering? A short comparison of these web frameworks with pluses and minuses will be nice.

My search lead me to only one project, which seems like an excellent framework: vibe.d

Are there other projects which are minimal in nature like ?

Это было полезно?

Решение 2

At the moment of writing this text there is no framework for building true RESTful web services that I know of. However, you should be able to easily build one on top of vibe.d or Adam's web modules that he already mentioned above.

Другие советы

I've heard good things about vibe.d http://vibed.org/

Though, I've never personally used it because I wrote my own libraries well before vibe came out. https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff

vibe is better documented, so you might be better off going there, but here's how my libraries work:

cgi.d is the base web interface (use -version=embedded_httpd when compiling to use its own web server instead of CGI if you want), and I offer some RESTy stuff in a separate file called web.d. It depends on cgi.d, dom.d, characterencodings.d, and sha.d. You might also want database.d and mysql.d for connecting to a mysql database.

The way web.d works is you just write functions and it automatically maps them to url and formats data.

http://arsdnet.net/cgi-bin/apidemo/add-some-numbers

The source code to that portion is:

import arsd.web;
class MySite : ApiProvider {
     export int addSomeNumbers(int a, int b) { return a+b; }
}
mixin FancyMain!MySite;

web.d automatically generates the form you see there, parses the url into the types given, and formats the return value into either html, json, or sometimes other things (for example, objects can be made into tables).

There is also an envelopeFormat url param that can wrap it in more json, best for machine consumption: http://arsdnet.net/cgi-bin/apidemo/add-some-numbers?a=1&b=2&format=json&envelopeFormat=json

web.d.php in my github shows one way you can consume it, and web.d itself automatically generates javascript functions to call from the client:

MySite.addSomeNumbers(10, 20).get(function(answer) { alert("Server replied: " + answer); });

answer would be of the type returned by the D function.

If you don't want/need the automatic function wrapping, cgi.d alone gives access to the basic info and writing functions:

void requestHandler(Cgi cgi) {
    // there's cgi.get["name"], cgi.post["name"], or cgi.request("name"), kinda like php
    cgi.write("hello ", cgi.request("name"));
}
mixin GenericMain!requestHandler;

But yeah, most the documentation that exists for my library is just me talking about it on forums... I think once you've done one function it isn't hard to figure out, but I'm biased!

edit: copy/paste from my comment below since it is pretty relevant to really getting RESTy:

I actually did play with the idea of having urls map to objects and the verbs go through: web.d also includes an ApiObject class which goes: /obj/name -> new Obj("name"); and then calls the appropriate methods on it. So GET /obj/name calls (new Obj("name")).GET();, same for POST, PUT, etc. Then /obj/name/foo calls (new Obj("name").foo(); with the same rules as I described for functions above.

But I don't use it as much as the plain functions for one because it is still somewhat buggy.... and it is still somewhat buggy because I don't use it enough to sit down and fit it all! lol

You use it by writing an ApiObject class and then aliasing it into the ApiProvider:

import arsd.web;
class MySite : ApiProvider {
     export int addSomeNumbers(int a, int b) { return a+b; }
     alias MyObject obj; // new, brings in MyObject as /obj/xxx/
}

And, of course, define the object:

class MyObject : ApiObject {
    CoolApi parent;
    string identifier;
    this(CoolApi parent, string identifier) {
    this.parent = parent;
    this.identifier = identifier;

    /* you might also want to load any existing object from a database or something here, using the identifier string, and initialize other members */
    // for now to show the example, we'll just initialize data with dummy info

    data.id = 8;
    data.name = "MyObject/" ~ identifier;
    }

    /* define some members as a child struct so we can return them later */
    struct Data {
    int id;
    string name;
    Element makeHtmlElement() {
        // for automatic formatting as html
        auto div = Element.make("div");
        import std.conv;
        div.addChild("span", to!string(id)).addClass("id");
        div.appendText(" ");
        div.addChild("span", name).addClass("name");
        return div;
    }
    }

    Data data;

    export Data GET() {
    return data;
    }

    export Data POST(string name) {
    parent.ensureGoodPost(); // CSRF token check

    data.name = name;
    // normally, you'd commit the changes to the database and redirect back to GET or something like that, but since we don't have a db we'll just return the modified object

    return data;
    }

// property accessors for the data, if you want
    export int id() {
    return data.id;
    }
}

mixin FancyMain!MySite;

Then you can access it:

http://arsdnet.net/cgi-bin/apidemo2/obj/cool/

BTW the trailing slash is mandatory: this is one of the outstanding bugs I haven't gotten around to fixing yet. (The trailing slash code is more complicated than it should be, making this harder to fix that it might look.)

Anyway, you can see the object rendered itself as html via makeHtmlElement. This is a good time to showcase other formats:

http://arsdnet.net/cgi-bin/apidemo2/obj/cool/?format=table

table, also try csv, and of course, json

http://arsdnet.net/cgi-bin/apidemo2/obj/cool/?format=json

or for machine consumption: http://arsdnet.net/cgi-bin/apidemo2/obj/cool/?format=json&envelopeFormat=json

and the property is available too: http://arsdnet.net/cgi-bin/apidemo2/obj/cool/id

Another major outstanding bug is that the automatically generated Javascript functions can't access child objects at all. They only work on functions on the top level ApiProvider. Another bug that is harder to fix than it might seem, and I'm not particularly driven to do so because the top-level functions can do it all anyway. Of course, you could make the URLs yourself on the xmlhttprequest and access it that way.

Let's also demo POST by slapping together a quick form:

http://arsdnet.net/cgi-bin/apidemo2/poster

you can submit something and see the POST handler indeed reset the name. (BTW note the action has that trailing slash: without it, it silently redirects you! I really should fix that.)

Anyway, bugs notwithstanding, the core of it works and might be the closest thing to full blown REST D has right now.

You can take a look at what I'm building. Still extremely alpha, but I'm attempting to build a Rails-like framework in D: http://jaredonline.github.io/action-pack/

I know this is a really late answer, but I figured someone might come by this one day, since it has been so long and a lot of changes has happened within the D community, especially towards web development.

With Diamond you can write RESTful web applications without hacking something together, since it supports it within the framework.

http://diamondmvc.org/docs/backend/#rest

You can try Hunt Framework.

routes setting

GET    /user/{id}    user.detail

app/UserController.d souce code:

module app.controller.UserController;

import hunt.framework;

class User
{
    int id;
    string name;
}

class UserController : Controller
{
    mixin MakeController;

    @Action
    JsonResponse detail(int id)
    {
        auto user = new User;
        user.id = id;
        user.name = "test";

        return new JsonResponse(user);
    }
}

Request http://localhost:8080/user/123

{
    "id": 123,
    "name": "test"
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top