commit 8c9185f70eacc419ad85aba20515901cccdae43d
parent 7d35ee0a660d42c90007541c5a416a7914756854
Author: Jake Bauer <jbauer@paritybit.ca>
Date: Sun, 21 May 2023 13:42:56 -0400
Write very simple webserver, capable of serving GET requests
Diffstat:
2 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/webserver/Main.java b/webserver/Main.java
@@ -0,0 +1,62 @@
+import java.net.*;
+import java.io.*;
+import java.nio.file.*;
+
+public class Main {
+ private static void handleRequest(Socket client) throws IOException {
+ BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
+ StringBuilder requestReader = new StringBuilder();
+
+ String line;
+ while (!(line = in.readLine()).isBlank()) {
+ requestReader.append(line + "\r\n");
+ }
+
+ // Headers not considered
+ String[] request = requestReader.toString().split("\r\n");
+ String method = request[0].split(" ")[0];
+ String path = request[0].split(" ")[1];
+ System.out.println(method + " " + path);
+
+ // Serve the requested page or 404
+ Path filePath = getFilePath(path);
+ if (Files.exists(filePath)) {
+ String contentType = Files.probeContentType(filePath);
+ sendResponse(client, "200 OK", contentType, Files.readAllBytes(filePath));
+ }
+ else {
+ byte[] message = "<h1>404 File Not Found</h1>".getBytes();
+ sendResponse(client, "404 Not Found", "text/html", message);
+ }
+ }
+
+ private static void sendResponse(Socket client, String status,
+ String contentType, byte[] content) throws IOException {
+ OutputStream out = client.getOutputStream();
+ out.write(("HTTP/1.1 " + status + "\r\n").getBytes());
+ out.write(("ContentType: " + contentType + "\r\n").getBytes());
+ out.write("\r\n".getBytes());
+ out.write(content);
+ out.write("\r\n\r\n".getBytes());
+ out.flush();
+ client.close();
+ }
+
+ private static Path getFilePath(String path) {
+ if ("/".equals(path)) {
+ path = "/index.html";
+ }
+ return Paths.get("./", path);
+ }
+
+ public static void main(String[] args) throws Exception{
+ // Listen using socket
+ try (ServerSocket server = new ServerSocket(8080)) {
+ while (true) {
+ try (Socket client = server.accept()) {
+ handleRequest(client);
+ }
+ }
+ }
+ }
+}
diff --git a/webserver/index.html b/webserver/index.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAABX1BMVEUAAAABAAAAAAAAAAAAAAAAAAAAAAC7amoAAABlPz8AAAAAAAAGAwMAAAAAAAAAAAC7d3cKBwe7d3e7d3eWX1/ny4+WX18CAQGHVlaTXl4BAAApGhpiPj7ny4/ny4/oy4/ozI/qz5Ona2u7d3d4TEzny48MCAhlQEC7d3e7d3cAAAAAAAC7d3e8d3cAAAC8d3fnzI+8dnYAAADpzJC9eHjny4+WX1+TXV13S0u7d3fny492S0vnzI/ny4+EU1PnzI8mFxe7d3cjFhZgPT3ny5AAAAC7d3fny4+7d3cAAADozJC6d3e7d3cAAADozI/my5Dny44AAAAAAAC7d3e4d3fkx5DpzY69c3O7d3eoamroy4+FVVWEVFR0Skq7d3e7d3e8d3cAAAC6eHi7eHi7eHi8dna8dnYAAADozJAAAADkyY28eXnqyJHqzY63eHi/dXXny48AAAC7d3e5dXW2dHSjLYEdAAAAcHRSTlMA9cj58gYaBOrflhjq44MI/ePbaP348u/u6Oba1sW+oosL/Pbv7ejnyLuXlI54RkM8Oy4iG/v38efl4ODf2tfT09LQz87FwbeimJeJf397ZUlIRTQvGxYP9/Xv4ODZz86yk4JxYlRQSjctJiYlJCAYM3tXUgAAAg1JREFUOMttk1V3ImEQRO8MQ3CChACBIHF3l427+7q7Tjfz/88+sNhk67Vuf3K6CuryXo2Yfo/HbwYnvDxW25EldVnBNpfdHjVErO2dJ9nsk51tS8SItreMmyLxV46qakxVndW4iNl0yExEjHxFEyfTcz7f3PT7La0EDInM1PxQRMJZTSQbE5OvtbNLuv6d0W5K1zM99DXf6RvTnrCY1XdExcjqKcD9RbFQKF7cAyS105AoQJsheT0EyqWUbdu2badKZeBEA2KFgCOJVxI+uNu169q9A4YqAxIEryWr+hnKG3aTNsowrX2S9vJFLGcLOLZbdAwMO4ZMMCKbegq/5luB+VlIak6CmJLXGzi3XTqHOQ2IiV9e6gMU3EABeJoRPx7p7AXW3cA6kOgQTw1YcwNrNcAvL/QBut1AN9CbET+m5PUWSm6gBH90UEyCsqnjMOUGvsJHzckoV2I4Q8BBq38AvHUMucZryZJOwmx/s98/C7exPkl7YUTilTc+mHre5E8Bw5UBGa2uO6BjwPf6T7p/AuM6WF03UTEWNQlwWVxJpVaKlwCfYgseOatFLtyjYy2RYzzWE5Y9byO0izo02bBv9nUhXA9tNfaBiu5/+OED3+/ksFYGPRL55irOkqOqy8sxVadvQGQv9Kh6Ri6Q6ejIBHKGiHXmLnAomG6UNz0a+k+/vRPBav3fXTdN/wUXrszXABeiEwAAAABJRU5ErkJggg==">
+ <title>Hello, World!</title>
+<style>body{background-color:#fcfcfc;color:#111;line-height:1.4em;max-width:38em;margin:auto;padding-bottom:2em;font-family:"IBM Plex Serif", serif}header{text-align:center;margin:0.7em;font-size:2em;font-weight:bold}h1{font-style:oblique;margin-bottom:0;font-size:1.7em}h2,h3,h4,h5,h6{margin:1em 0 -0.2em;line-height:1.1em}nav{text-align:center}nav a{padding:0 0.5em;font-size:1.1em;font-weight:bold;text-decoration:none}nav a:hover{text-decoration:underline}a,nav a:visited{color:#134799}a:hover{text-decoration:none}a:visited{color:#551a8b}article a[href^="http"]:where(:not([href*="paritybit.ca/"]))::after{content:"︎↗"}figure a::after{content:""!important}img,video{max-width:100%}figcaption{text-align:center}blockquote{border-left:3px solid #134799;padding-left:0.5em}cite{margin-left:40px}summary:hover{cursor:pointer;background-color:#ddd}table{width:100%;text-align:left}table,td,th{border-collapse:collapse;border:1px solid #ddd;margin-top:1em;padding:2px 4px;vertical-align: top}th{background-color:#ddd}tr:nth-child(even){background-color:#eee}pre{background-color:#ddd;overflow:auto;padding:0.5em;border:1px black solid}code{background-color:#ddd;font-family:"IBM Plex Mono", monospace;font-size:0.9em}.note{border:3px solid #134799;margin:0.7em 0}.note p{margin:0.7em 0.9em}figcaption,.date{font-size:smaller;color:#565151}#icons{float:right}@media print{pre{white-space:pre-wrap}nav{display:none}}@media only screen and (max-width: 700px){body{max-width:90%}#icons{float:none}}</style>
+</head>
+<body>
+ <h1>Hello, World!</h1>
+
+ <p>The server works!</p>
+</body>
+</html>