Skip to content

Commit

Permalink
Auto-(de)serialize Json for vibe.web.web
Browse files Browse the repository at this point in the history
  • Loading branch information
wilzbach committed Jul 18, 2017
1 parent be6862a commit 169f7c5
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 9 deletions.
39 changes: 32 additions & 7 deletions tests/vibe.web.web/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module app;

import vibe.core.core;
import vibe.core.log;
import vibe.data.json;
import vibe.http.client;
import vibe.http.router;
import vibe.http.server;
Expand All @@ -10,20 +11,43 @@ import std.format : format;

// TODO: test the various parameter and return type combinations, as well as all attributes

struct MyStruct
{
int foo = 2;
}

class Service {
@noRoute void getFoo(HTTPServerResponse res) { res.writeBody("oops"); }
void getBar(HTTPServerResponse res) { res.writeBody("ok"); }
// for POST/PUT requests: incoming objects are automatically serialized to Json
// by default an unknown return type is serialized to Json
auto postStruct(MyStruct st) { return st.foo + 3; }
}

shared static this()
{
auto settings = new HTTPServerSettings;
settings.bindAddresses = ["127.0.0.1"];
settings.port = 9132;

auto router = new URLRouter;
router.registerWebInterface(new Service);

listenHTTP(settings, router);

runTask({
scope (exit) exitEventLoop();

void postJson(V)(string url, V[string] payload, HTTPStatus expected, scope void delegate(scope HTTPClientResponse res) expectedHandler) {
requestHTTP("http://127.0.0.1:9132"~url,
(scope req) {
req.method = HTTPMethod.POST;
req.writeJsonBody(payload);
},
(scope res) {
assert(res.statusCode == expected, format("Unexpected status code for %s: %s", url, res.statusCode));
expectedHandler(res);
}
);
}
void test(string url, HTTPStatus expected) {
requestHTTP("http://127.0.0.1:9132"~url,
(scope req) {
Expand All @@ -36,11 +60,12 @@ shared static this()
}
test("/foo", HTTPStatus.notFound);
test("/bar", HTTPStatus.ok);

postJson("/struct", ["foo": 5], HTTPStatus.ok, (scope res) {
auto j = res.readJson;
assert(j.get!int == 8);
});

logInfo("All web tests succeeded.");
});
}

class Service {
@noRoute void getFoo(HTTPServerResponse res) { res.writeBody("oops"); }
void getBar(HTTPServerResponse res) { res.writeBody("ok"); }
}
18 changes: 16 additions & 2 deletions web/vibe/web/web.d
Original file line number Diff line number Diff line change
Expand Up @@ -868,8 +868,18 @@ private void handleRequest(string M, alias overload, C, ERROR...)(HTTPServerRequ
} else static if (is(PT == bool)) {
params[i] = param_names[i] in req.form || param_names[i] in req.query;
} else {
import std.algorithm.comparison : among;

enum has_default = !is(default_values[i] == void);
ParamResult pres = readFormParamRec(req, params[i], param_names[i], !has_default, nested_style, err);
ParamResult pres = void;
// For POST/PUT requests, parameters are usually sent via JSON
if (req.method.among(HTTPMethod.POST, HTTPMethod.PUT) && req.json.type != Json.Type.undefined && i == 0) {
params[i].setVoid(req.json.deserializeJson!PT);
pres = ParamResult.ok;
} else {
// otherwise try to read the parameters from a query forms
pres = readFormParamRec(req, params[i], param_names[i], !has_default, nested_style, err);
}
static if (has_default) {
if (pres == ParamResult.skipped)
params[i].setVoid(default_values[i]);
Expand Down Expand Up @@ -964,8 +974,12 @@ private void handleRequest(string M, alias overload, C, ERROR...)(HTTPServerRequ
} else {
res.writeBody(ret);
}
} else static if (is(RET : string)) {
res.writeBody(ret);
} else {
static assert(is(RET == void), M~": Only InputStream, Json and void are supported as return types for route methods.");
// Serialize to Json by default
static if (!is(RET : void))
res.writeJsonBody(ret);
}
}
} catch (Exception ex) {
Expand Down

0 comments on commit 169f7c5

Please sign in to comment.