This repository has been archived on 2021-12-05. You can view files and clone it, but cannot push or open issues or pull requests.
java-nio-server/src/main/java/com/jenkov/nioserver/http/HttpUtil.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;
}
}