Community
Participate
Working Groups
Build Identifier: jetty-distribution-7.2.0.v20101020 When I send a POST-Request via HttpUrlConnection (doOutput=true), Jetty calls doGet() and not doPost() in my servlet! I ckeck the same request with a plain SocketServer, that tolds me, that POST-Request was sent. Reproducible: Always Steps to Reproduce: This following class has the this output: Server-Header: POST /test HTTP/1.1 Server-Header: User-Agent: Java/1.6.0_16 Server-Header: Host: 127.0.0.1:7777 Server-Header: Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Server-Header: Connection: keep-alive Server-Header: Content-type: application/x-www-form-urlencoded Server-Header: Content-Length: 16 Server-Header: Server-Message: Hello, Server! Response-Code: 200 Response: Hi Client! - POST /test HTTP/1.1 2010-11-26 12:30:20.272:INFO::jetty-8.0.0.M2 2010-11-26 12:30:20.348:INFO::Started SelectChannelConnector@0.0.0.0:7777 [GET /test/]@30931963 org.eclipse.jetty.server.Request@1d7fbfb doGet-Called end of input Response-Code: 200 Response: Hi Client! - GET => Hi Client! - POST expected! ------------------------------------ ------------------------------------ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.ServerSocket; import java.net.Socket; import java.net.URL; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; public class TestServerJetty { public static void callServer() throws Exception { URL url = new URL("http://127.0.0.1:7777/test"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); PrintWriter w = new PrintWriter(conn.getOutputStream()); w.println("Hello, Server!"); w.flush(); w.close(); System.out.println("Response-Code: " + conn.getResponseCode()); BufferedReader in = new BufferedReader(new InputStreamReader( conn.getInputStream())); String line; while (null != (line = in.readLine())) { System.out.println("Response: " + line); } } public static void startJettyServer() throws Exception { Server server = new Server(7777); ServletContextHandler context = new ServletContextHandler(); context.setContextPath("/test"); context.addServlet(new ServletHolder(new TestServlet()), "/*"); HandlerList handlers = new HandlerList(); handlers.setHandlers(new Handler[] { context }); server.setHandler(handlers); server.start(); callServer(); server.stop(); } public static void startPlainServer() throws Exception { final ServerSocket server = new ServerSocket(7777); new Thread() { @Override public void run() { try { Socket socket = server.accept(); BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream())); String firstLine = null; String line; while (null != (line = in.readLine())) { System.out.println("Server-Header: " + line); if (firstLine == null) firstLine = line; if (line.length() == 0) break; } line = in.readLine(); System.out.println("Server-Message: " + line); PrintWriter out = new PrintWriter( socket.getOutputStream(), true); out.print("HTTP/1.0 200 OK\r\n" + // "Content-Type: test\r\n\r\n"); out.flush(); out.println("Hi Client! - " + firstLine); out.flush(); socket.close(); } catch (Exception e) { e.printStackTrace(); } } }.start(); callServer(); server.close(); } public static void main(String[] args) throws Exception { startPlainServer(); startJettyServer(); } public static class TestServlet extends HttpServlet { public TestServlet() { } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println(request); super.service(request, response); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doGet-Called"); handleCall("GET", request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doPost-Called"); handleCall("POST", request, response); } private void handleCall(String m, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { InputStream in = request.getInputStream(); BufferedReader r = new BufferedReader(new InputStreamReader(in)); String line; while (null != (line = r.readLine())) { System.out.println(line); } System.out.println("end of input"); response.setContentType("text/html"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("Hi Client! - " + m); } } }
The issue here is that jetty is doing a redirect from /test to /test/, and a redirected POST will end up as a GET. The reason for the redirect is that the servlet spec treats the root of a context like a directory and there is no valid set of contextPath + servletPath + pathInfo that is legal for a URL of /test to a context /test More importantly, if you send back HTML from a request to /test then any relative links will be relative to / instead of /test. Thus the redirect to /test/ fixes this. If you add a / to the URL in your post, you should be good.
Maybe the following was not possible back in 2010-12, but nowadays, you can add context.setAllowNullPathInfo(true) to avoid silent redirect from /context to /context/.