Java 解析原始HTTP请求
我正在研究HTTP流量数据集,它由完整的POST和GET请求组成,如下所示。我用java编写了代码,将每个请求分开,并将其保存为数组列表中的字符串元素。现在我不知道如何在java中解析这些原始HTTP请求,有什么方法比手动解析更好吗 我正在研究一个HTTP流量数据集,它由完整的POST和GET请求组成 因此,您需要解析包含多个HTTP请求的文件或列表。您要提取哪些数据?反正是一个JavaHTTP解析类,它可以读取请求行中使用的方法、版本和URI,并将所有头读入哈希表 如果你想重新发明轮子,你可以用它或者自己写一个。查看以查看请求的外观,以便正确解析它:Java 解析原始HTTP请求,java,http-headers,Java,Http Headers,我正在研究HTTP流量数据集,它由完整的POST和GET请求组成,如下所示。我用java编写了代码,将每个请求分开,并将其保存为数组列表中的字符串元素。现在我不知道如何在java中解析这些原始HTTP请求,有什么方法比手动解析更好吗 我正在研究一个HTTP流量数据集,它由完整的POST和GET请求组成 因此,您需要解析包含多个HTTP请求的文件或列表。您要提取哪些数据?反正是一个JavaHTTP解析类,它可以读取请求行中使用的方法、版本和URI,并将所有头读入哈希表 如果你想重新发明轮子,你可以
Request = Request-Line ; Section 5.1
*(( general-header ; Section 4.5
| request-header ; Section 5.3
| entity-header ) CRLF) ; Section 7.1
CRLF
[ message-body ] ; Section 4.3
下面是一个通用Http请求解析器,用于所有方法类型(GET、POST等),以方便您使用:
package util.dpi.capture;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Hashtable;
/**
* Class for HTTP request parsing as defined by RFC 2612:
*
* Request = Request-Line ; Section 5.1 (( general-header ; Section 4.5 |
* request-header ; Section 5.3 | entity-header ) CRLF) ; Section 7.1 CRLF [
* message-body ] ; Section 4.3
*
* @author izelaya
*
*/
public class HttpRequestParser {
private String _requestLine;
private Hashtable<String, String> _requestHeaders;
private StringBuffer _messagetBody;
public HttpRequestParser() {
_requestHeaders = new Hashtable<String, String>();
_messagetBody = new StringBuffer();
}
/**
* Parse and HTTP request.
*
* @param request
* String holding http request.
* @throws IOException
* If an I/O error occurs reading the input stream.
* @throws HttpFormatException
* If HTTP Request is malformed
*/
public void parseRequest(String request) throws IOException, HttpFormatException {
BufferedReader reader = new BufferedReader(new StringReader(request));
setRequestLine(reader.readLine()); // Request-Line ; Section 5.1
String header = reader.readLine();
while (header.length() > 0) {
appendHeaderParameter(header);
header = reader.readLine();
}
String bodyLine = reader.readLine();
while (bodyLine != null) {
appendMessageBody(bodyLine);
bodyLine = reader.readLine();
}
}
/**
*
* 5.1 Request-Line The Request-Line begins with a method token, followed by
* the Request-URI and the protocol version, and ending with CRLF. The
* elements are separated by SP characters. No CR or LF is allowed except in
* the final CRLF sequence.
*
* @return String with Request-Line
*/
public String getRequestLine() {
return _requestLine;
}
private void setRequestLine(String requestLine) throws HttpFormatException {
if (requestLine == null || requestLine.length() == 0) {
throw new HttpFormatException("Invalid Request-Line: " + requestLine);
}
_requestLine = requestLine;
}
private void appendHeaderParameter(String header) throws HttpFormatException {
int idx = header.indexOf(":");
if (idx == -1) {
throw new HttpFormatException("Invalid Header Parameter: " + header);
}
_requestHeaders.put(header.substring(0, idx), header.substring(idx + 1, header.length()));
}
/**
* The message-body (if any) of an HTTP message is used to carry the
* entity-body associated with the request or response. The message-body
* differs from the entity-body only when a transfer-coding has been
* applied, as indicated by the Transfer-Encoding header field (section
* 14.41).
* @return String with message-body
*/
public String getMessageBody() {
return _messagetBody.toString();
}
private void appendMessageBody(String bodyLine) {
_messagetBody.append(bodyLine).append("\r\n");
}
/**
* For list of available headers refer to sections: 4.5, 5.3, 7.1 of RFC 2616
* @param headerName Name of header
* @return String with the value of the header or null if not found.
*/
public String getHeaderParam(String headerName){
return _requestHeaders.get(headerName);
}
}
package util.dpi.capture;
导入java.io.BufferedReader;
导入java.io.IOException;
导入java.io.StringReader;
导入java.util.Hashtable;
/**
*用于RFC 2612定义的HTTP请求解析的类:
*
*请求=请求行;第5.1节((一般标题;第4.5节|
*请求标头;第5.3节(实体标头)CRLF);第7.1节CRLF[
*信息正文];第4.3节
*
*@作者伊泽拉亚
*
*/
公共类HttpRequestParser{
私有字符串_requestLine;
私有哈希表_requestHeaders;
私有StringBuffer_messagebody;
公共HttpRequestParser(){
_requestHeaders=新哈希表();
_messagetBody=newstringbuffer();
}
/**
*解析和HTTP请求。
*
*@param请求
*包含http请求的字符串。
*@抛出异常
*如果读取输入流时发生I/O错误。
*@抛出HttpFormatException
*如果HTTP请求格式不正确
*/
public void parseRequest(字符串请求)引发IOException、HttpFormatException{
BufferedReader reader=新BufferedReader(新StringReader(请求));
setRequestLine(reader.readLine());//请求行;第5.1节
字符串头=reader.readLine();
while(header.length()>0){
附录标题参数(标题);
header=reader.readLine();
}
字符串bodyLine=reader.readLine();
while(bodyLine!=null){
车身(车身线);
bodyLine=reader.readLine();
}
}
/**
*
*5.1请求行请求行以方法令牌开头,后跟
*请求URI和协议版本,并以CRLF结尾
*元素由SP字符分隔。除中之外,不允许使用CR或LF
*最后的CRLF序列。
*
*@带请求行的返回字符串
*/
公共字符串getRequestLine(){
返回请求行;
}
私有void setRequestLine(字符串requestLine)引发HttpFormatException{
if(requestLine==null | | requestLine.length()==0){
抛出新的HttpFormatException(“无效请求行:+requestLine”);
}
_requestLine=requestLine;
}
私有void appendHeaderParameter(字符串头)引发HttpFormatException{
int idx=header.indexOf(“:”);
如果(idx==-1){
抛出新的HttpFormatException(“无效的标头参数:“+标头”);
}
_requestHeaders.put(header.substring(0,idx),header.substring(idx+1,header.length());
}
/**
*HTTP消息的消息体(如果有)用于承载
*与请求或响应关联的实体正文。消息正文
*仅当传输编码已更改时,才与实体体不同
*已应用,如传输编码标题字段(第节)所示
* 14.41).
*@返回消息体字符串
*/
公共字符串getMessageBody(){
return_messagetBody.toString();
}
私有void appendMessageBody(字符串bodyLine){
_messagetBody.append(bodyLine.append(“\r\n”);
}
/**
*有关可用标题的列表,请参阅RFC 2616第4.5、5.3和7.1节
*@param headerName标头的名称
*@返回带有标头值的字符串,如果找不到则返回null。
*/
公共字符串getHeaderParam(字符串头名称){
return _requestHeaders.get(headerName);
}
}
如果您只想按原样发送原始请求,很简单,只需使用TCP套接字发送实际字符串即可
大概是这样的:
Socket socket = new Socket(host, port);
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream(), "UTF8"));
for (String line : getContents(request)) {
System.out.println(line);
out.write(line + "\r\n");
}
out.write("\r\n");
out.flush();
请参阅JoeJag提供的完整代码
更新
我启动了一个项目,为请求、响应、标题等提供HTTP解析器。。。结果证明,它非常好,使得在上面编写HTTP服务器和客户端非常容易。如果您正在寻找较低级别的内容,请查看它。您需要在哪里解析这些内容?在Servlet或类似技术(或)普通Java类中?数据来自哪里?您需要解析什么呢?如果您绝对必须直接执行HTTP,而这不是针对类,我强烈建议您使用ApacheCommonsHttpClient之类的工具。自己做这件事有很多陷阱。(例如分块传输编码)@AliAhmad-你到底想完成什么?如果您使用的是HttpClient类,则不需要手动解析HTTP数据流。您已经询问了如何解析HTTP,但这可能意味着很多事情,具体取决于您试图从原始流中提取的内容。如果不说明你的最终目标,这个问题就近乎于“没有建设性”。
Socket socket = new Socket(host, port);
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream(), "UTF8"));
for (String line : getContents(request)) {
System.out.println(line);
out.write(line + "\r\n");
}
out.write("\r\n");
out.flush();