正文
HTTP报文格式
在http协议中采用制表符(\r)+ 换行符(\n)将每个节点数据分割开,每个节点包含不同信息,需要进一步处理。具体处理为:
- 请求行:请求行中包括3个信息 依次为:请求方法 、url(访问路由地址)、 Http版本。
- 请求方法:标识表示该报文采用的是那种请求方式,在HTTP报文中的第一个字节。包含如下值 G(GET)、H(HEAD)、P(POST)、D(DELETE)、O(OPTIONS)、T(TRACE)、C(CONNECT)。若为22则为HTTPs请求。请求方法在HTTP报文中第一个字节。
- url:这里的url代表的是需要访问的数据在主机中的路由地址。主机 + url就得到一个数据访问地址去访问特定数据。
- HTTP版本:这里存储的是HTTP版本号 格式如:HTTP/1.0
- 报文头:报文头中包括一系列的信息包括主机信息。每个信息以键值对的形式存储,键与值之间以冒号加一个空格‘: ’分开,每个信息以制表符加换行符分割。具体参见HTTP请求头大全
- 空行: 空行的作用是将数据头与数据体分开。HTTP协议规定报头与数据体之间必须要用空行分割,没有数据体时任需要有。
- 数据体:数据体中包含所有需要发送给应用处理的信息,信息与信息以符号‘&’连接,信息以键值对存储,键与值间用符号‘=’连接。
以下是具体实现的代码:
public class HttpPacket extends Packet{
private boolean isHttp;
private boolean isHttps;
private boolean isOther;
private String requestMethod;
private String requestUrl;
private String httpVersion;
private String httpHost;
private String httpUrl;
private String dataLien;
private String[] keyLines;
private Map<String,String> keys = new HashMap<>();
private Map<String,String> datas = new HashMap<>();
public HttpPacket(byte[] bytes, int... parameters) {
super(bytes, parameters);
parse();
}
/**
* 解析数据
* G : GET
* H : HEAD
* P : POST
* D : DELETE
* O : OPTIONS
* T : TRACE
* C : CONNECT
*/
private void parse(){
switch (bytes[offset]){
case 'G':
case 'H':
case 'P':
case 'D':
case 'O':
case 'T':
case 'C':
isHttp = true;
isHttps = false;
parseHttp();
break;
case 22:
isHttp = false;
isHttps = true;
break;
default:
isOther = true;
isHttp = false;
isHttps = false;
}
}
private void parseHttp(){
if(validLength - offset < 10) return;
String dataString = new String(bytes,offset,validLength);
keyLines = dataString.split("\\r\\n");
for(int i = 0; i < keyLines.length; i++){
if(i == 0){
String requestLine = keyLines[i].trim();
String[] data = requestLine.split(" ");
if(data.length > 0){
requestMethod = data[0];
}
if(data.length > 1){
requestUrl = data[1];
}
if(data.length >= 2){
httpVersion = data[2];
}
}else if(i == keyLines.length - 1){
dataLien = keyLines[keyLines.length - 1].trim();
if(dataLien.isEmpty())return;
String[] data = dataLien.split("&");
for(int j = 0;j < data.length;j++){
if(data[i].indexOf("=") != -1){
String[] keys = data[i].trim().split("=",2);
if(keys[0].isEmpty())continue;
if(keys.length == 1){
datas.put(keys[0].trim(),"");
}else
if(keys.length == 2){
datas.put(keys[0].trim(),keys[1].trim());
}
}
}
}else{
String requestLine = keyLines[i].trim();
if(requestLine.indexOf(": ") != -1){
String[] data = requestLine.split(": ",2);
String key = data[0].trim();
String value = data[1].trim();
if(key.isEmpty())continue;
keys.put(key,value);
if(key.equals("host")){
httpHost = value;
if(requestUrl != null) httpUrl = "http://" + httpHost+"/" + requestUrl;
}
}
}
}
}
public boolean isHttp() {
return isHttp;
}
public boolean isHttps() {
return isHttps;
}
public String getRequestMethod() {
return requestMethod;
}
public String getRequestUrl() {
return requestUrl;
}
public String getHttpVersion() {
return httpVersion;
}
public String getHttpHost() {
return httpHost;
}
public String getHttpUrl() {
return httpUrl;
}
public String getDataLien() {
return dataLien;
}
public boolean isOther() {
return isOther;
}
public Map<String, String> getKeys() {
return keys;
}
public Map<String, String> getDatas() {
return datas;
}
}