Update: this seems to be due to an Apache bug: https://bz.apache.org/bugzilla/show_bug.cgi?id=60330
I have a Java application that runs Jetty 8 as an embedded HTTP server. This is a back-end service, running on port 20000. The code of my actual service is not relevant. I have created an example project on GitHub to demonstrate the problem: https://github.com/janvanmansum/apache-jetty9-502-error
The main code is displayed below for reference. It depends on a couple of libraries:
javax.servlet:javax.servlet-api:3.1.0
commons-io:commons-io:2.5
org.eclipse.jetty:jetty-server:9.4.6.v20170531 or 8.2.0.v20160908
org.eclipse.jetty:jetty-servlet:9.4.6.v20170531 or 8.2.0.v20160908
BackendServer.java
package nl.knaw.dans.test;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
public class BackendServer {
public static void main(String[] args) throws Exception {
Server server = new Server(20000);
ServletContextHandler handler = new ServletContextHandler();
handler.addServlet(AcceptAllServlet.class, "/acceptAll");
handler.addServlet(ReadAllServlet.class, "/readAll");
server.setHandler(handler);
server.start();
server.join();
}
}
AcceptAllServlet
package nl.knaw.dans.test;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AcceptAllServlet extends HttpServlet {
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().write("AcceptAll Servlet OK!");
resp.setStatus(200);
}
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setStatus(201);
}
}
ReadAllServlet
package nl.knaw.dans.test;
import org.apache.commons.io.IOUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
public class ReadAllServlet extends HttpServlet {
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().write("ReadAll Servlet OK!");
resp.setStatus(200);
}
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
FileOutputStream fos = new FileOutputStream("target/outfile");
try {
IOUtils.copy(req.getInputStream(), fos);
}
finally {
fos.close();
}
resp.setStatus(201);
}
}
The service is exposed to the outside world through an Apache HTTP Server, which serves as a proxy, using the following configuration:
<VirtualHost *:80>
ProxyTimeout 600
<Location / >
ProxyPass http://localhost:20000/
ProxyPassReverse http://localhost:20000/
</Location>
</VirtualHost>
POST
-ing files to the back-end service through Apache works fine with Jetty 8 with files of any size. However in Jetty 9 I am getting a 502 Bad Gateway
error when posting to the AcceptAllServlet and the file size exceeds about 256K. My guess is that this has something to do with Apache not having finished writing the data to the back-end service. However, if the back-end server wants to respond 401 Unauthorized
I wouldn't want it to first read all the data that it is going to reject anyway.
Any ideas why this has apparently changed? Have I misconfigured Apache or am I using Jetty incorrectly? Or is this a bug?
Thanks for any help!