Hi Aki
Re your tests below: can you clarify please how the JAX-RS method is
configured, what @Consumes it has ? And what do you mean sporadically ?
I appreciate you spending time on it :-), it is better that we have
total understanding of what is going on in these cases.
That said I'm not sure what exactly you are trying to suggest.
As I said that if we do not set any CT at all with the empty payloads
then we have various side-effects when HTTPUrlConnection is used, in
particular:
- if it is empty POST (or PUT as you confirmed) HTTPUrlConnection
defaults to a form content-type which IMHO is wrong
- I've linked to a JIRA that was reported against CXF dropping
Content-Type which was causing side-effects when GET was going via HTTP
proxy
So to avoid all of this CXF puts */* for empty requests. As you rightly
observed most of real world services would not even bother about
checking this CT for GET. Except for SpringBoot-powered services.
Let me even criticize SpringBoot here: while CXF sending a redundant and
arguably bogus CT with GET is not needed for HTTP but prely a workaround
against HTTPUrlConnection issues, an HTTP server that rejects a request
because a header that is not needed for processing this request is
apparently invalid is anti-HTTP because the WEB processing is, among
other things, about ignoring HTTP properties that are not relevant for
processing a given request.
So now we let people:
- configure CXF to drop CT no matter what
- override */* CT
If we have an empty request then not setting CT by default with
HTTPUrlConnection causes more side-effects than adding CT */*.
And indeed, now, if we have an empty POST and we know the target server
accepts empty and non-empty text/xml requests then it is only natural
that a user would set manually text/xml or application/json - so where
is the problem ?
The situation with HTTP proxy + GET where CT is dropped (see JIRA) is a
blocker IMHO. Can you please look at the JIRA I linked to and try to
confirm it is a problem in your set-up, if not then I'll ask Alexey to
help with double-checking it again in his set up and then we continue
narrowing it down. OK ?
Thanks, Sergey
On 20/08/15 11:01, Aki Yoshida wrote:
Hi Sergey,
maybe the original issue has some other cause. After running some
tests (starting an JAXRS endpoint and invoking it over POST with an
empty content), I am observing sporadically a strange issue at the
server that the server think the call is for parameter.getType() is
FORM. The wire message looks always the same as shown below (shown the
inbound messages logged at the server). But sporadically
JAXRSUtils#processParameter gets called with parameter whose type is
FORM somehow. And when this happens, the missing content type or some
non matching content type like plain/text leads to
javax.ws.rs.NotSupportedException: HTTP 415 Unsupported Media Type. In
contrast, this method is most of the time called with REQUEST_BODY.
This has something do with some issue in setting up the endpoint and
it sporadically fails to get setup correctly. Even in that case, the
other calls are fine but those with an empty body will suffer when it
doesn't carry the appropriate content-type value because the server
wrongly assumes the message type.
The message suffers looks like this.
Address: http://localhost:8282/endpoint/map/11foo
Encoding: ISO-8859-1
Http-Method: POST
Content-Type: text/plain
Headers: {Accept=[text/plain], Cache-Control=[no-cache],
connection=[keep-alive], Content-Length=[0],
content-type=[text/plain], Host=[localhost:8282], Pragma=[no-cache],
User-Agent=[Apache CXF
3.1.3-SNAPSHOT-ae95e49c500b529236732a14c86b4c9e100ac143]}
In contrast, when the request has the content-type: */*, it does not
suffer this issue because its type is not rejected by the FORM
processing.
Address: http://localhost:8282/endpoint/map/11foo
Encoding: ISO-8859-1
Http-Method: POST
Content-Type: */*
Headers: {Accept=[text/plain], Cache-Control=[no-cache],
connection=[keep-alive], Content-Length=[0], content-type=[*/*],
Host=[localhost:8282], Pragma=[no-cache], User-Agent=[Apache CXF
3.1.3-SNAPSHOT-ae95e49c500b529236732a14c86b4c9e100ac143]}
So, I think when we find out why sporadically the endpoint is wrongly
started and fix it, we can avoid sending the bogus content-type for
the empty payload.
regards, aki
2015-08-13 19:23 GMT+02:00 Aki Yoshida <[email protected]>:
Hi Sergey,
thanks.
Yes we have a proxy.
I'll check it against our proxy tomorrow.
regards, aki
2015-08-13 14:27 GMT+02:00 Sergey Beryozkin <[email protected]>:
Hi,
We've talked a bit more about it with Aki where we indeed came to a shared
understanding it was a workaround specifically around some HttpUrlConnection
issues.
I've added a new property "set.content.type.for.empty.request" that (in case
of the default conduit) can be set to false, is enabled by default
otherwise.
I'm hoping that eventually we can have this property disabled by default
over time. See CXF-6528.
Aki, do you have an HTTP proxy setup in your office somewhere ? May be you
can double check if GET with custom Accept is affected or not with
"set.content.type.for.empty.request" set to false ?
Thanks, Sergey
On 11/08/15 15:02, Aki Yoshida wrote:
Hi Sergey,
*/* may appear somewhere where the media-type is specified, but this
value still appears to violate the BNF rules given for the
Content-Type header.
http://tools.ietf.org/html/rfc2045#section-5.1
So, I still think it is actually wrong to set the content-type header
with */*, no?
regards, aki
2015-08-11 12:25 GMT+02:00 Sergey Beryozkin <[email protected]>:
Hi Aki
On 11/08/15 10:14, Aki Yoshida wrote:
HI Sergey,
it could be that the problem had something to do with the proxy's
configuration and not really a bug? Not related to this content-type
issue, we had a similar misconfiguration in the forwarding rule (e.g.,
it was letting only "Upgrade" accepted but not "upgrade") that
prevented some clients e.g., IE from opening a websocket through it.
;-)
Well, I'm not sure, one thing is definite is that setting a wildcard
Content-Type helped to solve the strange Accept replacement bug. As I
said
even without a proxy if it empty POST then a form payload is added. I
think
in that the case the target server had @Produces (text/xml) or json and
the
net effect was that the runtime returned the error due to media type
mismatches.
The problem is not a wildcard but the actual redundant use of
Content-Type.
It is not an http consumer issue, ie. why Spring bother parsing
Content-Type
for GET ?
Regarding the use of value */* for the content-type header , isn't
this value syntactically invalid?
Not at all, */* is a valid media type. The Spring error is arguable
because
the more friendly server can assume instead that */* is equivalent to CT
missing and then defaulting to some type as in JAX-RS servers.
There is something interesting in the following section of the MIME
spec.
http://tools.ietf.org/html/rfc2045#section-5.2
----
Default RFC 822 messages without a MIME Content-Type header are taken
by this protocol to be plain text in the US-ASCII character set,
which can be explicitly specified as:
Content-type: text/plain; charset=us-ascii
This default is assumed if no Content-Type header field is specified.
It is also recommend that this default be assumed when a
syntactically invalid Content-Type header field is encountered.
...
----
That means, we could also use "Content-type: text/plain;
charset=us-ascii" instead of the no content-type to have the same
effect or overwrite the default value with some valid content type.
Interestingly, the last sentence recommends the server to accept a
syntactically invalid type like */* and assume the default text/plain
ascii type. But it is only recommended and not required.
I'm not sure we should use text/plain for GETs :-) as a workaround. */*
is a
valid media type, though I do agree there should be a way to completely
block it. This is already done in case of async conduits which do not
exhibit strange side-effects...
Thanks, Sergey
regards, aki
2015-08-10 22:26 GMT+02:00 Sergey Beryozkin <[email protected]>:
On 10/08/15 21:23, Sergey Beryozkin wrote:
Hi Aki
What I know is that if we have HTTP Proxy and GET without Content-Type
then whatever Accept is there (ex. Accept: application/json) will be
replaced with */* by HttpUrlConnection (or proxy, not sure) - I have a
comment in the code about it though I haven't tried it myself - it was
reported by my company's colleague.
and wildcard is set to bypass that proxy bug, because it is just a
neutral
value.
Sergey
While it is a redundant header I'd say Spring is not very HTTP
friendly
- in GET cases Content-Type simply needs to be ignored as opposed to
reacting with the exception because it has no effect on the processing
-
the question is - would they accept GET with Content-Type
application/json, etc :-)
I'm not saying having a wildcard Content-Type with GET is very HTTP
friendly either :-). I'll add a property, disabled by default, but if
enabled then drop Content-Type.
Do you have HTTP proxy somewhere nearby ? If yes, may be you can
double
check ? We can definitely have this new property (always drop CT for
empty payloads) enabled by default eventually once the checks are
green
Thanks. Sergey
On 10/08/15 18:37, Aki Yoshida wrote:
Hi Sergey,
If I undertand the original query, Steen is seeing "Content-Type:
*/*"
in their GET request.
In that case, I don't understand why this unnecessary header with
this
invalid type value needs to be there to avoid some side-effect that
you mentioned.
Did I misunderstand the situation?
regards, aki
2015-08-10 16:32 GMT+02:00 Sergey Beryozkin <[email protected]>:
There's some history related to this issue.
At some point I updated the CXF client code to ignore Content-Type
completely. Then the side-effects caused by HttpUrlConnection
started
appearing:
- empty POSTs lead to HttpUrlConnection setting a form conetnt-type
- even more serious, if HTTP Proxy is used, a custom Accept is
completely
lost for requests with the empty payloads.
So indeed, I reverted it to have Content-Type dropped in case of
empty
payloads only if the async conduit is used.
I think it makes sense to let users control it via a property, as it
obvious
that unfortunately a single solution does not work with
HttpUrlConnection -
I'll take care of it.
It might also make sense to check what HttpUrlConnection does in
Java
8 and
9 re the above two side-effects
Cheers, Sergey
On 10/08/15 14:31, Steen Elvstrøm wrote:
I've been trying to use Apache CXF JAX-RS (version 3.0.4) to send
GET
requests to a Spring Boot application. Unfortunately CFX adds a
Content-Type: */* to the request headers which is not accepted by
spring
resulting in a 400 response stating "'Content-Type' cannot contain
wildcard
type '*'".
Since a Content-Type header on a GET request doesn't really make
sense
when
the request haven't got a request entity I guess it must be a bug.
A possible workaround is to add "cxf-rt-transports-http-hc" as a
dependency
and setting the property "use.async.http.conduit". Is it a valid
durable
way
to solve the issue?
--
View this message in context:
http://cxf.547215.n5.nabble.com/Why-does-CXF-JAX-RS-set-content-type-on-GET-requests-with-no-body-tp5759908.html
Sent from the cxf-user mailing list archive at Nabble.com.
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
Blog: http://sberyozkin.blogspot.com
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/