1 module web;
2 
3 import std.stdio;
4 import std.typecons;
5 import std.json;
6 import vibe.d;
7 import vibrant.d;
8 import mir.ser.json : serializeJson;
9 
10 struct Book {
11     string id;
12 }
13 
14 struct Bookshelf {
15     static Book[] all = [Book("apple"), Book("banana"), Book("cherry")];
16 
17     static Nullable!Book find(string id) {
18         foreach (book; all) {
19             if (book.id == id) {
20                 return Nullable!Book(book);
21             }
22         }
23         return Nullable!Book.init;
24     }
25 
26     static bool destroy(string id) {
27         foreach (i, book; all) {
28             if (book.id == id) {
29                 all = all[0 .. i] ~ all[i + 1 .. $];
30                 return true;
31             }
32         }
33         return false;
34     }
35 }
36 
37 class BookController {
38     mixin Routes;
39 
40     // GET /book
41     void index() {
42         auto books = Bookshelf.all;
43 
44         render!JSON = books.serializeJson;
45     }
46 
47     // GET /book/:id
48     void show() {
49         auto id = params["id"].as!string;
50         auto book = Bookshelf.find(id);
51 
52         render!JSON = book.serializeJson;
53     }
54 
55     // DELETE /book/:id
56     void destroy() {
57         auto id = params["id"].as!string;
58 
59         if (Bookshelf.destroy(id)) {
60             render!EMPTY = 201;
61         } else {
62             render!EMPTY = 404;
63         }
64     }
65 }
66 
67 void vibrant_web(T)(T vib) {
68     with (vib) {
69         // static files from wwwroot
70         router.get("*", serveStaticFiles("./wwwroot"));
71         // router.get("/static/*", serveStaticFiles("./wwwroot", new HTTPFileServerSettings("/static")));
72 
73         Get("/hello", (req, res) => "Hello World!");
74 
75         Before("/hello/:name", (req, res) {
76             if (req.params["name"] == "Jack") {
77                 halt("Don't come back.");
78             }
79         });
80 
81         Get("/hello/:name", (req, res) =>
82                 "Hello " ~ req.params["name"]
83         );
84 
85         Catch(Exception.classinfo, (ex, req, res) {
86             res.statusCode = 500;
87             res.writeBody(ex.msg);
88         });
89 
90         Get("/oops", (req, res) { throw new Exception("Whoops!"); });
91 
92         Get!Json("/hello2/:name", "application/json",
93             (req, res) =>
94                 Json([
95                         "greeting": Json("Hello " ~ req.params["name"])
96                     ]),
97                 (json) =>
98                 json.toPrettyString
99         );
100 
101         with (Scope("/api")) {
102             // Path : /api/hello
103             Get("/hello", (req, res) => "Hello developer!");
104 
105             with (Scope("/admin")) {
106                 // Path : /api/admin/hello
107                 Get("/hello", (req, res) => "Hello admin!");
108             }
109         }
110 
111         Resource!BookController;
112     }
113 }