Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 331194 - POST-Request becomes GET-Request
Summary: POST-Request becomes GET-Request
Status: RESOLVED WONTFIX
Alias: None
Product: Jetty
Classification: RT
Component: server (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows Vista
: P3 major (vote)
Target Milestone: 7.1.x   Edit
Assignee: Greg Wilkins CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-11-26 06:31 EST by Mahe CLA
Modified: 2013-08-19 07:38 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mahe CLA 2010-11-26 06:31:31 EST
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);
        }
    }
}
Comment 1 Greg Wilkins CLA 2010-12-01 05:19:22 EST
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.
Comment 2 Michael Frankfurter CLA 2013-08-19 07:38:50 EDT
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/.