Skip to content

Instantly share code, notes, and snippets.

@Tiefseetauchner
Created April 21, 2020 10:49
Show Gist options
  • Save Tiefseetauchner/33b62ea820d1c853fac3af15a3acfbe9 to your computer and use it in GitHub Desktop.
Save Tiefseetauchner/33b62ea820d1c853fac3af15a3acfbe9 to your computer and use it in GitHub Desktop.
Webserver
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