2013-12-18 38 views
0

我正在運行一個嵌入式Jetty(9.1.0.v20131115)設置,並有幾個處理程序安裝來處理請求在幾個不同的上下文。碼頭是莫名其妙地吃POST參數

其中一個處理程序在用戶提交表單時執行登錄功能。它的設置如下:

ContextHandler loginContext = new ContextHandler("/login"); 
loginContext.setHandler(new LoginHandler()); 

// Other handlers go here... 

contexts.setHandlers(new Handler[]{rootContext, logoutContext, loginContext, resourceHandler}); 
server.setHandler(contexts); 

這應該是相當標準的,沒什麼特別的。令我感到困惑的是,當我通過調試器運行LoginHandler時,即使表單明確具有兩個表單輸入元素,HttpServletRequest對象也沒有參數!

這裏的請求的副本,這是我通過netcat的抓:

POST /login HTTP/1.1 
Host: localhost:52520 
Connection: keep-alive 
Content-Length: 31 
Cache-Control: max-age=0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
Origin: http://localhost:52520 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 
Content-Type: application/x-www-form-urlencoded 
Referer: http://localhost:52520/dashboard/ 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 

username=myuser&password=mypass 

最重要的是,如果我改變形式的行動,而不是GET POST的參數顯示出來就好了!

爲了讓Handler接受POST參數,必須做什麼特別的事情嗎?

回答

2

似乎工作得很好。

package jetty; 

import static org.hamcrest.CoreMatchers.*; 
import static org.junit.Assert.*; 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.io.PrintWriter; 
import java.io.StringReader; 
import java.io.StringWriter; 
import java.net.InetSocketAddress; 
import java.net.Socket; 

import javax.servlet.ServletException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.eclipse.jetty.server.Request; 
import org.eclipse.jetty.server.Server; 
import org.eclipse.jetty.server.ServerConnector; 
import org.eclipse.jetty.server.handler.ContextHandler; 
import org.eclipse.jetty.server.handler.DefaultHandler; 
import org.eclipse.jetty.server.handler.HandlerCollection; 
import org.eclipse.jetty.server.handler.HandlerWrapper; 
import org.eclipse.jetty.util.IO; 
import org.junit.AfterClass; 
import org.junit.BeforeClass; 
import org.junit.Test; 

public class JettyPostTest 
{ 
    public static class LoginHandler extends HandlerWrapper 
    { 
     @Override 
     public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException 
     { 
      PrintWriter out = response.getWriter(); 
      response.setContentType("text/plain"); 

      out.printf("username = %s\n",request.getParameter("username")); 
      out.printf("password = %s\n",request.getParameter("password")); 

      baseRequest.setHandled(true); 
     } 
    } 

    private static Server server; 
    private static int port; 

    @BeforeClass 
    public static void startServer() throws Exception 
    { 
     server = new Server(); 
     ServerConnector connector = new ServerConnector(server); 
     connector.setPort(0); 
     server.addConnector(connector); 

     // collection for handlers 
     HandlerCollection handlers = new HandlerCollection(); 
     server.setHandler(handlers); 

     // login context 
     ContextHandler loginContext = new ContextHandler("/login"); 
     loginContext.setHandler(new LoginHandler()); 
     handlers.addHandler(loginContext); 

     // default handler 
     handlers.addHandler(new DefaultHandler()); 

     // start server 
     server.start(); 

     // grab port 
     port = connector.getLocalPort(); 
    } 

    @AfterClass 
    public static void stopServer() throws Exception 
    { 
     server.stop(); 
    } 

    @Test 
    public void testPostParameters() throws IOException 
    { 
     StringBuilder req = new StringBuilder(); 
     req.append("POST /login/ HTTP/1.1\r\n"); 
     req.append("Host: localhost:").append(port).append("\r\n"); 
     req.append("Connection: close\r\n"); 
     req.append("Content-Length: 31\r\n"); 
     req.append("Cache-Control: max-age=0\r\n"); 
     req.append("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"); 
     req.append("Origin: http://localhost:").append(port).append("\r\n"); 
     req.append("User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36\r\n"); 
     req.append("Content-Type: application/x-www-form-urlencoded\r\n"); 
     req.append("Referer: http://localhost:").append(port).append("/dashboard/\r\n"); 
     req.append("Accept-Encoding: gzip,deflate,sdch\r\n"); 
     req.append("Accept-Language: en-US,en;q=0.8\r\n"); 
     req.append("\r\n"); 
     req.append("username=myuser&password=mypass\r\n"); 

     try (Socket socket = new Socket()) 
     { 
      socket.connect(new InetSocketAddress("localhost",port)); 
      // Write request 
      try (OutputStream out = socket.getOutputStream(); 
        OutputStreamWriter writer = new OutputStreamWriter(out); 
        InputStream in = socket.getInputStream(); 
        InputStreamReader reader = new InputStreamReader(in)) 
      { 
       StringReader reqStream = new StringReader(req.toString()); 
       IO.copy(reqStream,writer); 
       writer.flush(); 
       out.flush(); 

       StringWriter respStream = new StringWriter(); 
       IO.copy(reader,respStream); 

       System.out.println(respStream.toString()); 

       String expected = "username = myuser\npassword = mypass\n"; 
       assertThat("Response",respStream.toString(),containsString(expected)); 
      } 
     } 
    } 
} 

結果輸出:

2013-12-18 13:23:08.856:INFO:oejs.Server:main: jetty-9.1.0.v20131115 
2013-12-18 13:23:08.888:INFO:oejsh.ContextHandler:main: Started [email protected]{/login,null,AVAILABLE} 
2013-12-18 13:23:08.897:INFO:oejs.ServerConnector:main: Started [email protected]{HTTP/1.1}{0.0.0.0:34456} 
HTTP/1.1 200 OK 
Content-Type: text/plain; charset=ISO-8859-1 
Connection: close 
Server: Jetty(9.1.0.v20131115) 

username = myuser 
password = mypass 

2013-12-18 13:23:08.994:INFO:oejs.ServerConnector:main: Stopped [email protected]{HTTP/1.1}{0.0.0.0:0} 
2013-12-18 13:23:08.995:INFO:oejsh.ContextHandler:main: Stopped [email protected]{/login,null,UNAVAILABLE} 

只改變我從你的要求而作出的改變Connection: keep-aliveConnection: close讓碼頭關閉連接。這種改變很小,只允許測試快速執行,使用原始值不會改變測試結果。

某件信息從您的問題中缺失。

+0

事實上,你是對的。運行你的單元測試我看到了相同的結果。我正在通過差異現在... –

+0

Joakim,你做了一個沒有提到的其他變化。您似乎已將「POST/login HTTP/1.1」更改爲「POST/login/HTTP/1.1」。尾隨斜線改變了所有區別。 –

+2

啊,是的。對''/ login''的請求將導致302重定向到「」/ login /「',並且您的客戶端可能不會正確地重新提交POST。我剛剛跳過了302重定向,並讓測試執行重定向後的請求。 –

相關問題