diff --git a/src/zutil/net/http/HttpHeader.java b/src/zutil/net/http/HttpHeader.java index d2b910a..b0ce035 100755 --- a/src/zutil/net/http/HttpHeader.java +++ b/src/zutil/net/http/HttpHeader.java @@ -29,49 +29,69 @@ import zutil.converter.Converter; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; public class HttpHeader { - private boolean request = true; - private String type = "GET"; - private String url = "/"; - private HashMap urlAttributes; + private boolean isRequest = true; + + /** Specifies the protocol that should be used */ + private String protocol = "HTTP"; + /** The protocol version specified in the header */ private float protocolVersion = 1.0f; - private int statusCode = 200; + + /** HTTP type specified in a HTTP request, e.g GET POST DELETE PUT etc */ + private String requestType = "GET"; + /** String containing the target URL */ + private String requestUrl = "/"; + /** Map containing all the properties from the URL */ + private Map requestUrlAttributes = new HashMap<>(); + + /** Status code specified in a HTTP response message */ + private int responseStatusCode = 200; + + /** An Map of all header fields */ + private Map headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + /** An Map of all cookies */ + private Map cookies = new HashMap<>(); + private InputStream in; - // Parameters - private HashMap headers; - private HashMap cookies; - - public HttpHeader() { - urlAttributes = new HashMap<>(); - headers = new HashMap<>(); - cookies = new HashMap<>(); - } + public HttpHeader() { } /** * @return true if this header represents a server response */ public boolean isResponse() { - return !request; + return !isRequest; } /** * @return true if this header represents a client request */ public boolean isRequest() { - return request; + return isRequest; } - /** - * @return the HTTP message type( ex. GET,POST...) - */ - public String getRequestType() { - return type; + public void setIsRequest(boolean request) { + this.isRequest = request; } + + /** + * @return the protocol specified in the header. e.g. HTTP, HTTPS, RTSP etc. + */ + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + /** * @return the protocol version from this header */ @@ -79,51 +99,87 @@ public class HttpHeader { return protocolVersion; } + public void setProtocolVersion(float version) { + this.protocolVersion = version; + } + + + /** + * @return the HTTP message type( ex. GET,POST...) + */ + public String getRequestType() { + return requestType; + } + + public void setRequestType(String type) { + this.requestType = type; + } + + /** * @return the HTTP Return Code from a Server */ - public int getStatusCode() { - return statusCode; + public int getResponseStatusCode() { + return responseStatusCode; } + public void setResponseStatusCode(int code) { + this.responseStatusCode = code; + } + + /** * @return the URL that the client sent the server */ public String getRequestURL() { - return url; + return requestUrl; + } + + public void setRequestURL(String url) { + this.requestUrl = url.trim().replaceAll("//", "/"); } /** * @return parses out the page name from the request url and returns it. */ public String getRequestPage() { - if (url != null) { + if (requestUrl != null) { int start = 0; - if (url.charAt(0) == '/') + if (requestUrl.charAt(0) == '/') start = 1; - int end = url.indexOf('?'); + int end = requestUrl.indexOf('?'); if (end < 0) - end = url.length(); + end = requestUrl.length(); - return url.substring(start, end); + return requestUrl.substring(start, end); } return null; } + /** * @return a Iterator with all defined url keys */ public Iterator getURLAttributeKeys() { - return urlAttributes.keySet().iterator(); + return requestUrlAttributes.keySet().iterator(); } /** * @return the URL attribute value of the given name. null if there is no such attribute */ public String getURLAttribute(String name) { - return urlAttributes.get(name); + return requestUrlAttributes.get(name); } + protected Map getURLAttributeMap() { + return requestUrlAttributes; + } + + public void setURLAttribute(String key, String value) { + this.requestUrlAttributes.put(key, value); + } + + /** * @return a Iterator with all defined headers */ @@ -138,6 +194,19 @@ public class HttpHeader { return headers.get(name.toUpperCase()); } + protected Map getHeaderMap() { + return headers; + } + + public void setHeader(String key, String value) { + this.headers.put(key, value); + } + + public void setHeaders(Map headerSrc) { + this.headers.putAll(headerSrc); + } + + /** * @return a Iterator with all defined cookies */ @@ -152,6 +221,19 @@ public class HttpHeader { return cookies.get(name); } + protected Map getCookieMap() { + return cookies; + } + + public void setCookie(String key, String value) { + this.cookies.put(key, value); + } + + public void setCookies(Map cookieSrc) { + this.cookies.putAll(cookieSrc); + } + + /** * @return a Reader that contains the body of the http request. */ @@ -159,61 +241,20 @@ public class HttpHeader { return in; } - - public void setIsRequest(boolean request) { - this.request = request; - } - - public void setRequestType(String type) { - this.type = type; - } - - public void setProtocolVersion(float version) { - this.protocolVersion = version; - } - - public void setStatusCode(int code) { - this.statusCode = code; - } - - public void setRequestURL(String url) { - this.url = url.trim().replaceAll("//", "/"); - } - - public void setHeader(String key, String value) { - this.headers.put(key.toUpperCase(), value); - } - protected void setInputStream(InputStream in) { this.in = in; } - protected HashMap getHeaderMap() { - return headers; - } - - protected HashMap getCookieMap() { - return cookies; - } - - protected HashMap getUrlAttributeMap() { - return urlAttributes; - } public String toString() { StringBuilder tmp = new StringBuilder(); - tmp.append("{Type: ").append(type); - tmp.append(", HTTP_version: HTTP/").append(protocolVersion); - if (url == null) - tmp.append(", URL: null"); - else - tmp.append(", URL: \"").append(url).append('\"'); - + tmp.append("{Type: ").append(requestType); + tmp.append(", HTTP_version: ").append(protocol).append("/").append(protocolVersion); + tmp.append(", URL: \"").append((String) requestUrl).append('\"'); tmp.append(", URL_attr: ").append(toStringAttributes()); tmp.append(", Headers: ").append(toStringHeaders()); tmp.append(", Cookies: ").append(toStringCookies()); - tmp.append('}'); return tmp.toString(); } @@ -224,7 +265,40 @@ public class HttpHeader { return Converter.toString(cookies); } public String toStringAttributes() { - return Converter.toString(urlAttributes); + return Converter.toString(requestUrlAttributes); } + + public String getResponseStatusString() { + return getResponseStatusString(responseStatusCode); + } + + public static String getResponseStatusString(int type) { + switch (type) { + case 100: + return "Continue"; + case 200: + return "OK"; + case 301: + return "Moved Permanently"; + case 304: + return "Not Modified"; + case 307: + return "Temporary Redirect"; + case 400: + return "Bad Request"; + case 401: + return "Unauthorized"; + case 403: + return "Forbidden"; + case 404: + return "Not Found"; + case 500: + return "Internal Server Error"; + case 501: + return "Not Implemented"; + default: + return ""; + } + } } diff --git a/src/zutil/net/http/HttpHeaderParser.java b/src/zutil/net/http/HttpHeaderParser.java index 1ac6242..f49a068 100755 --- a/src/zutil/net/http/HttpHeaderParser.java +++ b/src/zutil/net/http/HttpHeaderParser.java @@ -107,7 +107,7 @@ public class HttpHeaderParser { if (statusLine.startsWith("HTTP/")) { header.setIsRequest(false); header.setProtocolVersion(Float.parseFloat(statusLine.substring(5, 8))); - header.setStatusCode(Integer.parseInt(statusLine.substring(9, statusLine.indexOf(' ', 9)))); + header.setResponseStatusCode(Integer.parseInt(statusLine.substring(9, statusLine.indexOf(' ', 9)))); } // Client Request else if (statusLine.contains("HTTP/")) { @@ -121,7 +121,7 @@ public class HttpHeaderParser { if (index > -1) { header.setRequestURL(statusLine.substring(0, index)); statusLine = statusLine.substring(index + 1); - parseURLParameters(header.getUrlAttributeMap(), statusLine); + parseURLParameters(header.getURLAttributeMap(), statusLine); } else { header.setRequestURL(statusLine); } @@ -201,7 +201,7 @@ public class HttpHeaderParser { * @param urlAttributes is the String containing all the attributes */ public static void parseURLParameters(HttpHeader header, String urlAttributes) { - parseURLParameters(header.getUrlAttributeMap(), urlAttributes); + parseURLParameters(header.getURLAttributeMap(), urlAttributes); } /** diff --git a/src/zutil/net/http/HttpPrintStream.java b/src/zutil/net/http/HttpPrintStream.java index 3baf7cf..c9c9e0a 100755 --- a/src/zutil/net/http/HttpPrintStream.java +++ b/src/zutil/net/http/HttpPrintStream.java @@ -45,47 +45,19 @@ public class HttpPrintStream extends OutputStream { RESPONSE } - /** - * The actual output stream - */ - private PrintStream out; - /** - * This defines the type of message that will be generated - */ - private final HttpMessageType messageType; - /** - * Specifies the protocol that should be used - */ - private String protocol = "HTTP"; - /** - * Specifies the protocol version that should be used - */ - private String protocolVersion = "1.0"; - /** - * The status code of the message, ONLY for response - */ - private Integer responseStatusCode = 200; - /** - * The request type of the message ONLY for request - */ - private String requestType; - /** - * The requesting url ONLY for request - */ - private String requestUrl; - /** - * An Map of all the header values - */ - private HashMap headers = new HashMap<>(); - /** - * An Map of all the cookies - */ - private HashMap cookies = new HashMap<>(); + + private HttpHeader header = new HttpHeader(); + /** * The header data buffer, buffering is enabled if this variable is not null */ private StringBuffer buffer = null; + /** + * The actual output stream + */ + private PrintStream out; + /** * Creates an new instance of HttpPrintStream with @@ -106,7 +78,7 @@ public class HttpPrintStream extends OutputStream { */ public HttpPrintStream(OutputStream out, HttpMessageType type) { this.out = new PrintStream(out); - this.messageType = type; + header.setIsRequest(type == HttpMessageType.REQUEST); } @@ -129,8 +101,8 @@ public class HttpPrintStream extends OutputStream { /** * Set the http version that will be used in the http header */ - public void setProtocolVersion(String version) { - this.protocolVersion = version; + public void setProtocolVersion(float version) { + header.setProtocolVersion(version); } /** @@ -141,9 +113,9 @@ public class HttpPrintStream extends OutputStream { * @throws IllegalStateException if the header has already been sent */ public void setCookie(String key, String value) { - if (cookies == null) - throw new IllegalStateException("Header already sent"); - cookies.put(key, value); + headerSentCheck(); + + header.setCookie(key, value); } /** @@ -154,9 +126,9 @@ public class HttpPrintStream extends OutputStream { * @throws IllegalStateException if the header has already been sent */ public void setHeader(String key, String value) { - if (headers == null) - throw new IllegalStateException("Header already sent"); - headers.put(key, value); + headerSentCheck(); + + header.setHeader(key, value); } /** @@ -165,12 +137,12 @@ public class HttpPrintStream extends OutputStream { * @param code the code from 100 up to 599 * @throws IllegalStateException if the header has already been sent or the message type is wrong */ - public void setStatusCode(int code) { - if (messageType != HttpMessageType.RESPONSE) + public void setResponseStatusCode(int code) { + if (!header.isResponse()) throw new IllegalStateException("Status Code is only available with HTTP requests"); - if (responseStatusCode == null) - throw new IllegalStateException("Header already sent."); - responseStatusCode = code; + headerSentCheck(); + + header.setResponseStatusCode(code); } /** @@ -180,11 +152,11 @@ public class HttpPrintStream extends OutputStream { * @throws IllegalStateException if the header has already been sent or the message type is wrong */ public void setRequestType(String req_type) { - if (messageType != HttpMessageType.REQUEST) + if (!header.isRequest()) throw new IllegalStateException("Request Message Type is only available with HTTP requests"); - if (req_type == null) - throw new IllegalStateException("Header already sent."); - this.requestType = req_type; + headerSentCheck(); + + header.setRequestType(req_type); } /** @@ -194,19 +166,19 @@ public class HttpPrintStream extends OutputStream { * @throws IllegalStateException if the header has already been sent or the message type is wrong */ public void setRequestURL(String req_url) { - if (messageType != HttpMessageType.REQUEST) + if (!header.isRequest()) throw new IllegalStateException("Request URL is only available with a HTTP request"); - if (req_url == null) - throw new IllegalStateException("Header already sent."); - this.requestUrl = req_url; + headerSentCheck(); + + header.setRequestURL(req_url); } protected void setHeaders(HashMap map) { - headers = map; + header.setHeaders(map); } protected void setCookies(HashMap map) { - cookies = map; + header.setCookies(map); } @@ -246,42 +218,40 @@ public class HttpPrintStream extends OutputStream { * Method will directly print the provided String, if any headers are set then they will firstly be sent and cleared proceeded by the given String. */ private void printForced(String s) { - if (responseStatusCode != null) { - if (messageType == HttpMessageType.REQUEST) - out.print(requestType + " " + requestUrl + " " + protocol + "/" + protocolVersion); + if (header != null) { + if (header.isRequest()) + out.print(header.getRequestType() + " " + header.getRequestURL() + " " + header.getProtocol() + "/" + header.getProtocolVersion()); else - out.print("HTTP/" + protocolVersion + " " + responseStatusCode + " " + getStatusString(responseStatusCode)); + out.print(header.getProtocol() + "/" + header.getProtocolVersion() + " " + header.getResponseStatusCode() + " " + header.getResponseStatusString()); out.println(); - responseStatusCode = null; - requestType = null; - requestUrl = null; - } - if (headers != null) { - for (String key : headers.keySet()) { - out.println(key + ": " + headers.get(key)); + // Send headers + + for (String key : header.getHeaderMap().keySet()) { + out.println(key + ": " + header.getHeader(key)); } - headers = null; - } - if (cookies != null) { - if (!cookies.isEmpty()) { - if (messageType == HttpMessageType.REQUEST) { - out.print("Cookie: "); - for (String key : cookies.keySet()) { - out.print(key + "=" + cookies.get(key) + "; "); + // Send cookies + + if (!header.getCookieMap().isEmpty()) { + if (header.isRequest()) { + out.print("Cookie:"); + for (String key : header.getCookieMap().keySet()) { + out.print(" " + key + "=" + header.getCookie(key) + ";"); } out.println(); } else { - for (String key : cookies.keySet()) { - out.print("Set-Cookie: " + key + "=" + cookies.get(key) + ";"); + for (String key : header.getCookieMap().keySet()) { + out.print("Set-Cookie: " + key + "=" + header.getCookie(key) + ";"); out.println(); } } } out.println(); - cookies = null; + + header = null; } + out.print(s); } @@ -296,7 +266,12 @@ public class HttpPrintStream extends OutputStream { * @return true if headers has been sent. The setHeader, setStatusCode, setCookie method will throw IllegalStateException */ public boolean isHeaderSent() { - return responseStatusCode == null && headers == null && cookies == null; + return header == null; + } + + public void headerSentCheck() { + if (isHeaderSent()) + throw new IllegalStateException("Header already sent."); } @@ -319,7 +294,7 @@ public class HttpPrintStream extends OutputStream { if (isBufferEnabled()) { printForced(buffer.toString()); buffer.delete(0, buffer.length()); - } else if (responseStatusCode != null || headers != null || cookies != null) { + } else if (!isHeaderSent()) { printOrBuffer(""); } } @@ -342,59 +317,13 @@ public class HttpPrintStream extends OutputStream { out.write(buf, off, len); } - private String getStatusString(int type) { - switch (type) { - case 100: - return "Continue"; - case 200: - return "OK"; - case 301: - return "Moved Permanently"; - case 304: - return "Not Modified"; - case 307: - return "Temporary Redirect"; - case 400: - return "Bad Request"; - case 401: - return "Unauthorized"; - case 403: - return "Forbidden"; - case 404: - return "Not Found"; - case 500: - return "Internal Server Error"; - case 501: - return "Not Implemented"; - default: - return ""; - } - } public String toString() { StringBuilder str = new StringBuilder(); - str.append("{http_type: ").append(messageType); - if (responseStatusCode != null) { - if (messageType == HttpMessageType.REQUEST) { - str.append(", req_type: ").append(requestType); - if (requestUrl == null) - str.append(", req_url: null"); - else - str.append(", req_url: \"").append(requestUrl).append('\"'); - } else if (messageType == HttpMessageType.RESPONSE) { - str.append(", status_code: ").append(responseStatusCode); - str.append(", status_str: ").append(getStatusString(responseStatusCode)); - } - - if (headers != null) { - str.append(", Headers: ").append(Converter.toString(headers)); - } - if (cookies != null) { - str.append(", Cookies: ").append(Converter.toString(cookies)); - } - } else - str.append(", HEADER ALREADY SENT "); - str.append('}'); + if (!isHeaderSent()) + str.append(header); + else + str.append("{HEADER ALREADY SENT}"); return str.toString(); } diff --git a/src/zutil/net/http/HttpServer.java b/src/zutil/net/http/HttpServer.java index 908ba9d..45de735 100755 --- a/src/zutil/net/http/HttpServer.java +++ b/src/zutil/net/http/HttpServer.java @@ -210,22 +210,22 @@ public class HttpServer extends ThreadedTCPNetworkServer{ } //**************************** RESPONSE ************************************ - out.setProtocolVersion("1.0"); - out.setStatusCode(200); + out.setProtocolVersion(1.0f); + out.setResponseStatusCode(200); out.setHeader("Server", SERVER_NAME); out.setHeader("Content-Type", "text/html"); if (header.getRequestURL() != null && pages.containsKey(header.getRequestURL())) { HttpPage page = pages.get(header.getRequestURL()); - page.respond(out, header, session, header.getCookieMap(), header.getUrlAttributeMap()); + page.respond(out, header, session, header.getCookieMap(), header.getURLAttributeMap()); if (LogUtil.isLoggable(page.getClass(), Level.FINER)) logRequest(header, session, time); } else if (header.getRequestURL() != null && defaultPage != null) { - defaultPage.respond(out, header, session, header.getCookieMap(), header.getUrlAttributeMap()); + defaultPage.respond(out, header, session, header.getCookieMap(), header.getURLAttributeMap()); if (LogUtil.isLoggable(defaultPage.getClass(), Level.FINER)) logRequest(header, session, time); } else { - out.setStatusCode(404); + out.setResponseStatusCode(404); out.println("404 Page Not Found: " + header.getRequestURL()); logger.warning("Page not defined: " + header.getRequestURL()); } @@ -233,18 +233,15 @@ public class HttpServer extends ThreadedTCPNetworkServer{ } catch (Exception e) { logRequest(header, session, time); logger.log(Level.SEVERE, "500 Internal Server Error", e); - try { - if (!out.isHeaderSent()) - out.setStatusCode(500); - if (e.getMessage() != null) - out.println("500 Internal Server Error: " + e.getMessage()); - else if (e.getCause() != null) { - out.println("500 Internal Server Error: " + e.getCause().getMessage()); - } else { - out.println("500 Internal Server Error: " + e); - } - }catch(IOException ioe){ - logger.log(Level.SEVERE, null, ioe); + + if (!out.isHeaderSent()) + out.setResponseStatusCode(500); + if (e.getMessage() != null) + out.println("500 Internal Server Error: " + e.getMessage()); + else if (e.getCause() != null) { + out.println("500 Internal Server Error: " + e.getCause().getMessage()); + } else { + out.println("500 Internal Server Error: " + e); } } finally { diff --git a/src/zutil/net/http/page/HttpDigestAuthPage.java b/src/zutil/net/http/page/HttpDigestAuthPage.java index 09e57cb..d772b9d 100755 --- a/src/zutil/net/http/page/HttpDigestAuthPage.java +++ b/src/zutil/net/http/page/HttpDigestAuthPage.java @@ -69,12 +69,12 @@ public class HttpDigestAuthPage implements HttpPage{ if (headers.getHeader(HTTP_CLIENT_HEADER) == null || !session.containsKey(AUTH_NONCE)) { session.put(AUTH_NONCE, generateNonce()); - out.setStatusCode(401); + out.setResponseStatusCode(401); out.setHeader(HTTP_AUTH_HEADER, generateAuthHeader((String) session.get(AUTH_NONCE))); out.println("401 Unauthorized"); } else if ( ! headers.getHeader(HTTP_CLIENT_HEADER).startsWith(AUTH_TYPE)){ - out.setStatusCode(501); + out.setResponseStatusCode(501); out.println("501 Not Implemented"); } else{ @@ -91,7 +91,7 @@ public class HttpDigestAuthPage implements HttpPage{ targetPage.respond(out, headers, session, cookie, request); } else{ - out.setStatusCode(403); + out.setResponseStatusCode(403); out.println("403 Forbidden"); } } diff --git a/src/zutil/net/http/page/HttpFilePage.java b/src/zutil/net/http/page/HttpFilePage.java index b48fc6b..276af9b 100755 --- a/src/zutil/net/http/page/HttpFilePage.java +++ b/src/zutil/net/http/page/HttpFilePage.java @@ -122,12 +122,12 @@ public class HttpFilePage implements HttpPage{ }catch (FileNotFoundException | SecurityException e){ if(!out.isHeaderSent()) - out.setStatusCode(404); + out.setResponseStatusCode(404); log.log(Level.WARNING, e.getMessage()); out.println("404 Page Not Found: " + headers.getRequestURL()); } catch (IOException e){ if(!out.isHeaderSent()) - out.setStatusCode(500); + out.setResponseStatusCode(500); log.log(Level.WARNING, null, e); out.println("500 Internal Server Error: "+e.getMessage() ); } @@ -140,7 +140,7 @@ public class HttpFilePage implements HttpPage{ if (eTag != null && headers.getHeader("If-None-Match") != null && eTag.equals(StringUtil.trimQuotes(headers.getHeader("If-None-Match")))){ // File has not changed - out.setStatusCode(304); + out.setResponseStatusCode(304); } else { deliverFile(file, out); } diff --git a/src/zutil/net/http/page/HttpRedirectPage.java b/src/zutil/net/http/page/HttpRedirectPage.java index 25b894e..996cf45 100755 --- a/src/zutil/net/http/page/HttpRedirectPage.java +++ b/src/zutil/net/http/page/HttpRedirectPage.java @@ -32,7 +32,7 @@ public class HttpRedirectPage implements HttpPage{ Map cookie, Map request) throws IOException { - out.setStatusCode((permanent ? 301 : 307)); + out.setResponseStatusCode((permanent ? 301 : 307)); out.setHeader("Location", redirectUrl); out.print( "\n" + diff --git a/src/zutil/net/ssdp/SSDPServer.java b/src/zutil/net/ssdp/SSDPServer.java index a8fa01e..3df11e4 100755 --- a/src/zutil/net/ssdp/SSDPServer.java +++ b/src/zutil/net/ssdp/SSDPServer.java @@ -187,7 +187,7 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork // Generate the SSDP response ByteArrayOutputStream buffer = new ByteArrayOutputStream(); HttpPrintStream http = new HttpPrintStream( buffer ); - http.setStatusCode(200); + http.setResponseStatusCode(200); http.setHeader("Location", services.get(st).getLocation() ); http.setHeader("USN", services.get(st).getUSN() ); http.setHeader("Server", SERVER_INFO ); diff --git a/src/zutil/net/ssdp/StandardSSDPInfo.java b/src/zutil/net/ssdp/StandardSSDPInfo.java index 1aa7274..2e4290e 100755 --- a/src/zutil/net/ssdp/StandardSSDPInfo.java +++ b/src/zutil/net/ssdp/StandardSSDPInfo.java @@ -37,7 +37,7 @@ import java.util.UUID; /** * This class contains information about a service from * or through the SSDP protocol - * + * * @author Ziver */ public class StandardSSDPInfo implements SSDPServiceInfo, SSDPCustomInfo{ @@ -138,11 +138,8 @@ public class StandardSSDPInfo implements SSDPServiceInfo, SSDPCustomInfo{ } @Override public void writeHeaders(HttpPrintStream http) { - try { - for (String key : headers.keySet()) - http.setHeader(key, headers.get(key)); - }catch(IOException e){ - e.printStackTrace(); + for (String key : headers.keySet()) { + http.setHeader(key, headers.get(key)); } } @Override diff --git a/test/zutil/net/http/HttpHeaderTest.java b/test/zutil/net/http/HttpHeaderTest.java new file mode 100644 index 0000000..6b779e7 --- /dev/null +++ b/test/zutil/net/http/HttpHeaderTest.java @@ -0,0 +1,158 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ziver Koc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package zutil.net.http; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class HttpHeaderTest { + + @Test + public void setIsRequest() { + HttpHeader header = new HttpHeader(); + assertTrue(header.isRequest()); + assertFalse(header.isResponse()); + + header.setIsRequest(false); + assertFalse(header.isRequest()); + assertTrue(header.isResponse()); + } + + @Test + public void setProtocol() { + HttpHeader header = new HttpHeader(); + assertEquals("HTTP", header.getProtocol()); + + header.setProtocol("RTSP"); + assertEquals("RTSP", header.getProtocol()); + } + + + @Test + public void setProtocolVersion() { + HttpHeader header = new HttpHeader(); + assertEquals(1.0f, header.getProtocolVersion(), 0); + + header.setProtocolVersion(1.1f); + assertEquals(1.1f, header.getProtocolVersion(), 0); + } + + + @Test + public void setRequestType() { + HttpHeader header = new HttpHeader(); + assertEquals("GET", header.getRequestType()); + + header.setRequestType("POST"); + assertEquals("POST", header.getRequestType()); + } + + + @Test + public void setResponseStatusCode() { + HttpHeader header = new HttpHeader(); + assertEquals(200, header.getResponseStatusCode()); + + header.setResponseStatusCode(400); + assertEquals(400, header.getResponseStatusCode()); + } + + @Test + public void setRequestURL() { + HttpHeader header = new HttpHeader(); + assertEquals("/", header.getRequestURL()); + + header.setRequestURL("/page/test"); + assertEquals("/page/test", header.getRequestURL()); + + header.setRequestURL(" /page/1test "); + assertEquals("/page/1test", header.getRequestURL()); + + header.setRequestURL("/page//2test "); + assertEquals("/page/2test", header.getRequestURL()); + } + + @Test + public void getRequestPage() { + HttpHeader header = new HttpHeader(); + header.setRequestURL("/page/test?param=a&dd=tt"); + assertEquals("page/test", header.getRequestPage()); + } + + + @Test + public void setURLAttribute() { + HttpHeader header = new HttpHeader(); + assertNull(header.getURLAttribute("param1")); + + header.setURLAttribute("param1", "value1"); + assertEquals("value1", header.getURLAttribute("param1")); + assertNull(header.getURLAttribute("Param1")); + } + + + @Test + public void setHeader() { + HttpHeader header = new HttpHeader(); + assertNull(header.getHeader("param1")); + + header.setHeader("param1", "value1"); + header.setHeader("param2", "value2"); + assertEquals("value1", header.getHeader("param1")); + assertEquals("value1", header.getHeader("PARAM1")); + assertEquals("value2", header.getHeader("param2")); + assertEquals("value2", header.getHeader("Param2")); + + header.setHeader("param2", "value3"); + assertEquals("value3", header.getHeader("param2")); + } + + + @Test + public void setCookie() { + HttpHeader header = new HttpHeader(); + assertNull(header.getCookie("param1")); + + header.setCookie("param1", "value1"); + header.setCookie("param2", "value2"); + assertEquals("value1", header.getCookie("param1")); + assertEquals("value2", header.getCookie("param2")); + assertNull("value2", header.getCookie("Param2")); + + header.setCookie("param2", "value3"); + assertEquals("value3", header.getCookie("param2")); + } + + + @Test + public void getResponseStatusString() { + HttpHeader header = new HttpHeader(); + assertEquals("OK", header.getResponseStatusString()); + + header.setResponseStatusCode(400); + assertEquals("Bad Request", header.getResponseStatusString()); + } +} \ No newline at end of file diff --git a/test/zutil/net/http/HttpPrintStreamTest.java b/test/zutil/net/http/HttpPrintStreamTest.java new file mode 100644 index 0000000..56514a9 --- /dev/null +++ b/test/zutil/net/http/HttpPrintStreamTest.java @@ -0,0 +1,198 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020 Ziver Koc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package zutil.net.http; + +import org.junit.Test; +import zutil.io.StringOutputStream; +import zutil.net.http.HttpPrintStream.HttpMessageType; + +import static org.junit.Assert.*; + +public class HttpPrintStreamTest { + + @Test + public void requestDefaultOutput() { + StringOutputStream out = new StringOutputStream(); + HttpPrintStream httpOut = new HttpPrintStream(out, HttpMessageType.REQUEST); + + httpOut.flush(); + assertEquals( + "GET / HTTP/1.0" + System.lineSeparator() + + System.lineSeparator(), + out.toString() + ); + } + + @Test + public void requestSetType() { + StringOutputStream out = new StringOutputStream(); + HttpPrintStream httpOut = new HttpPrintStream(out, HttpMessageType.REQUEST); + + httpOut.setRequestType("POST"); + + httpOut.flush(); + assertEquals( + "POST / HTTP/1.0" + System.lineSeparator() + + System.lineSeparator(), + out.toString() + ); + } + + @Test + public void requestSetUrl() { + StringOutputStream out = new StringOutputStream(); + HttpPrintStream httpOut = new HttpPrintStream(out, HttpMessageType.REQUEST); + + httpOut.setRequestURL("/test/path/to/page?param=aa&tt=aa"); + + httpOut.flush(); + assertEquals( + "GET /test/path/to/page?param=aa&tt=aa HTTP/1.0" + System.lineSeparator() + + System.lineSeparator(), + out.toString() + ); + } + + @Test + public void requestSetCookie() { + StringOutputStream out = new StringOutputStream(); + HttpPrintStream httpOut = new HttpPrintStream(out, HttpMessageType.REQUEST); + + httpOut.setCookie("Test", "value"); + + httpOut.flush(); + assertEquals( + "GET / HTTP/1.0" + System.lineSeparator() + + "Cookie: Test=value;" + System.lineSeparator() + + System.lineSeparator(), + out.toString() + ); + } + + @Test + public void requestSetCookieMultiple() { + StringOutputStream out = new StringOutputStream(); + HttpPrintStream httpOut = new HttpPrintStream(out, HttpMessageType.REQUEST); + + httpOut.setCookie("Test1", "value1"); + httpOut.setCookie("Test2", "value2"); + + httpOut.flush(); + assertEquals( + "GET / HTTP/1.0" + System.lineSeparator() + + "Cookie: Test1=value1; Test2=value2;" + System.lineSeparator() + + System.lineSeparator(), + out.toString() + ); + } + + + @Test + public void responseDefaultOutput() { + StringOutputStream out = new StringOutputStream(); + HttpPrintStream httpOut = new HttpPrintStream(out, HttpMessageType.RESPONSE); + + httpOut.flush(); + assertEquals( + "HTTP/1.0 200 OK" + System.lineSeparator() + + System.lineSeparator(), + out.toString() + ); + } + + @Test + public void responseStatusCode() { + StringOutputStream out = new StringOutputStream(); + HttpPrintStream httpOut = new HttpPrintStream(out, HttpMessageType.RESPONSE); + + httpOut.setResponseStatusCode(400); + + httpOut.flush(); + assertEquals( + "HTTP/1.0 400 Bad Request" + System.lineSeparator() + + System.lineSeparator(), + out.toString() + ); + } + + @Test + public void responseSetCookie() { + StringOutputStream out = new StringOutputStream(); + HttpPrintStream httpOut = new HttpPrintStream(out, HttpMessageType.RESPONSE); + + httpOut.setCookie("Test", "value"); + + httpOut.flush(); + assertEquals( + "HTTP/1.0 200 OK" + System.lineSeparator() + + "Set-Cookie: Test=value;" + System.lineSeparator() + + System.lineSeparator(), + out.toString() + ); + } + + @Test + public void responseSetCookieMultiple() { + StringOutputStream out = new StringOutputStream(); + HttpPrintStream httpOut = new HttpPrintStream(out, HttpMessageType.RESPONSE); + + httpOut.setCookie("Test1", "value1"); + httpOut.setCookie("Test2", "value2"); + + httpOut.flush(); + assertEquals( + "HTTP/1.0 200 OK" + System.lineSeparator() + + "Set-Cookie: Test1=value1;" + System.lineSeparator() + + "Set-Cookie: Test2=value2;" + System.lineSeparator() + + System.lineSeparator(), + out.toString() + ); + } + + + @Test + public void setHeader() { + StringOutputStream out = new StringOutputStream(); + HttpPrintStream httpOut = new HttpPrintStream(out); + + httpOut.setHeader("Test1", "value1"); + httpOut.setHeader("Test2", "value2"); + + httpOut.flush(); + assertEquals( + "HTTP/1.0 200 OK" + System.lineSeparator() + + "Test1: value1" + System.lineSeparator() + + "Test2: value2" + System.lineSeparator() + + System.lineSeparator(), + out.toString() + ); + } + + + // TODO @Test + public void enableBuffering() { + + } +} \ No newline at end of file diff --git a/test/zutil/net/http/HttpTestUtil.java b/test/zutil/net/http/HttpTestUtil.java index a67d70a..d20a8f6 100755 --- a/test/zutil/net/http/HttpTestUtil.java +++ b/test/zutil/net/http/HttpTestUtil.java @@ -20,8 +20,9 @@ public class HttpTestUtil { public static HttpHeader makeRequest(HttpPage page, HttpHeader headers) throws IOException { StringOutputStream buff = new StringOutputStream(); HttpPrintStream out = new HttpPrintStream(buff); - page.respond( - out, headers, session, new HashMap(), new HashMap()); + + page.respond(out, headers, session, new HashMap(), new HashMap()); + out.flush(); HttpHeaderParser parser = new HttpHeaderParser(buff.toString()); return parser.read(); diff --git a/test/zutil/net/http/page/HttpDigestAuthPageTest.java b/test/zutil/net/http/page/HttpDigestAuthPageTest.java index a89a705..25ec43f 100755 --- a/test/zutil/net/http/page/HttpDigestAuthPageTest.java +++ b/test/zutil/net/http/page/HttpDigestAuthPageTest.java @@ -36,7 +36,7 @@ public class HttpDigestAuthPageTest { public void cleanRequest() throws IOException { HttpHeader rspHeader = HttpTestUtil.makeRequest(page); - assertEquals(401, rspHeader.getStatusCode()); + assertEquals(401, rspHeader.getResponseStatusCode()); assertNotNull(rspHeader.getHeader("WWW-Authenticate")); assertEquals("Digest", parseAuthType(rspHeader)); Map authHeader = parseAuthHeader(rspHeader); @@ -49,21 +49,21 @@ public class HttpDigestAuthPageTest { @Test public void authenticate() throws IOException { HttpHeader rspHeader = authenticate(PAGE_USERNAME, PAGE_PASSWORD); - assertEquals(200, rspHeader.getStatusCode()); + assertEquals(200, rspHeader.getResponseStatusCode()); assertThat(IOUtil.readContentAsString(rspHeader.getInputStream()), containsString(PAGE_CONTENT)); } @Test public void wrongUsername() throws IOException { HttpHeader rspHeader = authenticate(PAGE_USERNAME+"wrong", PAGE_PASSWORD); - assertEquals(403, rspHeader.getStatusCode()); + assertEquals(403, rspHeader.getResponseStatusCode()); assertThat(IOUtil.readContentAsString(rspHeader.getInputStream()), not(containsString(PAGE_CONTENT))); } @Test public void wrongPassword() throws IOException { HttpHeader rspHeader = authenticate(PAGE_USERNAME, PAGE_PASSWORD+"wrong"); - assertEquals(403, rspHeader.getStatusCode()); + assertEquals(403, rspHeader.getResponseStatusCode()); assertThat(IOUtil.readContentAsString(rspHeader.getInputStream()), not(containsString(PAGE_CONTENT))); }