cxf-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sergey Beryozkin <sberyoz...@gmail.com>
Subject Re: Why does CXF JAX-RS set content-type on GET requests with no body?
Date Thu, 20 Aug 2015 12:49:21 GMT
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 <sberyozkin@gmail.com>:
>> 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 <elakito@gmail.com>:
>>>>
>>>> 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 <sberyozkin@gmail.com>:
>>>>>
>>>>> 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 <sberyozkin@gmail.com>:
>>>>>>>
>>>>>>>
>>>>>>> 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 <sberyozkin@gmail.com>:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> 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
>>>>>>>>>>> <sberyozkin@gmail.com>:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> 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/


Mime
View raw message