LoginSignup
3
3

More than 5 years have passed since last update.

vibe.d Webアプリ開発ことはじめ

Last updated at Posted at 2016-12-23

はじめに

おことわり

  • やること
    • 簡単なWeb APIサーバーを作ります
  • やらないこと
    • GUIはやらないです
    • DBは使いません
    • D言語くんはでてきません

環境について

  • マルチプラットホーム
    • Windowsでも普通に動くぞ!やったぜ!
  • Dockerは?

待ち受けアドレスとポートを変更する

app.d
import vibe.d

void main()
{
  string address = "127.0.0.1";
  ushort port    = 8080;

  readOption("bindAddress|b", &address, "Sets the address for listning.");
  readOption("port|p", &port, "Sets the port for listning.");

  if (!finalizeCommandLineOptions()) return;
  lowerPrivileges();

  auto settings = new HTTPServerSettings;
  settings.port = port;
  settings.bindAddresses = [address];

  auto router = new URLRouter;
  router.get("/", &hello);
  listenHTTP(settings, router);

  // イベントループ呼び出し
  runEventLoop();
}

void hello(HTTPServerRequest req, HTTPServerResponse res)
{
  res.writeBody("Hello, World!");
}

REST Interfaceを使ってみる

app.d
import vibe.d;

void main()
{
  string address = "127.0.0.1";
  ushort port    = 8080;

  readOption("bindAddress|b", &address, "Sets the address for listning.");
  readOption("port|p", &port, "Sets the port for listning.");

  if (!finalizeCommandLineOptions())
    return;
  lowerPrivileges();

  auto settings = new HTTPServerSettings;
  settings.port = port;
  settings.bindAddresses = [address];

  auto router = new URLRouter;
  router.get("/", &hello);

  auto test = new TestImplementation;
  router.registerRestInterface(test);

  listenHTTP(settings, router);

  runEventLoop();
}

void hello(HTTPServerRequest req, HTTPServerResponse res)
{
  res.writeBody("Hello, World!");
}

interface TestInterface
{
  @path("test")
  string getTest();
}

class TestImplementation : TestInterface
{
  string getTest()
  {
    return "Hello from test resource!";
  }
}
$ curl localhost:8080/test
"Hello from test resource!"

もう少しRESTfulにリソースを作ってみる

app.d

import vibe.d;
import resource;

void main()
{
  string address = "127.0.0.1";
  ushort port    = 8080;

  readOption("bindAddress|b", &address, "Sets the address for listning.");
  readOption("port|p", &port, "Sets the port for listning.");

  if (!finalizeCommandLineOptions())
    return;
  lowerPrivileges();

  auto settings = new HTTPServerSettings;
  settings.port = port;
  settings.bindAddresses = [address];

  auto router = new URLRouter;
  auto test = new TestImplementation;
  router.registerRestInterface(test);

  listenHTTP(settings, router);

  runEventLoop();
}
resource.d
module resource;
import vibe.d;

struct Resource
{
  long id;
  string name;
}

interface TestAPI
{
  Resource getResource(long id);
  Resource postResource(string name);
}

class TestImplementation : TestAPI
{
  Resource getResource(long id)
  {
    return Resource(id, "test");
  }

  Resource postResource(string name)
  {
    return Resource(1, name);
  }
}
$ curl -X POST -H "Content-Type: application/json" -d '{"name": "test"}' localhost:8080/resource
{"id":1,"name":"test"}
$ curl localhost:8080/1/resource
{"id":1,"name":"test"}

任意のパスを設定する

  • /resources/:id に変更する
resrouce.d

 interface TestAPI
 {
-  Resource getResource(long id);
+  @path("resources/:id")
+  Resource getResource(long _id);
   Resource postResource(string name);
 }

 class TestImplementation : TestAPI
 {
-  Resource getResource(long id)
+  Resource getResource(long _id)
   {
-    return Resource(id, "test");
+    return Resource(_id, "test");
   }

   Resource postResource(string name)

JSONのキー名に"body"を使う

  • 変数名をbody_にする
resource.d
@@ -4,14 +4,14 @@ import vibe.d;
 struct Resource
 {
   long id;
-  string name;
+  string body_;
 }

 interface TestAPI
 {
   @path("resources/:id")
   Resource getResource(long _id);
-  Resource postResources(string name);
+  Resource postResources(string body_);
 }

 class TestImplementation : TestAPI
@@ -21,8 +21,8 @@ class TestImplementation : TestAPI
     return Resource(_id, "test");
   }

-  Resource postResources(string name)
+  Resource postResources(string body_)
   {
-    return Resource(1, name);
+    return Resource(1, body_);
   }
 }
curl -X POST -H "Content-Type: application/json" -d '{"body": "test"}' localhost:8080/resources
{"id":1,"body":"test"}

とにかくエラーを返す

resource.d
 Resource getResource(long _id)
 {
   enforceHTTP(_id > 0, HTTPStatus.notFound, httpStatusText(HTTPStatus.notFound));
   return Resource(_id, "test");
 }
$ curl -i localhost:8080/resources/1
HTTP/1.1 200 OK
Server: vibe.d/0.7.30
Date: Wed, 14 Dec 2016 14:50:15 GMT
Keep-Alive: timeout=10
Content-Type: application/json; charset=UTF-8
Content-Length: 22

{"id":1,"body":"test"}
$ curl -i localhost:8080/resources/0
HTTP/1.1 404 Not Found
Server: vibe.d/0.7.30
Date: Wed, 14 Dec 2016 14:50:20 GMT
Keep-Alive: timeout=10
Content-Type: application/json; charset=UTF-8
Content-Length: 29

{"statusMessage":"Not Found"}

MVCっぽく書いてみる

app.d
+  router.post("/resources", &test.postResources);
resource.d
module resource;
import vibe.d;

class Resource
{
  static int count = 0;
  long id;
  string body_;

  this (string body_)
  {
    this.id    = ++count;
    this.body_ = body_;
  }

  static Resource create(Json json)
  {
    string body_ = json["body"].get!(string);
    return new Resource(body_);
  }
}

interface TestAPI
{
  @path("resources/:id")
  Resource getResource(long _id);
}

class TestImplementation : TestAPI
{
  Resource getResource(long _id)
  {
    enforceHTTP(_id > 0, HTTPStatus.notFound, httpStatusText(HTTPStatus.notFound));
    return new Resource("test");
  }

  void postResources(HTTPServerRequest req, HTTPServerResponse res)
  {
    auto resource = Resource.create(req.json);
    res.writeJsonBody(serializeToJson(resource), HTTPStatus.created);
  }
}
$ curl -X POST -H "Content-Type: application/json" -d '{"body": "test:1"}' localhost:8080/resources
{"body":"test:1","id":1}
$ curl -X POST -H "Content-Type: application/json" -d '{"body": "test:2"}' localhost:8080/resources
{"body":"test:2","id":2}

ログレベル

まとめ

  • Ruby on Rails等と比べると機能の貧弱さは否めない
  • 大体のことは公式情報とソースを読めば解決できそう
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3