我听说过 vibe.d http://vibed.org/ 的好消息
不过,我从未亲自使用过它,因为我在 vibe 出现之前就编写了自己的库。
https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff
vibe 有更好的文档记录,所以你最好去那里,但我的库是这样工作的:
cgi.d 是基本的 Web 界面(如果需要,在编译时使用 -version=embedded_httpd 以使用它自己的 Web 服务器而不是 CGI),我在一个名为 web.d 的单独文件中提供了一些 RESTy 的东西。它依赖于 cgi.d、dom.d、characterencodings.d 和 sha.d。您可能还需要 database.d 和 mysql.d 来连接到 mysql 数据库。
web.d 的工作方式是您只需编写函数,它会自动将它们映射到 url 并格式化数据。
http://arsdnet.net/cgi-bin/apidemo/add-some-numbers
该部分的源代码是:
import arsd.web;
class MySite : ApiProvider {
export int addSomeNumbers(int a, int b) { return a+b; }
}
mixin FancyMain!MySite;
web.d 会自动生成您在此处看到的表单,将 url 解析为给定的类型,并将返回值格式化为 html、json 或其他格式(例如,可以将对象制成表格)。
还有一个envelopeFormat url param,可以把它包装成更多的json,最适合机器消费:
http://arsdnet.net/cgi-bin/apidemo/add-some-numbers?a=1&b=2&format=json&envelopeFormat=json
我的 github 中的 web.d.php 显示了一种使用它的方式,web.d 本身会自动生成 JavaScript 函数以从客户端调用:
MySite.addSomeNumbers(10, 20).get(function(answer) { alert("Server replied: " + answer); });
答案将是 D 函数返回的类型。
如果您不想要/不需要自动函数包装,cgi.d 单独提供访问基本信息和编写函数的权限:
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;
但是,是的,我的库中存在的大多数文档只是我在论坛上谈论它......我认为一旦你完成了一个功能,就不难弄清楚,但我有偏见!
编辑:从我下面的评论中复制/粘贴,因为它与真正获得 RESTy 非常相关:
实际上,我确实尝试过将 url 映射到对象并且动词经过的想法:web.d 还包含一个 ApiObject 类,该类如下: /obj/name -> new Obj("name");然后在其上调用适当的方法。所以 GET /obj/name 调用 (new Obj("name")).GET();,同样适用于 POST、PUT 等。然后 /obj/name/foo 调用 (new Obj("name").foo() ; 使用与我在上面描述的函数相同的规则。
但是我没有像普通函数那样使用它,因为它仍然有些错误......而且它仍然有些错误,因为我没有足够的使用它来坐下来适应它!哈哈
您通过编写一个 ApiObject 类然后将其别名到 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/
}
当然,还要定义对象:
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;
然后就可以访问了:
http://arsdnet.net/cgi-bin/apidemo2/obj/cool/
顺便说一句,尾部斜线是强制性的:这是我尚未解决的突出错误之一。 (尾部的斜杠代码比它应该的要复杂,使它看起来更难修复。)
无论如何,您可以通过 makeHtmlElement 看到对象本身呈现为 html。这是展示其他格式的好时机:
http://arsdnet.net/cgi-bin/apidemo2/obj/cool/?format=table
table,也可以试试 csv,当然还有 json
http://arsdnet.net/cgi-bin/apidemo2/obj/cool/?format=json
或用于机器消耗:
http://arsdnet.net/cgi-bin/apidemo2/obj/cool/?format=json&envelopeFormat=json
并且该属性也可用:
http://arsdnet.net/cgi-bin/apidemo2/obj/cool/id
另一个主要的突出错误是自动生成的 Javascript 函数根本无法访问子对象。它们仅适用于顶级 ApiProvider 上的功能。另一个比看起来更难修复的错误,我并不是特别想这样做,因为顶级函数无论如何都可以完成。当然,您可以自己在 xmlhttprequest 上创建 URL 并以这种方式访问它。
让我们也通过一个快速表单来演示 POST:
http://arsdnet.net/cgi-bin/apidemo2/poster
您可以提交一些东西并看到 POST 处理程序确实重置了名称。 (顺便说一句,该动作有斜杠:没有它,它会默默地重定向你!我真的应该解决这个问题。)
无论如何,尽管存在错误,但它的核心仍然有效,并且可能是目前最接近成熟 REST D 的东西。