-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Jersey 2 fails if request contains Content-Type
without a value
#2883
Comments
Issue #1116 was corrected in version 9.4.7.v20170914 So what you are seeing in 9.4.11.v20160115 would be something new. |
Tried putting together a testcase. package jetty.badclient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class Issue2883EmptyContentType
{
@SuppressWarnings("serial")
public static class HelloServlet extends HttpServlet
{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
resp.setContentType("text/plain");
resp.getWriter().println("Hello Test");
req.getParameterMap(); // trigger code that depends on Content-Type on the request
}
}
private static Server server;
@BeforeClass
public static void startServer() throws Exception
{
server = new Server(8080);
ServletContextHandler contexts = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
contexts.addServlet(HelloServlet.class,"/*");
server.setHandler(contexts);
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Test
public void testRequest() throws Throwable
{
String body = "hello";
String request =
"POST / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Type: \r\n" +
"Connection: close\r\n" +
"Accept-Encoding: gzip, deflated\r\n" +
"Content-Length: " + body.length() + "\r\n" +
"\r\n" +
body;
InetAddress destAddr = InetAddress.getByName("localhost");
int port = 8080;
SocketAddress endpoint = new InetSocketAddress(destAddr,port);
try (Socket socket = new Socket())
{
socket.connect(endpoint);
try (OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
Reader reader = new InputStreamReader(in);
BufferedReader buf = new BufferedReader(reader))
{
// Send GET Request
System.err.print(request);
System.err.println();
System.err.printf("Request: %,d bytes%n",request.length());
out.write(request.getBytes(StandardCharsets.UTF_8));
// Get Response
String line = null;
while ((line = buf.readLine()) != null)
{
System.err.printf("[response]: %s%n",line);
}
System.err.println("[done]");
}
}
}
} Output shows ...
Simply having an empty Something else is going on. |
Thanks for your reply. The API would look something like this : @POST
@Path("/vis")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response postRessource(Body body){} nginx does not alter the response :) as you can see from the body message, I am using jackson for json manipulation, but I doubt that would be it as in the previous version of jetty mentioned above, the request does go through ContainerRequestFilter as expected. |
@najibk turn on DEBUG log level for org.eclipse.jetty.servlet.ServletHandler. You should see log lines related to the handling of the request as it passes through the filterchain (if there is one). Can you also please provide a small reproduction test case. |
Here's a full example to reproduce the issue : API : @POST
@Path("vis")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addResource(){
return Response.ok().build();
} Filter (will never be called anyway) : @Provider
public class RequestFilter implements ContainerRequestFilter {
/**
* Add request id and service id to Thread context for automatic logging
* @param containerRequestContext
*/
@Override
public void filter(ContainerRequestContext containerRequestContext){
System.out.println("Hello filter");
}
} Test : @Test
public void testRequest() throws Throwable
{
String body = "hello";
String request =
"POST /vis HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Type: \r\n" +
"Connection: close\r\n" +
"Accept-Encoding: gzip, deflated\r\n" +
"Content-Length: " + body.length() + "\r\n" +
"\r\n" +
body;
InetAddress destAddr = InetAddress.getByName("localhost");
int port = 8080;
SocketAddress endpoint = new InetSocketAddress(destAddr,port);
try (Socket socket = new Socket())
{
socket.connect(endpoint);
try (OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
Reader reader = new InputStreamReader(in);
BufferedReader buf = new BufferedReader(reader))
{
// Send GET Request
System.err.print(request);
System.err.println();
System.err.printf("Request: %,d bytes%n",request.length());
out.write(request.getBytes(StandardCharsets.UTF_8));
// Get Response
String line = null;
while ((line = buf.readLine()) != null)
{
System.err.printf("[response]: %s%n",line);
}
System.err.println("[done]");
}
}
} DEBUG logs : |
@najibk I'd need a webapp as a reproduction. Also, the debug log shows that there is no filter chain. So please set Server.dumpAfterStart(true) on your server instance (if running embedded, or use the dumpAfterStart property in the server.ini file if running from the distro). That will show you what filters have been configured. |
Jersey will throw the response 400 in many scenarios related to invalid/unexpected Also, your code comment |
Thanks @joakime for your reply, The main issue is not the response itself but rather the way the request is handled, as I said before, I can't handle Exceptions anymore with the recent version of Jetty, catching exceptions is useful for editing the response body for example with a more explicit message. As to my comment, it's only for logging purposes : response status, duration ... i did not attach the full code to focus on the main issue. |
Confirmed. This is a Jersey behavior.
You are sending An empty string |
A full demo project (including above test case) can be found at ... |
Thank you @joakime for the detailed response and the demo project, I have filed an issue as you suggested to eclipse-ee4j/jersey, it can be found at eclipse-ee4j/jersey#3932. |
I'm closing this as not a Jetty issue. |
Content-Type
without a value
Hello,
I'm using Jersey 2 to develop a web service on Jetty.
A POST request with an empty Content-type results in a 400 Bad Request response in Jetty 9.4.11.v20180605 without the request going through Request filters.
is this a bug related to this fix "Support empty HTTP header values" issues/1116 ?
Issue not present on Jetty 9.3.7.v20160115 for example.
My questions is how is this request handled ? ExceptionMapper does not catch this kinf of errors neither.
Thanks
The text was updated successfully, but these errors were encountered: