diff --git a/tests/vibe.web.web/source/app.d b/tests/vibe.web.web/source/app.d index 06fb8ab86f..8b30a4a01b 100644 --- a/tests/vibe.web.web/source/app.d +++ b/tests/vibe.web.web/source/app.d @@ -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; @@ -10,12 +11,24 @@ 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); @@ -23,7 +36,18 @@ shared static this() 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) { @@ -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"); } -} diff --git a/web/vibe/web/web.d b/web/vibe/web/web.d index 9a3eae7cc4..9329a11c97 100644 --- a/web/vibe/web/web.d +++ b/web/vibe/web/web.d @@ -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]); @@ -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) {