diff --git a/src/main/java/org/fungover/storm/client/ClientHandler.java b/src/main/java/org/fungover/storm/client/ClientHandler.java index da8262f5..7168ee90 100644 --- a/src/main/java/org/fungover/storm/client/ClientHandler.java +++ b/src/main/java/org/fungover/storm/client/ClientHandler.java @@ -6,6 +6,7 @@ import org.fungover.storm.filehandler.re.FileNotFoundException; import org.fungover.storm.filehandler.re.FileRequestHandler; import org.fungover.storm.filehandler.re.ResponseCode; +import org.fungover.storm.filehandler.re.Teapot; import java.io.BufferedReader; import java.io.IOException; @@ -26,18 +27,26 @@ public ClientHandler(Socket socket, FileRequestHandler fileRequestHandler) { @Override public void run() { - OutputStream out; - BufferedReader in; + OutputStream out; + BufferedReader in; try { out = clientSocket.getOutputStream(); in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); String input = in.readLine(); - byte[][] response = getResponse(input); + byte[][] response; + + if (Teapot.isCoffeeRequest(HttpParser.getPath(input))) { + response = Teapot.write418Response(); + } else { + response = getResponse(input); + } out.write(response[0]); - out.write(response[1]); + if (response.length > 1 && response[1] != null) { + out.write(response[1]); + } in.close(); out.close(); @@ -54,6 +63,7 @@ private byte[][] getResponse(String input) throws IOException { FileInfo fileInfo; byte[][] response; try { + LOGGER.info("INPUT: " + input); fileInfo = fileRequestHandler.handleRequest(input); response = fileRequestHandler.writeResponse(fileInfo); } catch (FileNotFoundException e) { @@ -64,13 +74,13 @@ private byte[][] getResponse(String input) throws IOException { } private byte[][] getFileNotFoundResponse(FileNotFoundException e) throws IOException { - FileInfo fileInfo; + FileInfo fileInfo = fileRequestHandler.handleError(e.getParsedRequest(), e.getError404FileName(), e.getResponseCode()); byte[][] response; - fileInfo = fileRequestHandler.handleError(e.getParsedRequest(), e.getError404FileName(), e.getResponseCode()); if (Files.exists(fileInfo.getPath())) { response = fileRequestHandler.writeResponse(fileInfo, e.getResponseCode()); - } else + } else { response = fileRequestHandler.writeResponse(e.getResponseCode()); + } return response; } } diff --git a/src/main/java/org/fungover/storm/client/HttpParser.java b/src/main/java/org/fungover/storm/client/HttpParser.java index 396d6035..eaf8e3bd 100644 --- a/src/main/java/org/fungover/storm/client/HttpParser.java +++ b/src/main/java/org/fungover/storm/client/HttpParser.java @@ -10,6 +10,7 @@ public class HttpParser { private HttpParser() { } + public static Map getRequestHeaders(String headers) { List lines = headers.lines().toList(); String[] firstLine = lines.get(0).split(" "); @@ -20,6 +21,18 @@ public static Map getRequestHeaders(String headers) { return Map.of(); } + + public static String getPath(String requestLine) { + String[] properties = requestLine.split(" "); + if (validRequest(properties)) { + return properties[1]; + } else { + return ""; + } + } + + + private static Map requestHeaders(List lines, String[] firstLine) { Map requestHeaders = new HashMap<>(parseFirstLine(firstLine)); lines.stream().skip(1).map(HttpParser::parseHeader).forEach(header -> requestHeaders.put(header[0], header[1])); @@ -40,7 +53,10 @@ private static boolean validRequest(String[] properties) { private static String[] parseHeader(String header) { String[] properties = header.split(":"); - return new String[]{properties[0].trim(), properties[1].trim()}; + if (properties.length >= 2) { + return new String[]{properties[0].trim(), properties[1].trim()}; + } else { + return new String[]{properties[0].trim(), ""}; + } } - } diff --git a/src/main/java/org/fungover/storm/filehandler/re/Teapot.java b/src/main/java/org/fungover/storm/filehandler/re/Teapot.java new file mode 100644 index 00000000..ed125d6f --- /dev/null +++ b/src/main/java/org/fungover/storm/filehandler/re/Teapot.java @@ -0,0 +1,18 @@ +package org.fungover.storm.filehandler.re; + +public class Teapot { + + + public static boolean isCoffeeRequest(String requestPath) { + return "/coffee".equals(requestPath); + } + + + public static byte[][] write418Response() { + String response = "HTTP/1.1 418 I'm a Teapot\r\n" + + "Content-Type: text/plain\r\n" + + "Connection: close\r\n\r\n" + + "418 I'm a teapot."; + return new byte[][]{response.getBytes()}; + } +} \ No newline at end of file diff --git a/src/test/java/org/fungover/storm/filehandler/re/TeapotTest.java b/src/test/java/org/fungover/storm/filehandler/re/TeapotTest.java new file mode 100644 index 00000000..c2c89f91 --- /dev/null +++ b/src/test/java/org/fungover/storm/filehandler/re/TeapotTest.java @@ -0,0 +1,50 @@ +package org.fungover.storm.filehandler.re; + +import org.fungover.storm.client.HttpParser; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import java.util.Map; + +public class TeapotTest { + + @Test + public void testIsCoffeeRequest() { + assertTrue(Teapot.isCoffeeRequest("/coffee")); + assertFalse(Teapot.isCoffeeRequest("/tea")); + } + + @Test + public void testIsCoffeeRequestCaseSensitivity() { + assertFalse(Teapot.isCoffeeRequest("/Coffee"), "Path matching should be case-sensitive."); + } + + @Test + public void testWrite418Response() { + byte[][] response = Teapot.write418Response(); + String responseString = new String(response[0]); + + assertTrue(responseString.startsWith("HTTP/1.1 418 I'm a Teapot"), "Response should start with 418 status code."); + assertTrue(responseString.contains("418 I'm a teapot."), "Response should contain the teapot message."); + } + + @Test + public void testResponseContentType() { + byte[][] response = Teapot.write418Response(); + String responseHeaders = new String(response[0]); + assertTrue(responseHeaders.contains("Content-Type: text/plain"), "Response should specify the correct content type."); + } + + @Test + public void testHttpRequestParsingForCoffee() { + String httpRequest = "GET /coffee HTTP/1.1\r\nHost: localhost\r\n\r\n"; + Map parsedHeaders = HttpParser.getRequestHeaders(httpRequest); + assertTrue(Teapot.isCoffeeRequest(parsedHeaders.get("path")), "The path should be correctly identified from an HTTP request."); + } + + @Test + public void testMalformedHttpRequest() { + String malformedRequest = "GET /coffee"; + Map parsedHeaders = HttpParser.getRequestHeaders(malformedRequest); + assertTrue(parsedHeaders.isEmpty(), "Malformed requests should not produce valid headers."); + } +}