156 lines
5.1 KiB
Java
156 lines
5.1 KiB
Java
package com.jenkov.nioserver.http;
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
/**
|
|
* Created by jjenkov on 19-10-2015.
|
|
*/
|
|
public class HttpUtil {
|
|
|
|
private static final byte[] GET = new byte[]{'G','E','T'};
|
|
private static final byte[] POST = new byte[]{'P','O','S','T'};
|
|
private static final byte[] PUT = new byte[]{'P','U','T'};
|
|
private static final byte[] HEAD = new byte[]{'H','E','A','D'};
|
|
private static final byte[] DELETE = new byte[]{'D','E','L','E','T','E'};
|
|
|
|
private static final byte[] HOST = new byte[]{'H','o','s','t'};
|
|
private static final byte[] CONTENT_LENGTH = new byte[]{'C','o','n','t','e','n','t','-','L','e','n','g','t','h'};
|
|
|
|
public static int parseHttpRequest(byte[] src, int startIndex, int endIndex, HttpHeaders httpHeaders){
|
|
|
|
|
|
/*
|
|
int endOfHttpMethod = findNext(src, startIndex, endIndex, (byte) ' ');
|
|
if(endOfHttpMethod == -1) return false;
|
|
resolveHttpMethod(src, startIndex, httpHeaders);
|
|
*/
|
|
|
|
//parse HTTP request line
|
|
int endOfFirstLine = findNextLineBreak(src, startIndex, endIndex);
|
|
if(endOfFirstLine == -1) return -1;
|
|
|
|
|
|
//parse HTTP headers
|
|
int prevEndOfHeader = endOfFirstLine + 1;
|
|
int endOfHeader = findNextLineBreak(src, prevEndOfHeader, endIndex);
|
|
|
|
while(endOfHeader != -1 && endOfHeader != prevEndOfHeader + 1){ //prevEndOfHeader + 1 = end of previous header + 2 (+2 = CR + LF)
|
|
|
|
if(matches(src, prevEndOfHeader, CONTENT_LENGTH)){
|
|
try {
|
|
findContentLength(src, prevEndOfHeader, endIndex, httpHeaders);
|
|
} catch (UnsupportedEncodingException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
prevEndOfHeader = endOfHeader + 1;
|
|
endOfHeader = findNextLineBreak(src, prevEndOfHeader, endIndex);
|
|
}
|
|
|
|
if(endOfHeader == -1){
|
|
return -1;
|
|
}
|
|
|
|
//check that byte array contains full HTTP message.
|
|
int bodyStartIndex = endOfHeader + 1;
|
|
int bodyEndIndex = bodyStartIndex + httpHeaders.contentLength;
|
|
|
|
if(bodyEndIndex <= endIndex){
|
|
//byte array contains a full HTTP request
|
|
httpHeaders.bodyStartIndex = bodyStartIndex;
|
|
httpHeaders.bodyEndIndex = bodyEndIndex;
|
|
return bodyEndIndex;
|
|
}
|
|
|
|
|
|
return -1;
|
|
}
|
|
|
|
private static void findContentLength(byte[] src, int startIndex, int endIndex, HttpHeaders httpHeaders) throws UnsupportedEncodingException {
|
|
int indexOfColon = findNext(src, startIndex, endIndex, (byte) ':');
|
|
|
|
//skip spaces after colon
|
|
int index = indexOfColon +1;
|
|
while(src[index] == ' '){
|
|
index++;
|
|
}
|
|
|
|
int valueStartIndex = index;
|
|
int valueEndIndex = index;
|
|
boolean endOfValueFound = false;
|
|
|
|
while(index < endIndex && !endOfValueFound){
|
|
switch(src[index]){
|
|
case '0' : ;
|
|
case '1' : ;
|
|
case '2' : ;
|
|
case '3' : ;
|
|
case '4' : ;
|
|
case '5' : ;
|
|
case '6' : ;
|
|
case '7' : ;
|
|
case '8' : ;
|
|
case '9' : { index++; break; }
|
|
|
|
default: {
|
|
endOfValueFound = true;
|
|
valueEndIndex = index;
|
|
}
|
|
}
|
|
}
|
|
|
|
httpHeaders.contentLength = Integer.parseInt(new String(src, valueStartIndex, valueEndIndex - valueStartIndex, "UTF-8"));
|
|
|
|
}
|
|
|
|
|
|
public static int findNext(byte[] src, int startIndex, int endIndex, byte value){
|
|
for(int index = startIndex; index < endIndex; index++){
|
|
if(src[index] == value) return index;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public static int findNextLineBreak(byte[] src, int startIndex, int endIndex) {
|
|
for(int index = startIndex; index < endIndex; index++){
|
|
if(src[index] == '\n'){
|
|
if(src[index - 1] == '\r'){
|
|
return index;
|
|
}
|
|
};
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public static void resolveHttpMethod(byte[] src, int startIndex, HttpHeaders httpHeaders){
|
|
if(matches(src, startIndex, GET)) {
|
|
httpHeaders.httpMethod = HttpHeaders.HTTP_METHOD_GET;
|
|
return;
|
|
}
|
|
if(matches(src, startIndex, POST)){
|
|
httpHeaders.httpMethod = HttpHeaders.HTTP_METHOD_POST;
|
|
return;
|
|
}
|
|
if(matches(src, startIndex, PUT)){
|
|
httpHeaders.httpMethod = HttpHeaders.HTTP_METHOD_PUT;
|
|
return;
|
|
}
|
|
if(matches(src, startIndex, HEAD)){
|
|
httpHeaders.httpMethod = HttpHeaders.HTTP_METHOD_HEAD;
|
|
return;
|
|
}
|
|
if(matches(src, startIndex, DELETE)){
|
|
httpHeaders.httpMethod = HttpHeaders.HTTP_METHOD_DELETE;
|
|
return;
|
|
}
|
|
}
|
|
|
|
public static boolean matches(byte[] src, int offset, byte[] value){
|
|
for(int i=offset, n=0; n < value.length; i++, n++){
|
|
if(src[i] != value[n]) return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|