RejectedSoftware Forums

Sign up

Handling body of a POST request

Hello all,

I'm playing with the REST interface functionality of vibe.d and have got stuck on what seems like a simple problem: to create a POST request where the server returns back the data contained in the body of the POST request itself.

However, I always wind up with 400 Bad Request errors, with the claim that the request body does not contain a valid JSON value.

Here's my interface and implementation:

interface MyRestInterface
{
    string post (string data);
}

class MyRestImplementation : MyRestInterface
{
    string post (string data)
    {
        if (data is null) return "hello!";
        return data ~ data;
    }
}

and then in my main function:

auto myRestInterface = new MyRestImplementation;

auto router = new URLRouter;
registerRestInterface(router, myRestInterface);

auto settings = new HTTPServerSettings;
settings.port = httpPort;
settings.bindAddresses = ["::1", "127.0.0.1"];
listenHTTP(settings, router);

Sample behaviour when trying to send a POST request using curl:

$ curl -d @post-body.txt http://localhost:8080/
400 - Bad Request

The request body does not contain a valid JSON value.

Internal error information:
vibe.http.common.HTTPStatusException@../../../../.dub/packages/vibe-d-0.7.29/source/vibe/web/rest.d(913): The request body does not contain a valid JSON value.
----------------josephcurl --trace - -d @post-body.txt http://localhost:8080/
== Info:   Trying 127.0.0.1...
== Info: Connected to localhost (127.0.0.1) port 8080 (#0)
=> Send header, 148 bytes (0x94)
0000: 50 4f 53 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d POST / HTTP/1.1.
0010: 0a 48 6f 73 74 3a 20 6c 6f 63 61 6c 68 6f 73 74 .Host: localhost
0020: 3a 38 30 38 30 0d 0a 55 73 65 72 2d 41 67 65 6e :8080..User-Agen
0030: 74 3a 20 63 75 72 6c 2f 37 2e 34 37 2e 30 0d 0a t: curl/7.47.0..
0040: 41 63 63 65 70 74 3a 20 2a 2f 2a 0d 0a 43 6f 6e Accept: */*..Con
0050: 74 65 6e 74 2d 4c 65 6e 67 74 68 3a 20 31 39 0d tent-Length: 19.
0060: 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 61 .Content-Type: a
0070: 70 70 6c 69 63 61 74 69 6f 6e 2f 78 2d 77 77 77 pplication/x-www
0080: 2d 66 6f 72 6d 2d 75 72 6c 65 6e 63 6f 64 65 64 -form-urlencoded
0090: 0d 0a 0d 0a                                     ....
=> Send data, 19 bytes (0x13)
0000: 7b 22 64 61 74 61 22 20 3a 20 22 74 68 65 72 65 {"data" : "there
0010: 22 20 7d                                        " }
== Info: upload completely sent off: 19 out of 19 bytes
<= Recv header, 26 bytes (0x1a)
0000: 48 54 54 50 2f 31 2e 31 20 34 30 30 20 42 61 64 HTTP/1.1 400 Bad
0010: 20 52 65 71 75 65 73 74 0d 0a                    Request..
<= Recv header, 23 bytes (0x17)
0000: 53 65 72 76 65 72 3a 20 76 69 62 65 2e 64 2f 30 Server: vibe.d/0
0010: 2e 37 2e 32 39 0d 0a                            .7.29..
<= Recv header, 37 bytes (0x25)
0000: 44 61 74 65 3a 20 54 75 65 2c 20 30 39 20 41 75 Date: Tue, 09 Au
0010: 67 20 32 30 31 36 20 31 31 3a 32 30 3a 34 35 20 g 2016 11:20:45 
0020: 47 4d 54 0d 0a                                  GMT..
<= Recv header, 24 bytes (0x18)
0000: 4b 65 65 70 2d 41 6c 69 76 65 3a 20 74 69 6d 65 Keep-Alive: time
0010: 6f 75 74 3d 31 30 0d 0a                         out=10..
<= Recv header, 41 bytes (0x29)
0000: 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 74 65 Content-Type: te
0010: 78 74 2f 70 6c 61 69 6e 3b 20 63 68 61 72 73 65 xt/plain; charse
0020: 74 3d 55 54 46 2d 38 0d 0a                      t=UTF-8..
<= Recv header, 21 bytes (0x15)
0000: 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 3a 20 Content-Length: 
0010: 32 37 38 0d 0a                                  278..
<= Recv header, 2 bytes (0x2)
0000: 0d 0a                                           ..
<= Recv data, 278 bytes (0x116)
0000: 34 30 30 20 2d 20 42 61 64 20 52 65 71 75 65 73 400 - Bad Reques
0010: 74 0a 0a 54 68 65 20 72 65 71 75 65 73 74 20 62 t..The request b
0020: 6f 64 79 20 64 6f 65 73 20 6e 6f 74 20 63 6f 6e ody does not con
0030: 74 61 69 6e 20 61 20 76 61 6c 69 64 20 4a 53 4f tain a valid JSO
0040: 4e 20 76 61 6c 75 65 2e 0a 0a 49 6e 74 65 72 6e N value...Intern
0050: 61 6c 20 65 72 72 6f 72 20 69 6e 66 6f 72 6d 61 al error informa
0060: 74 69 6f 6e 3a 0a 76 69 62 65 2e 68 74 74 70 2e tion:.vibe.http.
0070: 63 6f 6d 6d 6f 6e 2e 48 54 54 50 53 74 61 74 75 common.HTTPStatu
0080: 73 45 78 63 65 70 74 69 6f 6e 40 2e 2e 2f 2e 2e sException@../..
0090: 2f 2e 2e 2f 2e 2e 2f 2e 64 75 62 2f 70 61 63 6b /../../.dub/pack
00a0: 61 67 65 73 2f 76 69 62 65 2d 64 2d 30 2e 37 2e ages/vibe-d-0.7.
00b0: 32 39 2f 73 6f 75 72 63 65 2f 76 69 62 65 2f 77 29/source/vibe/w
00c0: 65 62 2f 72 65 73 74 2e 64 28 39 31 33 29 3a 20 eb/rest.d(913): 
00d0: 54 68 65 20 72 65 71 75 65 73 74 20 62 6f 64 79 The request body
00e0: 20 64 6f 65 73 20 6e 6f 74 20 63 6f 6e 74 61 69  does not contai
00f0: 6e 20 61 20 76 61 6c 69 64 20 4a 53 4f 4e 20 76 n a valid JSON v
0100: 61 6c 75 65 2e 0a 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d alue..----------
0110: 2d 2d 2d 2d 2d 2d                               ------
400 - Bad Request

The request body does not contain a valid JSON value.

Internal error information:
vibe.http.common.HTTPStatusException@../../../../.dub/packages/vibe-d-0.7.29/source/vibe/web/rest.d(913): The request body does not contain a valid JSON value.
----------------== Info: Connection #0 to host localhost left intact

I'm feeling a bit baffled about what is expected here, so could someone shed light on what I'm doing wrong?

N.B. what I'd really like is to be able to avoid JSON (de)serialization entirely and for the REST API to just hand over the post body directly to the handling method, but IIUC the design is currently tied to JSON ... ?

Thanks in advance for any advice. I imagine this is just new user misunderstanding kind of stuff ... ? :-P

Best wishes,

-- Joe

Re: Handling body of a POST request

On Tue, 09 Aug 2016 11:25:00 GMT, Joseph Rushton Wakeling wrote:

Hello all,

... damn, what went wrong with the code posting above? :-(

Re: Handling body of a POST request

On 8/9/16 7:25 AM, Joseph Rushton Wakeling wrote:

Hello all,

I'm playing with the REST interface functionality of vibe.d and have got stuck on what seems like a simple problem: to create a POST request where the server returns back the data contained in the body of the POST request itself.

However, I always wind up with 400 Bad Request errors, with the claim that the request body does not contain a valid JSON value.

Here's my interface and implementation:

interface MyRestInterface
{
    string post (string data);
}

class MyRestImplementation : MyRestInterface
{
    string post (string data)
    {
        if (data is null) return "hello!";
        return data ~ data;
    }
}

and then in my main function:

auto myRestInterface = new MyRestImplementation;

auto router = new URLRouter;
registerRestInterface(router, myRestInterface);

auto settings = new HTTPServerSettings;
settings.port = httpPort;
settings.bindAddresses = ["::1", "127.0.0.1"];
listenHTTP(settings, router);

Sample behaviour when trying to send a POST request using curl:

[snip]

I'm feeling a bit baffled about what is expected here, so could someone shed light on what I'm doing wrong?

I'm not familiar with curl command line. But when I was testing rest
interface, I did it with wget, and you need to add the Content-Type
header. If you notice in your request, the content-type is
"application/x-www-form-urlencoded". Here is what I'd pass using wget:

wget --header=Content-Type:application/json --post-data='{"data":
"there"}' http://localhost:8080/

I'm sure curl supports a similar thing.

N.B. what I'd really like is to be able to avoid JSON (de)serialization entirely and for the REST API to just hand over the post body directly to the handling method, but IIUC the design is currently tied to JSON ... ?

You can use registerWebInterface, and then process the data directly
from HTTPServerRequest parameter. As far as I know, if you want to use
registerRestInterface, you have to play by those rules (Json only). I
have crappy parts of my code where I have to register both a rest
interface for the normal data, and then register web interface when I
want to do something out of the ordinary (including streaming back Json
data!). You may be able to use a @before or @after attribute to process
the data differently.

I'm also just getting into vibe.d, so take my advice with a grain of
salt, maybe there is a way :)

-Steve

Re: Handling body of a POST request

On Tue, 9 Aug 2016 08:19:10 -0400, Steven Schveighoffer wrote:

I'm not familiar with curl command line. But when I was testing rest
interface, I did it with wget, and you need to add the Content-Type
header. If you notice in your request, the content-type is
"application/x-www-form-urlencoded". Here is what I'd pass using wget:

wget --header=Content-Type:application/json --post-data='{"data":
"there"}' http://localhost:8080/

I'm sure curl supports a similar thing.

Oh, nicely spotted. That's exactly what was wrong; using curl's -H "Content-Type: application/json" option means that suddenly vibe.d is happy and full of beans.

You can use registerWebInterface, and then process the data directly
from HTTPServerRequest parameter. As far as I know, if you want to use
registerRestInterface, you have to play by those rules (Json only). I
have crappy parts of my code where I have to register both a rest
interface for the normal data, and then register web interface when I
want to do something out of the ordinary (including streaming back Json
data!). You may be able to use a @before or @after attribute to process
the data differently.

Oh, nice. I've been working through Kai Nacke's book, but jumped straight to the REST chapter -- ironically, if I'd read the preceding chapter, I'd have already known about the raw web interfaces ...

I'm also just getting into vibe.d, so take my advice with a grain of
salt, maybe there is a way :)

Well, you're at least one step ahead of me and your advice seems good so far ... :-)

BTW apologies for lack of post-DConf follow-up -- I owe you an email one of these days ;-) Hope all is good with you in the meanwhile!

Thanks & best wishes,

-- Joe

Re: Handling body of a POST request

On 8/9/16 7:26 AM, Joseph Rushton Wakeling wrote:

On Tue, 09 Aug 2016 11:25:00 GMT, Joseph Rushton Wakeling wrote:

Hello all,

... damn, what went wrong with the code posting above? :-(

Just FYI, looked great on my NNTP reader :) But looking at it in the
forum, not so much...

-Steve