RejectedSoftware Forums

Sign up

Pages: 1 2

REST API return non-JSON data.

I am trying to implement a simple REST API that returns some binary data to a user (it could be BSON format or just the RAW binary data).

Say I define the following interface:

@getRootPathFromName
interface MyAPI
{
    @path("getdata") @method(HTTPMethod.GET)
    ubyte[] getData();
}

class MyImpl : MyAPI
{
    override ubyte[] getData() {
       ubyte[] the_data;
       the_data ~= 1;
       the_data ~= 2;
       the_data ~= 3;
       return the_data;
    }
}

Running code like this returns the text '[1,2,3]' in JSON format. If I want to send the binary data (or perhaps a file - say .png or .jpg) how could I handle this.

Re: REST API return non-JSON data.

On Thu, 15 Aug 2013 20:27:11 GMT, Craig Dillabaugh wrote:

I am trying to implement a simple REST API that returns some binary data to a user (it could be BSON format or just the RAW binary data).

Say I define the following interface:

@getRootPathFromName
interface MyAPI
{
    @path("getdata") @method(HTTPMethod.GET)
    ubyte[] getData();
}

class MyImpl : MyAPI
{
    override ubyte[] getData() {
       ubyte[] the_data;
       the_data ~= 1;
       the_data ~= 2;
       the_data ~= 3;
       return the_data;
    }
}

Running code like this returns the text '[1,2,3]' in JSON format. If I want to send the binary data (or perhaps a file - say .png or .jpg) how could I handle this.

So I guess this was a dumb question :o)

Re: REST API return non-JSON data.

On Sat, 17 Aug 2013 19:52:03 GMT, Craig Dillabaugh wrote:

On Thu, 15 Aug 2013 20:27:11 GMT, Craig Dillabaugh wrote:

I am trying to implement a simple REST API that returns some binary data to a user (it could be BSON format or just the RAW binary data).

Say I define the following interface:

@getRootPathFromName
interface MyAPI
{
    @path("getdata") @method(HTTPMethod.GET)
    ubyte[] getData();
}

class MyImpl : MyAPI
{
    override ubyte[] getData() {
       ubyte[] the_data;
       the_data ~= 1;
       the_data ~= 2;
       the_data ~= 3;
       return the_data;
    }
}

Running code like this returns the text '[1,2,3]' in JSON format. If I want to send the binary data (or perhaps a file - say .png or .jpg) how could I handle this.

So I guess this was a dumb question :o)

Not at all ;) Sorry, I'm currently struggling a bit keeping up with the forums and e-mail messages.

So the short answer is: This is not possible using the REST interface generator. A manual route would have to be registered in the URLRouter and a custom HTTP request needs to be constructed on the client side. Those would then work alongside MyAPI.

However, I think this is common enough to warrant direct support in the REST generator. How about recognizing a method signature of the form void method(..., OutputStream, ...). The REST server would then directly write the response to that stream and the client would pass the contents of the bodyReader to the caller. The "Content-Type" could for example be defined using a @uda.

Any other ideas? I'd prefer a stream based solution to be on the safe side regarding big responses and to be able to avoid allocations if necessary, but maybe a @uda could also be used to support ubyte[] return types for achieving the same result.

Re: REST API return non-JSON data.

On Sun, 18 Aug 2013 06:37:38 GMT, Sönke Ludwig wrote:

On Sat, 17 Aug 2013 19:52:03 GMT, Craig Dillabaugh wrote:

On Thu, 15 Aug 2013 20:27:11 GMT, Craig Dillabaugh wrote:

I am trying to implement a simple REST API that returns some binary data to a user (it could be BSON format or just the RAW binary data).

Say I define the following interface:

@getRootPathFromName
interface MyAPI
{
    @path("getdata") @method(HTTPMethod.GET)
    ubyte[] getData();
}

class MyImpl : MyAPI
{
    override ubyte[] getData() {
       ubyte[] the_data;
       the_data ~= 1;
       the_data ~= 2;
       the_data ~= 3;
       return the_data;
    }
}

Running code like this returns the text '[1,2,3]' in JSON format. If I want to send the binary data (or perhaps a file - say .png or .jpg) how could I handle this.

So I guess this was a dumb question :o)

Not at all ;) Sorry, I'm currently struggling a bit keeping up with the forums and e-mail messages.

So the short answer is: This is not possible using the REST interface generator. A manual route would have to be registered in the URLRouter and a custom HTTP request needs to be constructed on the client side. Those would then work alongside MyAPI.

However, I think this is common enough to warrant direct support in the REST generator. How about recognizing a method signature of the form void method(..., OutputStream, ...). The REST server would then directly write the response to that stream and the client would pass the contents of the bodyReader to the caller. The "Content-Type" could for example be defined using a @uda.

Any other ideas? I'd prefer a stream based solution to be on the safe side regarding big responses and to be able to avoid allocations if necessary, but maybe a @uda could also be used to support ubyte[] return types for achieving the same result.

I thought I had already replied to this already, but since I see nothing on the form I will try again.

