接上篇, 上篇讲到解析请求行,这篇来讲下,请求头的处理, 基于http协议的请求头格式key:value形式存在,再解析时可以以:为分隔点, 左边为name, 右边value,循环,一行一行解析:
新增类:HttpHeader
package com.wolfcode._02_2_tomcat.http;
public class HttpHeader {
public static final int INITIAL_NAME_SIZE = 32;
public static final int INITIAL_VALUE_SIZE = 64;
public static final int MAX_NAME_SIZE = 128;
public static final int MAX_VALUE_SIZE = 4096;
public char[] name;
public int nameEnd;
public char[] value;
public int valueEnd;
protected int hashCode = 0;
public HttpHeader() {
this(new char[INITIAL_NAME_SIZE], 0, new char[INITIAL_VALUE_SIZE], 0);
}
public HttpHeader(char[] name, int nameEnd, char[] value, int valueEnd) {
this.name = name;
this.nameEnd = nameEnd;
this.value = value;
this.valueEnd = valueEnd;
}
public HttpHeader(String name, String value) {
this.name = name.toLowerCase().toCharArray();
this.nameEnd = name.length();
this.value = value.toCharArray();
this.valueEnd = value.length();
}
public void recycle() {
nameEnd = 0;
valueEnd = 0;
hashCode = 0;
}
}
修改类:SocketInputStream
添加类解析请求头的方法
/**
* 读请求头
*
* @param header
*/
public void readHeader(HttpHeader header) throws IOException {
if (header.nameEnd != 0) {
header.recycle();
}
int chr = read();
if (chr == '\r' || chr == '\n') {
header.nameEnd = 0;
header.valueEnd = 0;
return;
} else {
pos--; // 退一位操作
}
int maxRead = header.name.length;
int readStart = pos;
int readCount = 0;
boolean colon = false;
while (!colon) {
if (readCount >= maxRead) {
if ((2 * maxRead) <= HttpHeader.MAX_NAME_SIZE) {
char[] newBuffer = new char[2 * maxRead];
System.arraycopy(header.name, 0, newBuffer, 0, maxRead);
header.name = newBuffer;
maxRead = header.name.length;
} else {
throw new RuntimeException("读请求头数据出错");
}
}
if (pos >= count) {
int val = read();
if (val == -1) {
throw new RuntimeException("读请求头数据出错");
}
pos = 0;
readStart = 0;
}
if (buf[pos] == ':') {
colon = true;
}
char val = (char) buf[pos];
if ((val >= 'A') && (val <= 'Z')) {
// 大写转小写
val = (char) (val + 32);
}
// 请求头的key值
header.name[readCount] = val;
readCount++;
pos++;
}
header.nameEnd = readCount - 1;
maxRead = header.value.length;
readStart = pos;
readCount = 0;
boolean eol = false;
boolean validLine = true;
while (validLine) {
boolean space = true;
while (space) {
if (pos >= count) {
int val = read();
if (val == -1)
throw new RuntimeException("读请求头数据出错");
pos = 0;
readStart = 0;
}
// 去掉:后面的空格
if (buf[pos] == ' ') {
pos++;
} else {
space = false;
}
}
while (!eol) {
if (readCount >= maxRead) {
if ((2 * maxRead) <= HttpHeader.MAX_VALUE_SIZE) {
char[] newBuffer = new char[2 * maxRead];
System.arraycopy(header.value, 0, newBuffer, 0, maxRead);
header.value = newBuffer;
maxRead = header.value.length;
} else {
throw new RuntimeException("读请求头数据出错");
}
}
if (pos >= count) {
int val = read();
if (val == -1)
throw new RuntimeException("读请求头数据出错");
pos = 0;
readStart = 0;
}
if (buf[pos] == '\r') {
} else if (buf[pos] == '\n') {
eol = true;
} else {
int ch = buf[pos] & 0xff;
header.value[readCount] = (char) ch;
readCount++;
}
pos++;
}
int nextChr = read();
//下一个请求头
if ((nextChr != ' ') && (nextChr != '\t')) {
pos--;
validLine = false;
} else {
eol = false;
if (readCount >= maxRead) {
if ((2 * maxRead) <= HttpHeader.MAX_VALUE_SIZE) {
char[] newBuffer = new char[2 * maxRead];
System.arraycopy(header.value, 0, newBuffer, 0,
maxRead);
header.value = newBuffer;
maxRead = header.value.length;
} else {
throw new RuntimeException("读请求头数据出错");
}
}
header.value[readCount] = ' ';
readCount++;
}
}
header.valueEnd = readCount;
}
修改类:HttpServer
添加了解析请求头的方法
/**
* 解析请求头信息
*
* @param input
*/
private void parseHeaders(SocketInputStream input) throws IOException {
while (true) {
HttpHeader header = new HttpHeader();
input.readHeader(header);
if (header.nameEnd == 0) {
if (header.valueEnd == 0) {
return;
} else {
throw new RuntimeException("解析请求头报错");
}
}
String name = new String(header.name, 0, header.nameEnd);
String value = new String(header.value, 0, header.valueEnd);
request.addHeader(name, value);
if (name.equals("content-length")) {
int n = -1;
try {
n = Integer.parseInt(value);
} catch (Exception e) {
throw new RuntimeException("解析请求头报错");
}
request.setContentLength(n);
} else if (name.equals("content-type")) {
request.setContentType(value);
}
}
}
修改类:Reqeust
添加一个map接收header数据
public void addHeader(String name, String value) {
name = name.toLowerCase();
synchronized (headers) {
if (value != null) {
headers.put(name, value);
}
}
}
好到这,本篇内容结束。