eclipse-ee4j / jersey

Eclipse Jersey Project - Read our Wiki:
https://github.com/eclipse-ee4j/jersey/wiki
Other
692 stars 354 forks source link

Empty Content-type results in request not going through Filters #3932

Open najibk opened 6 years ago

najibk commented 6 years ago

Hello,

I have filed this issue first to https://github.com/eclipse/jetty.project/issues/2883 thinking it was Jetty's behaviour.

Context : I'm using Jersey 2 and Jackson to develop a web service on Jetty. A POST request with an empty Content-type results in a 400 Bad Request response in Jetty without the request going through Request filters.

Issue : The problem is that I would like to edit the response body but I can't find a way to handle this kind of Exceptions using ExceptionMapper. It seems that the request does not go through Filters nor caught by a generic ExceptionMapper class.

A full demo project (including a test case) can be found at https://github.com/joakime/jetty-issue-2883-jersey-empty-content-type

Thanks

senivam commented 6 years ago

OK, thank you, I will take a look. Possibly is related to #3922

joakime commented 6 years ago

@senivam it's due to a nuance about HttpServletRequest.getHeader("Content-Type").

If it returns an empty string "", that means the header existed in the request, but had an empty value. If it returns a null, that means the header didn't exist in the request.

The 2 types of requests this can happen on ...

Using RFC7230 syntax ...

POST /vis HTTP/1.1
Host: localhost
Content-Type: 
Connection: close
Accept-Encoding: gzip, deflated
Content-Length: 5

hello

Using RFC2616 syntax ...

POST /vis HTTP/1.1
Host: localhost
Content-Type: ""
Connection: close
Accept-Encoding: gzip, deflated
Content-Length: 5

hello

Both of those will result in the following stacktrace with Jersey 2.27 ...

[FINE] WebComponent: Attempt to read the header value failed.
org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: ""
    at org.glassfish.jersey.message.internal.InboundMessageContext.exception(InboundMessageContext.java:338)
    at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:333)
    at org.glassfish.jersey.message.internal.InboundMessageContext.getMediaType(InboundMessageContext.java:446)
    at org.glassfish.jersey.servlet.WebComponent.filterFormParameters(WebComponent.java:612)
    at org.glassfish.jersey.servlet.WebComponent.initContainerRequest(WebComponent.java:463)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:414)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:857)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
    at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:61)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at org.eclipse.jetty.server.Server.handle(Server.java:503)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.lang.Thread.run(Thread.java:748)
Caused by: javax.ws.rs.ProcessingException: java.lang.IllegalArgumentException: Error parsing media type ''
    at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:452)
    at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:446)
    at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:331)
    ... 34 more
Caused by: java.lang.IllegalArgumentException: Error parsing media type ''
    at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:93)
    at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:61)
    at javax.ws.rs.core.MediaType.valueOf(MediaType.java:196)
    at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:450)
    ... 36 more
Caused by: java.text.ParseException: End of header.
    at org.glassfish.jersey.message.internal.HttpHeaderReaderImpl.getNextCharacter(HttpHeaderReaderImpl.java:179)
    at org.glassfish.jersey.message.internal.HttpHeaderReaderImpl.next(HttpHeaderReaderImpl.java:140)
    at org.glassfish.jersey.message.internal.HttpHeaderReaderImpl.next(HttpHeaderReaderImpl.java:135)
    at org.glassfish.jersey.message.internal.HttpHeaderReader.nextToken(HttpHeaderReader.java:128)
    at org.glassfish.jersey.message.internal.MediaTypeProvider.valueOf(MediaTypeProvider.java:111)
    at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:91)
    ... 39 more
najibk commented 6 years ago

Any updates on this ?

Thanks

jansupol commented 5 years ago

Someone can correct me, but I believe this is the JAX-RS Specification pipeline definition. The pipeline is defined as "when no content, no filters". Will try to find the exact wording.