-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathHttpParser.java
More file actions
135 lines (123 loc) · 5.77 KB
/
HttpParser.java
File metadata and controls
135 lines (123 loc) · 5.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package com.johan.http;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class HttpParser {
private final static Logger LOGGER = LoggerFactory.getLogger(HttpParser.class);
private static final int SP = 0x20; //32
private static final int CR = 0x0D; //13
private static final int LF = 0x0A; //10
public static HttpRequest parseHttpReq(InputStream iptStream) throws HttpParsingException {
InputStreamReader isr = new InputStreamReader(iptStream, StandardCharsets.US_ASCII);
HttpRequest request = new HttpRequest();
try {
parseRequestLine(isr, request);
parseHeader(isr, request);
}catch(IOException e){
throw new HttpParsingException(HttpStatusCode.CLIENT_ERROR_400_BAD_REQ);
}
parseBody(isr, request);
return request;
}
private static void parseRequestLine(InputStreamReader isr, HttpRequest req) throws IOException, HttpParsingException {
boolean methodParsed = false;
boolean reqTargetParsed = false;
StringBuilder processDataBuffer = new StringBuilder();
int _byte;
while ((_byte=isr.read()) >=0){
if(_byte==CR){
_byte=isr.read();
if(_byte==LF){
LOGGER.debug("Request Line VERSION to process : {}", processDataBuffer.toString());
if (!methodParsed || !reqTargetParsed) {
throw new HttpParsingException(HttpStatusCode.CLIENT_ERROR_400_BAD_REQ);
}
try {
req.setHttpVersion(processDataBuffer.toString());
}catch (BadHttpVersionException e) {
LOGGER.error("Bad HTTP Version received : {}", e.getMessage());
throw new HttpParsingException(HttpStatusCode.SERVER_ERROR_505_HTTP_VERSION_NOT_SUPPORTED);
}
return;
}else{
throw new HttpParsingException(HttpStatusCode.CLIENT_ERROR_400_BAD_REQ);
}
}
if(_byte==SP){
if (!methodParsed) {
LOGGER.debug("Request Line METHOD to process : {}", processDataBuffer.toString());
try {
req.setMethod(processDataBuffer.toString());
methodParsed = true;
}catch (HttpParsingException e){
LOGGER.error("Invalid HTTP Method received : {}", e.getMessage());
throw new HttpParsingException(HttpStatusCode.SERVER_ERROR_501_NOT_IMPLEMENTED);
}
}else if (!reqTargetParsed) {
LOGGER.debug("Request Line REQ TARGET to process : {}", processDataBuffer.toString());
req.setRequestTarget(processDataBuffer.toString());
reqTargetParsed = true;
}
else{
throw new HttpParsingException(HttpStatusCode.CLIENT_ERROR_400_BAD_REQ);
}
processDataBuffer.delete(0, processDataBuffer.length());
}else{
processDataBuffer.append((char)_byte);
if(!methodParsed){
if(processDataBuffer.length()>HttpMethod.MAX_LENGTH){
LOGGER.error("Terminating connection, Bad Method received : {}", processDataBuffer.toString());
throw new HttpParsingException(HttpStatusCode.SERVER_ERROR_501_NOT_IMPLEMENTED);
}
}
}
}
}
private static void parseHeader(InputStreamReader isr, HttpRequest req) throws HttpParsingException, IOException {
StringBuilder processDataBuffer = new StringBuilder();
boolean headerParsed = false;
int _byte;
while ((_byte=isr.read()) >=0){
if(_byte==CR){
_byte=isr.read();
if(_byte==LF) {
String line = processDataBuffer.toString().trim();
if (line.isEmpty()) {
if(!headerParsed){
throw new HttpParsingException(HttpStatusCode.CLIENT_ERROR_400_BAD_REQ);
}
return;
}
processingHeaderField(processDataBuffer, req);
headerParsed = true;
processDataBuffer.delete(0, processDataBuffer.length());
} else{
throw new HttpParsingException(HttpStatusCode.CLIENT_ERROR_400_BAD_REQ);
}
} else{
processDataBuffer.append((char)_byte);
}
}
}
private static void processingHeaderField(StringBuilder processDataBuffer, HttpRequest req) throws HttpParsingException {
String rawHeaderField = processDataBuffer.toString();
if (rawHeaderField.length() > 8192) {
throw new HttpParsingException(HttpStatusCode.CLIENT_ERROR_414_URI_TOO_LONG);
}
int colonIndex = rawHeaderField.indexOf(':');
if(colonIndex == -1){
throw new HttpParsingException(HttpStatusCode.CLIENT_ERROR_400_BAD_REQ);
}
String fieldName = rawHeaderField.substring(0, colonIndex).trim();
String fieldValue = rawHeaderField.substring(colonIndex+1).trim();
if(fieldName.isEmpty()){
throw new HttpParsingException(HttpStatusCode.CLIENT_ERROR_400_BAD_REQ);
}
req.addHeader(fieldName, fieldValue);
}
private static void parseBody(InputStreamReader isr, HttpRequest req) {
}
}