【问题标题】:Parsing HTTP Request in Java在 Java 中解析 HTTP 请求
【发布时间】:2016-06-24 14:04:05
【问题描述】:

我正在用 Java 构建一个简单的 http 请求解析器,作为工作中的学习练习。我的任务是简单地获取一个包含正文的 POST 请求,对其进行解析并根据 http 协议发回响应(状态 200 OK)。

当我使用 curl 命令发布请求时,请求行和标题会打印出来,但正文不会。在我按下 Ctrl c 退出卷曲后,身体会被打印出来。

nc -l 命令可以正常工作,并且正文与标题一起打印出来。

这两者有什么区别,如何使用 curl post 命令打印请求正文?

我的代码在下面,欢迎任何输入。

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class Server {

private static ServerSocket serverSocket;
private static Socket clientSocket;
private static BufferedReader bufferedReader;
private static String inputLine;
private static PrintWriter output;

public static void main(String[] args) {
    try {
        serverSocket = new ServerSocket(3000);

        while (true) {
            List<String> list = new ArrayList<String>();
            clientSocket = serverSocket.accept();
            bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            output = new PrintWriter(clientSocket.getOutputStream());

            inputLine = bufferedReader.readLine();
            while (inputLine.length() > 0) {
                System.out.println(inputLine);
                list.add(inputLine);
                inputLine = bufferedReader.readLine();
            }

           String bodyLine = bufferedReader.readLine();
            while(bodyLine != null && bodyLine.length() > 0){
                System.out.println(bodyLine);
                output.println(bodyLine);
                bodyLine = bufferedReader.readLine();
            }

            /* My Request class has a parse method that takes a List and parses in accordingly. getRequestLine() returns the request line of the request and getMethod() its method. */

            Request r = Request.parse(list);
            if (r.getRequestLine().getMethod().equals("GET")){
                output.println("HTTP/1.0 200 OK");
                output.println("Content-Type: text/html");
                output.println("");
                output.println("<p>GET REQUEST: </p><p>" + r + "</p>");
            }

            if (r.getRequestLine().getMethod().equals("POST")){
                output.println("HTTP/1.0 200 OK");
                output.println("Content-Type: text/html");
                output.println("");
                output.println("<p>POST REQUEST:</p><p>" + r + "</p>");
            }

            output.close();
            bufferedReader.close();
            clientSocket.close();

        }


    } catch (IOException error) {
        System.out.println(error);

    }

}

}

请求类:

import java.util.*;

public class Request {
private Map<String, String> headers;
private String body;
private RequestLine requestLine;

public Request(Map<String, String> headers, String body, RequestLine requestLine) {
    this.headers = headers;
    this.body = body;
    this.requestLine = requestLine;
}

public Map<String, String> getHeaders() {
    return headers;
}

public String getBody() {
    return body;
}

public RequestLine getRequestLine() {
    return requestLine;
}

public String toString() {
    return "Request Line: " + getRequestLine() + '\n' +  "Headers: " + getHeaders();
}

public static Request parse(List<String> lines) {
    String requestLineStr = lines.get(0);
    String[] requestLineArr = requestLineStr.split(" ");
    String method = requestLineArr[0];
    String URI = requestLineArr[1];
    String status = requestLineArr[2];

    RequestLine requestLine = new RequestLine(URI, method, status);


    //  int index = lines.indexOf("\r\n\r\n");
    //  List<String> headerList = lines.subList(1, index);
    // List<String> bodyList = lines.subList(index, -1);

    List<String> headerList = lines.subList(1, lines.size()-1);
    Map<String, String> headersMap = new HashMap<>();

    for(int i = 0; i <headerList.size(); i++) {
        String line = headerList.get(i);
        String[] arr = line.split(" ");
        headersMap.put(arr[0], arr[1]);
    }

    /*String bodyString = "";
    for(int i = 0; i < bodyList.size(); i++) {
        bodyString += bodyList.get(i);
    }*/

    return new Request(headersMap, "", requestLine);
}

}

【问题讨论】:

  • Request 使用什么库?如果自定义 - 提供您的代码
  • 添加到问题中,但我很确定问题出在我获取输入流的方式上
  • 能否请您添加到目前为止的 HTTP 请求和控制台输出?
  • 我使用 curl 发送带有正文的 post 请求,它会看到第一个缓冲的阅读器,输入行,打印出请求行和标题并停止
  • RequestLine 也是自定义类吗?

标签: java http httprequest


【解决方案1】:

LF = HTTP/1.1 将序列 CR LF 定义为除实体主体之外的所有协议元素的行尾标记。 RFC2616

标题一直到\r\n。之后身体开始。

读取线

公共字符串 readLine() 抛出 IOException

读取一行文本。一行被认为是由换行符('\n')中的任何一个终止,a 回车 ('\r'),或回车后紧跟 换行。返回:包含行内容的字符串,而不是 包括任何行终止字符,或 null 如果 已到达流 抛出:IOException - 如果发生 I/O 错误 BufferedReader#readLine()

所以只需在标题阅读和正文阅读之间添加一个额外的bufferedReader.readLine();

inputLine = bufferedReader.readLine();
        while (inputLine.length() > 0) {
            System.out.println(inputLine);
            list.add(inputLine);
            inputLine = bufferedReader.readLine();
        }
  bufferedReader.readLine();
  String bodyLine = bufferedReader.readLine();
        while(bodyLine != null && bodyLine.length() > 0){
            System.out.println(bodyLine);
            output.println(bodyLine);
            bodyLine = bufferedReader.readLine();
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-18
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多