I think it makes sense for us to investigate in depth the proxy issue, if it proves to be avoidable then we can def start restricting setting a default */* CT for empty POST/PUT only. Which should be not bad because in such cases (empty POST/PUT) the users will know more about the target Consumes and thus they'd set Content-Type as needed.

By the way, as far as I know PUT with form payloads is apparently controversial though I'm not really sure why, more related the purity aspect of using PUT :-).

If we can restrict setting a default CT */* to POST/PUT only then I think it can be easier to eventually consider setting CT to */* disabled by default because if it is empty POST/PUT which targets the resource method that can only accept empty POSTs/PUTs, as opposed to either empty or non-empty payload with @Nillable then it would not be a problem even if HTTPUrlConnection sticks a form CT there...

I'll get you updated once we get a bit more info about the http proxy case...

Thanks, Sergey

On 20/08/15 13:20, Aki Yoshida wrote:
Hi Sergey,

2015-08-20 12:33 GMT+02:00 Sergey Beryozkin <[email protected]>:
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 ?

the method has no @Consumes but has only @POST and @Path.
But I think my problem was caused by my mistake in having another
operation that was interfering with this operation. So the operation
was randomly picked up ;-(. Sorry. Because I added this operation for
an empty body testing and didn't pay attention on interfering with the
existing operations.


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.

I thought something was happening at the server side, as I saw the
outgoing wire messages always look the same. But as I said, there was
an error in the way I configured my endpoint that caused that sporadic
errors.


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


If you mean CXF-6214, I don't know who is adding text/xml.
HTTPUrlConnection is not adding any content-type when using GET and
going directly or over an http proxy. So I suppose their proxy is
doing it.


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.

I can agree with your argument and SpringBoot should follow the
robustness principle that is the fundamental spirit of HTTP.
Otherwise, it is unnecessarily limiting its usability while not
getting any benefit from enforcing that strict rule.


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 ?

No. There is no 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 ?

I don't know which JIRA ticket you mean.

For CXF-6214, I suspect that their proxy is causing this issue and not
HttpURLConnection nor CXFClient.
For CXF-6553, this was an issue and you just fixed it with the logging
issue ticket CXF-6548.
So, I'll also set CXF-6548 as resolved. And for CXF-6538, as I
commented there, I didn't see any difference in the behavior, with or
without using a proxy.

With the current option that you added and the fix to the initial
default content-type setting, there is no actual problem.
thanks.

regards, aki




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/

Reply via email to