Skip to content

Instantly share code, notes, and snippets.

@weburnit
Created November 20, 2018 17:26
Show Gist options
  • Save weburnit/8a147a9e2e6baa2dfeee792b857e7a55 to your computer and use it in GitHub Desktop.
Save weburnit/8a147a9e2e6baa2dfeee792b857e7a55 to your computer and use it in GitHub Desktop.
WebServer.java
import java.io.*;
import java.net.*;
import java.util.ArrayList;
class WebServer {
// this is the port the web server listens on
private static final int PORT_NUMBER = 8080;
// main entry point for the application
public static void main(String args[]) {
try {
// open socket
ServerSocket serverSocket = new ServerSocket(PORT_NUMBER);
// start listener thread
Thread listener = new Thread(new SocketListener(serverSocket));
listener.start();
// message explaining how to connect
System.out.println("To connect to this server via a web browser, try \"http://127.0.0.1:8080/{url to retrieve}\"");
// wait until finished
System.out.println("Press enter to shutdown the web server...");
// kill listener thread
listener.interrupt();
} catch (Exception e) {
System.err.println("WebServer::main - " + e.toString());
}
}
}
class SocketListener implements Runnable {
private ServerSocket serverSocket;
public SocketListener(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
}
// this thread listens for connections, launches a seperate socket connection
// thread to interact with them
public void run() {
while (true) {
try {
Socket clientSocket = serverSocket.accept();
Thread connection = new Thread(new SocketConnection(clientSocket));
connection.start();
Thread.yield();
} catch (IOException e) {
if (!this.serverSocket.isClosed()) {
System.err.println("SocketListener::run - " + e.toString());
}
}
}
}
}
class HttpRequest {
private String method;
private String path;
public HttpRequest() {
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
class SocketConnection implements Runnable {
private final String HTTP_LINE_BREAK = "\r\n";
private Socket clientSocket;
public SocketConnection(Socket clientSocket) {
this.clientSocket = clientSocket;
}
// one of these threads is spawned and used to talk to each connection
public void run() {
try {
BufferedReader request = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
PrintWriter response = new PrintWriter(this.clientSocket.getOutputStream(), true);
this.handleConnection(request, response);
} catch (Exception e) {
System.err.println("SocketConnection::run - " + e.toString());
}
}
// TODO: implement your HTTP protocol for this server within this method
private void handleConnection(BufferedReader reader, PrintWriter response) throws IOException {
try {
/*
*
* TODO: implement your web server here
*
* Tasks:
* ------
* 1.) Figure out how to parse the HTTP reader header
* 2.) Figure out how to open files
* 3.) Figure out how to create an HTTP responseHtml header
* 4.) Figure out how to return resources (i.e. files)
*
*/
// EXAMPLE: code prints the web reader
HttpRequest request = this.readHTTPHeader(reader, new HttpRequest());
ArrayList<String> folders = new ArrayList<>();
folders.add("add");
folders.add("helloworld");
folders.add("subdirectory");
// Start sending our reply, using the HTTP 1.1 protocol
response.print("HTTP/1.1 200 \r\n"); // Version & status code
response.print("Content-Type: text/html; charset=utf-8\r\n"); // The type of data
response.print("Connection: close\r\n"); // Will close stream
response.print("\r\n"); // End of headers
if (folders.contains(request.getPath().replaceFirst("/", ""))) {
if (request.getPath().replace("/", "").equals("subdirectory")) {
response.print(responseDirectory(null));
} else response.println(this.responseHtmlFile(request.getPath()));
} else if (request.getPath().contains("subdirectory")) {
response.print(responseDirectory(request.getPath().replace("/subdirectory/", "")));
} else {
StringBuilder builder = new StringBuilder();
builder.append("<a href=\"/add\">add</a><br>");
builder.append("<a href=\"/helloworld\">helloworld</a><br>");
builder.append("<a href=\"/subdirectory\">subdirectory</a><br>");
response.print(builder.toString());
}
response.close();
reader.close();
} finally {
// close the socket, no keep alives
this.clientSocket.close();
}
}
private String responseDirectory(String sub) throws IOException {
if (sub == null) {
StringBuilder builder = new StringBuilder();
String dir = System.getProperty("user.dir") + "/" + "webroot" + "/subdirectory";
File directory = new File(dir);
//get all the files from a directory
File[] fList = directory.listFiles();
for (File file : fList) {
if (file.isFile()) {
builder.append("<a href=\"/subdirectory/" + file.getName() + "\">" + file.getName() + "</a><br>");
}
}
return builder.toString();
}
return responseHtml(System.getProperty("user.dir") + "/" + "webroot" + "/subdirectory/" + sub);
}
private String responseHtmlFile(String path) throws IOException {
String dir = System.getProperty("user.dir") + "/" + "webroot" + "/" + path + "/" + "index.html";
return responseHtml(dir);
}
private String responseHtml(String dir) throws IOException {
FileReader fr = new FileReader(dir);
BufferedReader br = new BufferedReader(fr);
String sCurrentLine;
StringBuilder content = new StringBuilder();
try {
while ((sCurrentLine = br.readLine()) != null) {
content.append(sCurrentLine);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
br.close();
fr.close();
}
return content.toString();
}
private HttpRequest readHTTPHeader(BufferedReader reader, HttpRequest request) {
String message = "";
String line = "";
int read = 0;
while ((line != null) && (!line.equals(this.HTTP_LINE_BREAK))) {
line = this.readHTTPHeaderLine(reader);
if (read == 0) {
String[] data = line.split(" ");
request.setMethod(data[0]);
request.setPath(data[1]);
}
message += line;
read++;
}
return request;
}
private String readHTTPHeaderLine(BufferedReader reader) {
String line = "";
try {
line = reader.readLine() + this.HTTP_LINE_BREAK;
} catch (IOException e) {
System.err.println("SocketConnection::readHTTPHeaderLine: " + e.toString());
line = "";
}
return line;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment