Created
April 21, 2020 10:49
-
-
Save Tiefseetauchner/33b62ea820d1c853fac3af15a3acfbe9 to your computer and use it in GitHub Desktop.
Webserver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.*; | |
import java.net.ServerSocket; | |
import java.net.Socket; | |
import java.nio.charset.StandardCharsets; | |
import java.nio.file.Files; | |
import java.nio.file.Paths; | |
import java.util.*; | |
public class WebServer { | |
public static int PORT = 8080; | |
public static Map<String, Long> accesses; | |
public static void main(String[] args) { | |
try (ServerSocket server = new ServerSocket(PORT)) { | |
System.out.println("Server started on port " + PORT); | |
accesses = new HashMap<>(); | |
while (true) { | |
Socket socket = server.accept(); | |
new Thread(() -> | |
{ | |
try ( | |
Writer w = new OutputStreamWriter(socket.getOutputStream()); | |
DataOutputStream dw = new DataOutputStream(socket.getOutputStream()); | |
BufferedWriter bw = new BufferedWriter(w); | |
Reader r = new InputStreamReader(socket.getInputStream()); | |
BufferedReader br = new BufferedReader(r) | |
) { | |
System.out.println("Connection established on port " + socket.getPort()); | |
String line = br.readLine(); | |
if (!isValidRequest(line)) { | |
System.out.println("Invalid Request from port " + socket.getPort()); | |
System.out.println("Connection closed on port " + socket.getPort()); | |
sendHeader(500, bw); | |
return; | |
} | |
String path = line.substring(4, line.lastIndexOf("HTTP") - 1); | |
System.out.println("Request for " + path + " from port " + socket.getPort()); | |
if (path.startsWith("/static")) { | |
switch (path.substring(path.lastIndexOf(".") + 1)) { | |
case "html": | |
sendHeader(200, bw); | |
try (BufferedReader in = Files.newBufferedReader( | |
Paths.get(path.replace("/static", "resources")), | |
StandardCharsets.UTF_8) | |
) { | |
String readLine; | |
StringBuilder text = new StringBuilder(); | |
while ((readLine = in.readLine()) != null) { | |
text.append(readLine); | |
} | |
sendMessage(text.toString(), bw); | |
} | |
break; | |
case "png": | |
sendHeader(200, bw, "image/png"); | |
try (InputStream in = Files.newInputStream( | |
Paths.get(path.replace("/static", "resources"))) | |
) { | |
sendRawMessage(in.readAllBytes(), dw); | |
} | |
break; | |
case "jpg": | |
case "jpeg": | |
sendHeader(200, bw, "image/jpeg"); | |
try (InputStream in = Files.newInputStream( | |
Paths.get(path.replace("/static", "resources"))) | |
) { | |
sendRawMessage(in.readAllBytes(), dw); | |
} | |
break; | |
} | |
} else { | |
switch (path) { | |
case "/": | |
sendHeader(303, bw, "index.html"); | |
break; | |
case "/index.html": | |
sendHeader(200, bw); | |
sendMessage("<h1>Main Page, boring</h1>\n" + | |
"<a href=\"counter\">Counter</a><br>\n" + | |
"<a href=\"time\">Time</a><br>\n" + | |
"<img src=\"/static/image.png\"", bw); | |
break; | |
case "/time": | |
sendHeader(200, bw); | |
sendMessage("<h1>It's " + new Date(System.currentTimeMillis()) + "</h1>", bw); | |
break; | |
case "/counter": | |
sendHeader(200, bw); | |
StringBuilder accessesHTML = new StringBuilder(); | |
for (String key : accesses.keySet()) { | |
accessesHTML | |
.append("<tr style=\"background-color: #dddddd\">" + "<th>") | |
.append(key) | |
.append("</th>").append("<th>") | |
.append(accesses.get(key)) | |
.append("</th>") | |
.append("</tr>"); | |
} | |
sendMessage("<h1>Counter</h1>" + | |
"<table>" + | |
"<tr style=\"background-color: #aaaaaa\">" + | |
"<th>Website</th>" + | |
"<th>Accesses</th>" + | |
"</tr>" + | |
accessesHTML + | |
"</table>", bw); | |
break; | |
default: | |
sendHeader(404, bw); | |
sendMessage("<h1>404</h1>\n" | |
+ "<p>\"<b>" + path + "</b>\" wasn't found in our vast databases</p>\n", bw); | |
} | |
} | |
if (accesses.containsKey(path)) { | |
accesses.put(path, accesses.get(path) + 1); | |
} else { | |
accesses.put(path, 0L); | |
} | |
bw.flush(); | |
System.out.println("Connection closed on port " + socket.getPort()); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
}).start(); | |
} | |
} catch ( | |
IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
private static boolean isValidRequest(String line) { | |
return line.matches("GET [/\\p{L} \\d.]*? HTTP/\\d\\.?\\d?"); | |
} | |
private synchronized static void sendMessage(String message, BufferedWriter bw) throws IOException { | |
bw.write("<html>\n" + | |
"<header>\n" + | |
"<title>SEW</title>\n" + | |
"</header>\n" + | |
"<body>\n" + | |
message + | |
"</body>\n" + | |
"</html>"); | |
bw.flush(); | |
} | |
private synchronized static void sendRawMessage(byte[] message, DataOutputStream dw) throws IOException { | |
dw.write(message); | |
dw.flush(); | |
} | |
private synchronized static void sendHeader(int code, BufferedWriter bw) throws IOException { | |
switch (code) { | |
case 200: | |
bw.write("HTTP/1.1 200 OK\n" | |
+ "Connection: close\n" | |
+ "Content-Type: text/html\n\n"); | |
break; | |
case 404: | |
bw.write("HTTP/1.1 404 NOT FOUND\n" | |
+ "Connection: close\n" | |
+ "Content-Type: text/html\n\n"); | |
break; | |
case 303: | |
bw.write("HTTP/1.1 303 See Other\n" | |
+ "Location: /\n"); | |
break; | |
case 500: | |
bw.write("HTTP/1.1 500 Internal Server Error\n"); | |
break; | |
default: | |
System.err.println("Unknown Response Code: " + code); | |
} | |
} | |
private synchronized static void sendHeader(int code, BufferedWriter bw, String advancedResponseContent) throws IOException { | |
switch (code) { | |
case 200: | |
bw.write("HTTP/1.1 200 OK\n" | |
+ "Connection: close\n" | |
+ "Content-Type: " + advancedResponseContent + "\n\n"); | |
break; | |
case 404: | |
bw.write("HTTP/1.1 404 NOT FOUND\n" | |
+ "Connection: close\n" | |
+ "Content-Type: " + advancedResponseContent + "\n\n"); | |
break; | |
case 303: | |
bw.write("HTTP/1.1 303 See Other\n" | |
+ "Location: /" + advancedResponseContent + "\n"); | |
break; | |
default: | |
System.err.println("Unknown Response Code"); | |
} | |
bw.flush(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment