We're using the Jersey reference implementation of Jax-RS. The Jax-RS client implementation of Jersey is appending a default accept header to the request if no accept header is specified. The default accept header looks like this:
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
As you can see, it uses a single asterisk '*' as content-type (after image/jpeg).
In the Jax-RS spec (see here), this single * is defined as
/**
* The value of a type or subtype wildcard {@value #MEDIA_TYPE_WILDCARD}.
*/
public static final String MEDIA_TYPE_WILDCARD = "*";
which I interpret as "wildcard for any media type"
The '*/*' is defined as
/**
* A {@code String} constant representing wildcard {@value #WILDCARD} media type .
*/
public final static String WILDCARD = "*/*";
which I interpret as "wildcard for any media range"
However, the HTTP spec (RFC7231) does not mention an "any media type" wildcard, only media-range wildcards:
media-range = ( "*/*"
/ ( type "/" "*" )
/ ( type "/" subtype )
) *( OWS ";" OWS parameter )
(..)
The asterisk "*" character is used to group media types into ranges,
with "*/*" indicating all media types and "type/*" indicating all
subtypes of that type. The media-range can include media type
parameters that are applicable to that range.
Which I interpret as allowed content-types:
in other words, the content type has to be always of the form "something slash something" or "a single * is not a valid content type". Although, the latter is not explicitly stated.
Now both specs are publicly standardized, with the HTTP spec being somewhat the parent document to the Jax-RS spec as Jax-RS is based on HTTP. IMHO both standards contradict each other regarding the wildcard content types.
Question is, what is applicable?
While dealing with Jsoup (not JaxRS/Jersey), I observed, that JSoup is using the same default accept types and it seems, the default headers are an implementation detail of the sun.net.www.protocol.http.HttpURLConnection
static final String acceptString = "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2";
So in case this is a bug, it's not a bug in Jersey, but Java's HttpURLConnection
You say:
which I interpret as "wildcard for any media type"
I think that is incorrect. It is a wildcard for type or subtype. The wildcard for any media type is defined as */*
, like in the HTTP spec.
Also, when in doubt, follow the HTTP spec. In the end, that is the communication protocol you are using. The other party might not know about the Jax-RS spec.
It seems to be a problem with the Jersey client library/code.
Looking through the JAX-RS specification at
https://download.oracle.com/otn-pub/jcp/jaxrs-2_0-fr-eval-spec/jsr339-jaxrs-2.0-final-spec.pdf?AuthParam=1542959568_b3be8ccd614accaf7749ade85e6ebf67
, I could not find any explicit mention of supporting a media type * . It explicitly mentions supported media types like "n/m" where m could be * or n and m could be *, but only * is nowhere mentioned.
A quote from the document:
First, let us define the client media type and the server media type as those denoted by the Accept header in a request and the @Produces annotation on a resource method, respectively. Let a client media type be of the form n/m;q=v1, a server media type be of the form n/m;qs=v2 and a combined media type of the form n/m;q=v1;qs=v2;d=v3, where the distance factor d is defined below. For any of these types, m could be ∗, or m and n could be ∗ and the values of q and qs are assumed to be 1.0 if absent
Thus, I believe there is something wrong with the Jersey client API which creates the default Accept header when there is no explicit one provided and sets its value to the one which you have mentioned, i.e.
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Also, just to add here, the JAX-RS specification, mentions this:
(a) Filter M by removing members that do not meet the following criteria:
• The request method is supported. If no methods support the request method an implementation
MUST generate a NotAllowedException (405 status) and no entity. Note the
additional support for HEAD and OPTIONS described in Section 3.3.5.
• The media type of the request entity body (if any) is a supported input data format (see Section
3.5). If no methods support the media type of the request entity body an implementation
MUST generate a NotSupportedException (415 status) and no entity.
• At least one of the acceptable response entity body media types is a supported output data
format (see Section 3.5). If no methods support one of the acceptable response entity body
media types an implementation MUST generate a NotAcceptableException (406 status)
and no entity
Thus, 406 HTTP code would be appropriate if the requested media type (in Accept header) cannot be matched with any server supported methods' response media types.
However, in your case, there are various media types specified in the request including the generic one which supports all media types, so throwing an error wouldn't be the right thing to do, even though * is not exactly a correct media type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With