I am quite new to web-app develpment and UDAs so I am not sure how helpful my comments on the proposal will be, but I like the general idea. The solution you propose is close to what I 'expected' to happen so I guess that is a good sign. I doubt there are many web-applications where a raw binary array is the expected by the client, so I think the OutputStream based solution makes sense.

Just curious, when you say the 'client' would pass the contents of the 'bodyReader' to the caller, what does that mean? (in my thinking client == caller).

Re: REST API return non-JSON data.

I need to warn that this is a very delicate thing if you consider REST interface client. Currently you are guaranteed to have 100% working client-server pair if those use same interface definition. If application will be allowed to use custom serialization format not deducible from interface definition, this guarantee will perish and manual parsing will be needed at client, as well as integrity control.

This is quite a feature to lose.

Re: REST API return non-JSON data.

On Tue, 20 Aug 2013 02:22:09 GMT, Dicebot wrote:

I need to warn that this is a very delicate thing if you consider REST interface client. Currently you are guaranteed to have 100% working client-server pair if those use same interface definition. If application will be allowed to use custom serialization format not deducible from interface definition, this guarantee will perish and manual parsing will be needed at client, as well as integrity control.

This is quite a feature to lose.

(Asumming you mean the OutputStream suggestion:) Think of it as a single ubyte[] return value. What's stored inside that array is up to the API implementor and using an OutputStream doesn't make a difference there. The wire protocol will still be well-defined, but just use binary data instead of JSON in that case. I think it's actually a quite common requirement to be able to transfer raw file contents (not necessarily from an actual file, tough). So at least we should find some solution here.

Re: REST API return non-JSON data.

On Mon, 19 Aug 2013 19:24:32 GMT, Craig Dillabaugh wrote:

Just curious, when you say the 'client' would pass the contents of the 'bodyReader' to the caller, what does that mean? (in my thinking client == caller).

I just mean that the RestInterfaceClient would create a stub method similar to this:

void performOperationWithBinaryResult(OutputStream out, int some_parameter, int some_other_parameter)
{
    auto res = requestHTTP(...);
    out.write(res.bodyReader);
}

So the HTTP response body is written verbatim to the output stream that was passed by the user code to the method.

Re: REST API return non-JSON data.

On Tue, 20 Aug 2013 06:59:37 GMT, Sönke Ludwig wrote:

(Asumming you mean the OutputStream suggestion:) Think of it as a single ubyte[] return value. What's stored inside that array is up to the API implementor and using an OutputStream doesn't make a difference there. The wire protocol will still be well-defined, but just use binary data instead of JSON in that case. I think it's actually a quite common requirement to be able to transfer raw file contents (not necessarily from an actual file, tough). So at least we should find some solution here.

I think it is worth requiring explicit UDA annotation, something like @rawResponse - it will both make interface more clear to the reader and help client generator to verify that it is not misused (so far REST module does not rely on any extra user code to work properly and I think it is worth keeping). Once you start going the declarative way, no reasons to stop in the middle.

Re: REST API return non-JSON data.

On Tue, 20 Aug 2013 19:10:38 GMT, Dicebot wrote:

On Tue, 20 Aug 2013 06:59:37 GMT, Sönke Ludwig wrote:

(Asumming you mean the OutputStream suggestion:) Think of it as a single ubyte[] return value. What's stored inside that array is up to the API implementor and using an OutputStream doesn't make a difference there. The wire protocol will still be well-defined, but just use binary data instead of JSON in that case. I think it's actually a quite common requirement to be able to transfer raw file contents (not necessarily from an actual file, tough). So at least we should find some solution here.

I think it is worth requiring explicit UDA annotation, something like @rawResponse - it will both make interface more clear to the reader and help client generator to verify that it is not misused (so far REST module does not rely on any extra user code to work properly and I think it is worth keeping). Once you start going the declarative way, no reasons to stop in the middle.

Agreed, this makes it much clearer than just inferring it.

Re: REST API return non-JSON data.

I'm wondering if this ending up getting anywhere? I don't see it in the current documentation.

On Tue, 20 Aug 2013 19:30:31 GMT, Sönke Ludwig wrote:

On Tue, 20 Aug 2013 19:10:38 GMT, Dicebot wrote:

On Tue, 20 Aug 2013 06:59:37 GMT, Sönke Ludwig wrote:

(Asumming you mean the OutputStream suggestion:) Think of it as a single ubyte[] return value. What's stored inside that array is up to the API implementor and using an OutputStream doesn't make a difference there. The wire protocol will still be well-defined, but just use binary data instead of JSON in that case. I think it's actually a quite common requirement to be able to transfer raw file contents (not necessarily from an actual file, tough). So at least we should find some solution here.

I think it is worth requiring explicit UDA annotation, something like @rawResponse - it will both make interface more clear to the reader and help client generator to verify that it is not misused (so far REST module does not rely on any extra user code to work properly and I think it is worth keeping). Once you start going the declarative way, no reasons to stop in the middle.

Agreed, this makes it much clearer than just inferring it.

Pages: 1 2