users@jersey.java.net

[Jersey] Re: Jersey 2.x accepts requests with unspecified content type and empty body.

From: Koper, Dies <diesk_at_fast.au.fujitsu.com>
Date: Mon, 23 Sep 2013 15:12:14 +1000

Hi P.,

I'm not a Jersey developer but I'm not sure the behaviour is incompliant.

The javadoc for @Consumes says:
Defines the media types that the methods of a resource class or MessageBodyReader can accept.
(...)
A container is responsible for ensuring that the method invoked is capable of consuming the media type of the HTTP request entity body.
https://jsr311.java.net/nonav/javadoc/javax/ws/rs/Consumes.html

Also, the HTTP spec talks about what the server should do when no Content-Type is specified in the request:

If and only if the media type is not given by a Content-Type field, the recipient MAY attempt to guess the media type via inspection of its content and/or the name extension(s) of the URI used to identify the resource.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html

And according to the JSON spec a JSON text cannot be empty:

   JSON-text = object / array
(...)
An object structure is represented as a pair of curly brackets
   surrounding zero or more name/value pairs (or members).
(...)
   An array structure is represented as square brackets surrounding zero
   or more values (or elements).
http://www.ietf.org/rfc/rfc4627.txt

So the container receives a request with an empty body and no content type.
The container could try hard to guess the media type via inspection of the content and conclude that according to the JSON RFC, no content is not valid JSON text.
In that case it should not invoke your method. But rfc2616 doesn't say it MUST try hard. Maybe it tried only a little (i.e. check whether it's text vs. binary), and instead only look at your method arguments and leave it to the method implementation to determine the body's media type.
Your resource method signature indicates that it is capable of consuming an empty body (argument MyData is nullable, and there is no @NotNull validation constraint on it to say otherwise), so it invokes it, relying on your implementation (which claims it can only accept JSON) to check and complain.

Regards,
Dies Koper


-----Original Message-----
From: TheCuriousOne_at_centrum.cz [mailto:TheCuriousOne_at_centrum.cz]
Sent: Sunday, September 22, 2013 3:58 PM
To: users_at_jersey.java.net
Subject: [Jersey] Re: Jersey 2.x accepts requests with unspecified content type and empty body.

Yes, perhaps you did not read my original email, which specifically said that the "Content-Type" header field is not specified. The "Accept: */*" header field simply means that the client does not care about the format of the body of the response, which is unrelated to this issue.

Anyway, to put it maybe more clearly: the resource MyResource.foo expects a valid JSON-encoded object of MyData class in the request body, but this contract is clearly being violated here (the body is empty and the 'myData' parameter is set to null). And even if you do not acknowledge it as a bug, there is an inconsistent behavior: if I set the "Content-Type" header field to any value and leave the body empty, the request is (correctly) rejected (MyResource.foo is not called); if I do not specify the "Content-Type" and leave the body empty, the request is (incorrectly) not rejected (MyResource.foo is called with the 'myData' parameter being null).

Hopefully the developers DO acknowledge this as a bug (or perhaps tell me what I'm doing wrong), otherwise all of my resources would have to be littered with "if (myArg != null) { ... }", which would be ridiculous.

P.

______________________________________________________________
> Od: "Ted M. Young [@jitterted]" <tedyoung_at_gmail.com>
> Komu: "users_at_jersey.java.net" <users_at_jersey.java.net>
> Datum: 22.09.2013 02:06
> Předmět: [Jersey] Re: Jersey 2.x accepts requests with unspecified content type and empty body.
>
>In the log you posted in that Gist, curl is sending
>
>Accept: */*
>
>Which means that it'll accept anything. This is not the same as
>"unspecified", which would be *no* Accept header. So, that's still acting
>as I would expect. Perhaps I'm not understanding what you're actually
>getting vs. what you're expecting?
>
>;ted
>
>
>
>On Sat, Sep 21, 2013 at 12:09 AM, <TheCuriousOne_at_centrum.cz> wrote:
>
>> Sure, this is the case when MyResource.foo is called (the server prints
>> "MyResource.foo" to stderr) even though it should not be [1]. In case I
>> specify the Content-Type, it works as expected (either the request is
>> rejected based on the content type or based on the body being malformed
>> (even when it's empty)).
>>
>> [1]: https://gist.github.com/anonymous/1e5c2dd49dc703d9b089
>>
>> Cheers,
>> P.
>>
>> ______________________________________________________________
>> > Od: "Ted M. Young [@jitterted]" <tedyoung_at_gmail.com>
>> > Komu: "users_at_jersey.java.net" <users_at_jersey.java.net>
>> > Datum: 20.09.2013 19:42
>> > Předmět: [Jersey] Re: Jersey 2.x accepts requests with unspecified
>> content type and empty body.
>> >
>> >I tried your Gist and I get the expected 415 Unsupported Media Type when I
>> >do an empty POST with no content type specified. When I add the
>> >Content-Type: application/json, it calls the method, also as expected. How
>> >are you testing this?
>> >
>> >;ted
>> >--
>> >http://about.me/tedmyoung
>> >
>> >
>> >
>> >On Fri, Sep 20, 2013 at 8:01 AM, <TheCuriousOne_at_centrum.cz> wrote:
>> >
>> >> Hi, this might be a bug (or I might be doing something wrong), but
>> Jersey
>> >> accepts requests where the content type is not specified (even though
>> the
>> >> resource is annotated with @Consumes(MediaType.APPLICATION_JSON)) and
>> whose
>> >> body is empty (even though the resource expects non-empty JSON body).
>> Here
>> >> is a minimal example (replace "_" with "/" in the file names, compile
>> using
>> >> "mvn clean install exec:java"):
>> >> https://gist.github.com/anonymous/8c0426646c334cecda50
>> >>
>> >> Cheers,
>> >> P.
>> >>
>> >
>>
>