RejectedSoftware Forums

Sign up

JSON in query parameters

I have a somewhat weird JSON API I'm trying to replicate in vibe.d using the rest interface generator. It uses query parameters for the top level keys of a JSON object and the values will be JSON objects (don't ask why). Example:

curl 'http://foobar.com/find_foo?ids=[1,2,3]'

(The JSON array needs to be URL encoded)

This works fine for GET requests but the API is similar for POST requests as well, but the data is passed in the body instead:

curl -d 'ids=[1,2,3]' http://foobar.com/update_foo

This way of passing the JSON data does not work for POST requests.

What's the best way to deal with this? I would really like to be able to use the rest interface generator because it's very convenient that (de)serialization is handle automatically. It's a bit inconsistent in vibe.d that it works with GET requests but not with POST request.

/Jacob Carlborg

Re: JSON in query parameters

On Tue, 14 Jun 2016 08:58:15 GMT, Jacob Carlborg wrote:

I have a somewhat weird JSON API I'm trying to replicate in vibe.d using the rest interface generator. It uses query parameters for the top level keys of a JSON object and the values will be JSON objects (don't ask why). Example:

curl 'http://foobar.com/find_foo?ids=[1,2,3]'

(The JSON array needs to be URL encoded)

This works fine for GET requests but the API is similar for POST requests as well, but the data is passed in the body instead:

curl -d 'ids=[1,2,3]' http://foobar.com/update_foo

This way of passing the JSON data does not work for POST requests.

What's the best way to deal with this? I would really like to be able to use the rest interface generator because it's very convenient that (de)serialization is handle automatically. It's a bit inconsistent in vibe.d that it works with GET requests but not with POST request.

/Jacob Carlborg

Serialization formats for query and body parameters are currently unfortunately still hard-coded, but making that customizable is planned. It still shows that the REST generator was initially just intended as a simple means to provide a RESTful RPC mechanism and not to replicate existing REST APIs.

The exact API design for the customization still needs to be worked out. The basic idea would be to define a UDA à la @bodySerializer!TheSerializer, but there are probably some details that require something more complex.

Re: JSON in query parameters

On 2016-06-20 19:22, Sönke Ludwig wrote:

Serialization formats for query and body parameters are currently unfortunately still hard-coded, but making that customizable is planned. It still shows that the REST generator was initially just intended as a simple means to provide a RESTful RPC mechanism and not to replicate existing REST APIs.

The exact API design for the customization still needs to be worked out. The basic idea would be to define a UDA à la @bodySerializer!TheSerializer, but there are probably some details that require something more complex.

I see. Is it possible to somehow to do with the current version of
vibe.d, using some form of middleware of before hook? I thinking that
request could be modified to something the REST generator expects.

/Jacob Carlborg

Re: JSON in query parameters

On Mon, 20 Jun 2016 21:38:20 +0200, Jacob Carlborg wrote:

(...)

I see. Is it possible to somehow to do with the current version of
vibe.d, using some form of middleware of before hook? I thinking that
request could be modified to something the REST generator expects.

/Jacob Carlborg

If you just need to model the server side, it should work with @before:

private Json extractContents(HTTPServerRequest req, HTTPServerResponse res)
{
    return req.json;
}

@before!extractContents("contents")
void postSomething(Json contents)
{
    // ...
}

The client side wouldn't really work, though, AFAICS.

Re: JSON in query parameters

On Sat, 02 Jul 2016 09:11:11 GMT, Sönke Ludwig wrote:

On Mon, 20 Jun 2016 21:38:20 +0200, Jacob Carlborg wrote:

(...)

I see. Is it possible to somehow to do with the current version of
vibe.d, using some form of middleware of before hook? I thinking that
request could be modified to something the REST generator expects.

/Jacob Carlborg

If you just need to model the server side, it should work with @before:

private Json extractContents(HTTPServerRequest req, HTTPServerResponse res)
{

return parseJsonString(req.form["someparam"]);

}

@before!extractContents("contents")
void postSomething(Json contents)
{
    // ...
}

The client side wouldn't really work, though, AFAICS.

Sorry, mixed up the topic. Corrected extractContents is above. I didn't test this, so I'm not 100% sure that the interface generator doesn't try to access the body as a JSON object, but if it does, that would at least be easily fixable.

Re: JSON in query parameters

On 02/07/16 11:17, Sönke Ludwig wrote:

Sorry, mixed up the topic. Corrected extractContents is above. I didn't test this, so I'm not 100% sure that the interface generator doesn't try to access the body as a JSON object, but if it does, that would at least be easily fixable.

I can give it a try. It's only the server side I need.

/Jacob Carlborg

Re: JSON in query parameters

On Sat, 02 Jul 2016 09:17:00 GMT, Sönke Ludwig wrote:

Sorry, mixed up the topic. Corrected extractContents is above. I didn't test this, so I'm not 100% sure that the interface generator doesn't try to access the body as a JSON object, but if it does, that would at least be easily fixable.

Seems like the return type of the before hook needs to match the type of the parameter. Otherwise I get this compile error:

../../../../.dub/packages/vibe-d-0.7.30-alpha.3/vibe-d/source/vibe/web/rest.d(970,7): Error: template std.typecons.Nullable!(int[]).Nullable.opAssign cannot deduce function from argument types !()(string), candidates are:
~/.dvm/compilers/dmd-2.071.1/osx/bin/../../src/phobos/std/typecons.d(2039,10):        std.typecons.Nullable!(int[]).Nullable.opAssign()(T value)
../../../../.dub/packages/vibe-d-0.7.30-alpha.3/vibe-d/source/vibe/web/rest.d(99,45): Error: template instance vibe.web.rest.jsonMethodHandler!(foobar, 0LU, FoobarController) error instantiating
source/Application.d(62,37):        instantiated from here: registerRestInterface!(FoobarController)
source/Application.d(27,34):        instantiated from here: registerRestInterface!(FoobarController)
source/app.d(10,16):        instantiated from here: registerController!(FoobarController)
../../../../.dub/packages/vibe-d-0.7.30-alpha.3/vibe-d/source/vibe/web/rest.d(101,37): Error: forward reference to inferred return type of function call 'filter!((p) => p.kind != ParameterKind.internal)(route.parameters)'
../../../../.dub/packages/vibe-d-0.7.30-alpha.3/vibe-d/source/vibe/web/rest.d(107,62): Error: forward reference to inferred return type of function call 'filter!((rs) => rs.all!((r) => r.method != HTTPMethod.OPTIONS))(intf.getRoutesGroupedByPattern())'

Ideally I need a more generic approach, something that works for all parameter for all rest interfaces that are registered. Not sure if it's possible to use meta programming to generate some code for that.