Added test for http parser and fixed some issues
This commit is contained in:
parent
c196a7cca0
commit
9934ff1df5
8 changed files with 163 additions and 55 deletions
|
|
@ -35,31 +35,34 @@ import java.util.TreeMap;
|
|||
public class HttpHeader {
|
||||
// Constants
|
||||
|
||||
public static final String HEADER_CACHE_CONTROL = "Cache-Control";
|
||||
public static final String HEADER_COOKIE = "Cookie";
|
||||
public static final String HEADER_CONTENT_TYPE = "Content-Type";
|
||||
public static final String HEADER_CONTENT_LENGTH = "Content-Length";
|
||||
public static final String HEADER_COOKIE = "Cookie";
|
||||
public static final String HEADER_SET_COOKIE = "Set-Cookie";
|
||||
public static final String HEADER_SERVER = "Server";
|
||||
public static final String HEADER_USER_AGENT = "User-Agent";
|
||||
public static final String HEADER_IF_NONE_MATCH = "If-None-Match";
|
||||
|
||||
// Variables
|
||||
|
||||
private boolean isRequest = true;
|
||||
|
||||
/** Specifies the protocol that should be used */
|
||||
private String protocol = "HTTP";
|
||||
private String protocol = null;
|
||||
/** The protocol version specified in the header */
|
||||
private float protocolVersion = 1.0f;
|
||||
private float protocolVersion = -1;
|
||||
|
||||
/** HTTP type specified in a HTTP request, e.g GET POST DELETE PUT etc */
|
||||
private String requestType = "GET";
|
||||
private String requestType = null;
|
||||
/** String containing the target URL */
|
||||
private String requestUrl = "/";
|
||||
private String requestUrl = null;
|
||||
/** Map containing all the properties from the URL */
|
||||
private Map<String, String> requestUrlAttributes = new HashMap<>();
|
||||
|
||||
/** Status code specified in a HTTP response message */
|
||||
private int responseStatusCode = 200;
|
||||
private int responseStatusCode = -1;
|
||||
private String responseStatusString = null;
|
||||
|
||||
/** An Map of all header fields */
|
||||
private Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
|
@ -136,8 +139,16 @@ public class HttpHeader {
|
|||
|
||||
public void setResponseStatusCode(int code) {
|
||||
this.responseStatusCode = code;
|
||||
this.responseStatusString = getResponseStatusString(code);
|
||||
}
|
||||
|
||||
public String getResponseStatusString() {
|
||||
return responseStatusString;
|
||||
}
|
||||
|
||||
public void getResponseStatusString(String msg) {
|
||||
this.responseStatusString = msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the URL that the client sent the server
|
||||
|
|
@ -303,10 +314,6 @@ public class HttpHeader {
|
|||
}
|
||||
|
||||
|
||||
public String getResponseStatusString() {
|
||||
return getResponseStatusString(responseStatusCode);
|
||||
}
|
||||
|
||||
public static String getResponseStatusString(int type) {
|
||||
switch (type) {
|
||||
case 100: return "Continue";
|
||||
|
|
|
|||
|
|
@ -101,28 +101,34 @@ public class HttpHeaderParser {
|
|||
* @param statusLine the status line String
|
||||
*/
|
||||
private static void parseStatusLine(HttpHeader header, String statusLine) {
|
||||
String[] lineArr = statusLine.split(" ", 3);
|
||||
|
||||
if (lineArr.length != 3)
|
||||
return;
|
||||
|
||||
// Server Response
|
||||
if (statusLine.startsWith("HTTP/")) {
|
||||
if (lineArr[0].contains("/")) {
|
||||
header.setIsRequest(false);
|
||||
header.setProtocolVersion(Float.parseFloat(statusLine.substring(5, 8)));
|
||||
header.setResponseStatusCode(Integer.parseInt(statusLine.substring(9, statusLine.indexOf(' ', 9))));
|
||||
header.setProtocol(lineArr[0].substring(0, lineArr[0].indexOf('/')));
|
||||
header.setProtocolVersion(Float.parseFloat(lineArr[0].substring(lineArr[0].indexOf('/')+1)));
|
||||
header.setResponseStatusCode(Integer.parseInt(lineArr[1]));
|
||||
header.getResponseStatusString(lineArr[2]);
|
||||
}
|
||||
// Client Request
|
||||
else if (statusLine.contains("HTTP/")) {
|
||||
else {
|
||||
header.setIsRequest(true);
|
||||
header.setRequestType(statusLine.substring(0, statusLine.indexOf(" ")).trim());
|
||||
header.setProtocolVersion(Float.parseFloat(statusLine.substring(statusLine.lastIndexOf("HTTP/") + 5).trim()));
|
||||
statusLine = (statusLine.substring(header.getRequestType().length() + 1, statusLine.lastIndexOf("HTTP/")));
|
||||
header.setRequestType(lineArr[0]);
|
||||
header.setProtocol(lineArr[2].substring(0, lineArr[2].indexOf('/')));
|
||||
header.setProtocolVersion(Float.parseFloat(lineArr[2].substring(lineArr[2].indexOf('/')+1)));
|
||||
String url = lineArr[1];
|
||||
|
||||
// parse URL and attributes
|
||||
int index = statusLine.indexOf('?');
|
||||
if (index > -1) {
|
||||
header.setRequestURL(statusLine.substring(0, index));
|
||||
statusLine = statusLine.substring(index + 1);
|
||||
parseURLParameters(header.getURLAttributeMap(), statusLine);
|
||||
} else {
|
||||
header.setRequestURL(statusLine);
|
||||
int paramStartIndex = url.indexOf('?');
|
||||
if (paramStartIndex >= 0) {
|
||||
url = statusLine.substring(0, paramStartIndex);
|
||||
parseURLParameters(header.getURLAttributeMap(), statusLine.substring(paramStartIndex + 1));
|
||||
}
|
||||
header.setRequestURL(url.trim());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,20 @@ public class HttpPrintStream extends OutputStream {
|
|||
*/
|
||||
public HttpPrintStream(OutputStream out, HttpMessageType type) {
|
||||
this.out = new PrintStream(out);
|
||||
header.setIsRequest(type == HttpMessageType.REQUEST);
|
||||
|
||||
// Set defaults
|
||||
|
||||
header.setProtocol("HTTP");
|
||||
header.setProtocolVersion(1.0f);
|
||||
|
||||
if (type == HttpMessageType.REQUEST) {
|
||||
header.setIsRequest(true);
|
||||
header.setRequestType("GET");
|
||||
header.setRequestURL("/");
|
||||
} else {
|
||||
header.setIsRequest(false);
|
||||
header.setResponseStatusCode(200);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -50,11 +50,12 @@ public class HttpFilePage implements HttpPage{
|
|||
private static final Logger log = LogUtil.getLogger();
|
||||
private static final int MAX_CACHE_AGE_SECONDS = 120;
|
||||
|
||||
private File resource_root;
|
||||
private final File resource_root;
|
||||
private boolean showFolders;
|
||||
private boolean redirectToIndex;
|
||||
|
||||
private HashMap<File,FileCache> cache;
|
||||
private final HashMap<File,FileCache> cache;
|
||||
|
||||
private static class FileCache{
|
||||
public long lastModified;
|
||||
public String hash;
|
||||
|
|
@ -64,6 +65,9 @@ public class HttpFilePage implements HttpPage{
|
|||
* @param file a reference to a root directory or a file.
|
||||
*/
|
||||
public HttpFilePage(File file){
|
||||
if (file == null)
|
||||
throw new IllegalArgumentException("Root path cannot be null.");;
|
||||
|
||||
this.resource_root = file;
|
||||
this.showFolders = true;
|
||||
this.redirectToIndex = true;
|
||||
|
|
@ -76,7 +80,7 @@ public class HttpFilePage implements HttpPage{
|
|||
HttpHeader headers,
|
||||
Map<String, Object> session,
|
||||
Map<String, String> cookie,
|
||||
Map<String, String> request) throws IOException{
|
||||
Map<String, String> request) {
|
||||
|
||||
try {
|
||||
// Is the root only one file or a folder
|
||||
|
|
@ -95,15 +99,21 @@ public class HttpFilePage implements HttpPage{
|
|||
}
|
||||
// Show folder contents
|
||||
else if (showFolders) {
|
||||
out.println("<HTML><BODY><H1>Directory: " + headers.getRequestURL() + "</H1>");
|
||||
out.println("<HR><UL>");
|
||||
for (String f : file.list()) {
|
||||
out.println("<html>");
|
||||
out.println("<body>");
|
||||
out.println(" <h1>Directory: " + headers.getRequestURL() + "</h1>");
|
||||
out.println(" <hr>");
|
||||
out.println(" <ul>");
|
||||
for (String containingFile : file.list()) {
|
||||
String url = headers.getRequestURL();
|
||||
out.println("<LI><A href='" +
|
||||
url + (url.charAt(url.length()-1)=='/'?"":"/")+ f
|
||||
+"'>" + f + "</A></LI>");
|
||||
out.println(" <li><a href='" +
|
||||
url + (url.endsWith("/") ? "" : "/") + containingFile
|
||||
+"'>" + containingFile + "</a></li>");
|
||||
}
|
||||
out.println("</UL><HR></BODY></HTML>");
|
||||
out.println(" </ul>");
|
||||
out.println(" <hr>");
|
||||
out.println("</body>");
|
||||
out.println("</html>");
|
||||
}
|
||||
else {
|
||||
throw new SecurityException("User not allowed to view folder: root=" + resource_root.getAbsolutePath());
|
||||
|
|
@ -133,13 +143,13 @@ public class HttpFilePage implements HttpPage{
|
|||
|
||||
private void deliverFileWithCache(HttpHeader headers, File file, HttpPrintStream out) throws IOException {
|
||||
String eTag = getFileHash(file);
|
||||
out.setHeader("Cache-Control", "max-age=" + MAX_CACHE_AGE_SECONDS);
|
||||
out.setHeader(HttpHeader.HEADER_CACHE_CONTROL, "max-age=" + MAX_CACHE_AGE_SECONDS);
|
||||
|
||||
if (eTag != null) {
|
||||
out.setHeader("ETag", "\"" + eTag + "\"");
|
||||
|
||||
if (headers.getHeader("If-None-Match") != null &&
|
||||
eTag.equals(StringUtil.trimQuotes(headers.getHeader("If-None-Match")))) { // File has not changed
|
||||
if (headers.getHeader(HttpHeader.HEADER_IF_NONE_MATCH) != null &&
|
||||
eTag.equals(StringUtil.trimQuotes(headers.getHeader(HttpHeader.HEADER_IF_NONE_MATCH)))) { // File has not changed
|
||||
out.setResponseStatusCode(304);
|
||||
} else {
|
||||
deliverFile(file, out);
|
||||
|
|
@ -150,8 +160,8 @@ public class HttpFilePage implements HttpPage{
|
|||
String fileExt = FileUtil.getFileExtension(file);
|
||||
|
||||
if (MimeTypeUtil.getMimeByExtension(fileExt) != null)
|
||||
out.setHeader("Content-Type", MimeTypeUtil.getMimeByExtension(fileExt).toString());
|
||||
out.setHeader("Content-Length", "" + file.length());
|
||||
out.setHeader(HttpHeader.HEADER_CONTENT_TYPE, MimeTypeUtil.getMimeByExtension(fileExt).toString());
|
||||
out.setHeader(HttpHeader.HEADER_CONTENT_LENGTH, "" + file.length());
|
||||
out.flush();
|
||||
|
||||
InputStream in = new FileInputStream(file);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue