Last active
August 29, 2015 13:56
-
-
Save svenoaks/9148060 to your computer and use it in GitHub Desktop.
A very primitive Java web server
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.BufferedReader; | |
import java.io.BufferedWriter; | |
import java.io.FileNotFoundException; | |
import java.io.FileReader; | |
import java.io.IOException; | |
import java.io.InputStreamReader; | |
import java.io.OutputStreamWriter; | |
import java.net.ServerSocket; | |
import java.net.Socket; | |
import java.nio.CharBuffer; | |
import java.text.DateFormatSymbols; | |
import java.text.SimpleDateFormat; | |
import java.util.Date; | |
import java.util.Locale; | |
import java.util.TimeZone; | |
public class WebServer | |
{ | |
public static void main(String[] args) | |
{ | |
WebServer server = null; | |
try | |
{ | |
server = new WebServer(); | |
} | |
catch (IOException e1) | |
{ | |
e1.printStackTrace(); | |
System.exit(1); | |
} | |
while (true) | |
{ | |
try | |
{ | |
server.awaitConnection(); | |
if (!server.isClosed()) | |
{ | |
server.processRequest(); | |
} | |
} | |
catch (IOException e) | |
{ | |
e.printStackTrace(); | |
} | |
catch (InvalidRequestException e) | |
{ | |
e.printStackTrace(); | |
} | |
finally | |
{ | |
try | |
{ | |
server.closeClient(); | |
} | |
catch (IOException e) | |
{ | |
e.printStackTrace(); | |
} | |
} | |
} | |
} | |
private static final int START_LINE_TOKENS = 3; | |
private static final String END_OF_HEADER = ""; | |
private static final String HTTP = "HTTP/1.1"; | |
private static final String METHOD_GET = "GET"; | |
private static final String ENCODING = "UTF-8"; | |
private static final String CONTENT_TYPE = "Content-Type: text/plain; charset=" + ENCODING; | |
private static final String CONTENT_LENGTH = "Content-Length: "; | |
private static final String DATE = "Date: "; | |
private Socket clientSocket; | |
private ServerSocket serverSocket; | |
class RequestParams | |
{ | |
public RequestParams(String method, String dir, String http) | |
{ | |
this.method = method.toUpperCase(); | |
this.dir = dir.toLowerCase(); | |
this.http = http.toUpperCase(); | |
} | |
public String getMethod() | |
{ | |
return method; | |
} | |
public String getDir() | |
{ | |
return dir; | |
} | |
public String getHttp() | |
{ | |
return http; | |
} | |
String method; | |
String dir; | |
String http; | |
public boolean validate() | |
{ | |
return method != null && dir != null && http != null && | |
method.equals(METHOD_GET) && dir.startsWith("/") && | |
http.equals(HTTP); | |
} | |
} | |
class InvalidRequestException extends Exception | |
{} | |
WebServer() throws IOException | |
{ | |
serverSocket = new ServerSocket(8080); | |
} | |
void awaitConnection() throws IOException | |
{ | |
clientSocket = serverSocket.accept(); | |
} | |
boolean isClosed() | |
{ | |
return clientSocket.isClosed(); | |
} | |
void closeClient() throws IOException | |
{ | |
clientSocket.close(); | |
} | |
void closeServer() throws IOException | |
{ | |
serverSocket.close(); | |
} | |
private void processRequest() throws IOException, InvalidRequestException | |
{ | |
if (clientSocket != null) | |
{ | |
String request = readRequest(); | |
System.out.println(request); | |
if (request.equals("")) | |
{ | |
return; //nothing to process. | |
} | |
RequestParams params = parseRequest(request); | |
String dir = params.getDir(); | |
switch (dir) | |
{ | |
case ("/"): | |
case("/latin.txt"): | |
issueResponse(dir, true); | |
break; | |
case ("/fail"): | |
default: | |
issueResponse(dir, false); | |
} | |
} | |
} | |
private void issueResponse(String dir, boolean success) throws IOException | |
{ | |
try (BufferedWriter buf = new BufferedWriter | |
(new OutputStreamWriter(clientSocket.getOutputStream(), ENCODING))) | |
{ | |
String statusCode = null; | |
String statusResponse = null; | |
String message = null; | |
if (success) | |
{ | |
statusCode = "200"; | |
statusResponse = "Ok"; | |
message = "Success!! You connected to Steve's primitive web server.\n"; | |
} | |
else | |
{ | |
statusCode = "404"; | |
statusResponse = "Not Found"; | |
message = "Failure, resource not found."; | |
} | |
if (success && !dir.equals("/")) message += readText(dir); | |
long cLength = message.getBytes(ENCODING).length; | |
String now = generateDate(); | |
buf.write(HTTP + " " + statusCode + " " + statusResponse); | |
buf.write(System.lineSeparator()); | |
buf.write(CONTENT_TYPE); | |
buf.write(System.lineSeparator()); | |
buf.write(CONTENT_LENGTH + cLength); | |
buf.write(System.lineSeparator()); | |
buf.write(DATE + now); | |
buf.write(System.lineSeparator()); | |
buf.write(System.lineSeparator()); | |
buf.write(message); | |
buf.flush(); | |
} | |
} | |
private String readText(String dir) | |
{ | |
CharBuffer buf = CharBuffer.allocate(5000); | |
try (FileReader fr = new FileReader(dir.substring(1));) | |
{ | |
fr.read(buf); | |
} | |
catch (FileNotFoundException e) | |
{ | |
e.printStackTrace(); | |
} | |
catch (IOException e1) | |
{ | |
e1.printStackTrace(); | |
} | |
return buf.flip().toString(); | |
} | |
private String generateDate() | |
{ | |
SimpleDateFormat formatter = | |
new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss zzz", new DateFormatSymbols(Locale.US)); | |
formatter.setTimeZone(TimeZone.getTimeZone("GMT")); | |
return formatter.format(new Date()); | |
} | |
private RequestParams parseRequest(String request) throws InvalidRequestException | |
{ | |
int f = request.indexOf(System.lineSeparator()); | |
if (f < 0) | |
{ | |
throw new InvalidRequestException(); | |
} | |
String firstLine = request.substring(0, f); | |
String[] tokens = firstLine.split(" "); | |
if (tokens.length != START_LINE_TOKENS) | |
{ | |
throw new InvalidRequestException(); | |
} | |
RequestParams result = new RequestParams(tokens[0], tokens[1], tokens[2]); | |
if (!result.validate()) | |
{ | |
throw new InvalidRequestException(); | |
} | |
return result; | |
} | |
private String readRequest() throws IOException | |
{ | |
String line = null; | |
StringBuilder result = new StringBuilder(); | |
BufferedReader buf = new BufferedReader | |
(new InputStreamReader(clientSocket.getInputStream())); | |
while (true) | |
{ | |
line = buf.readLine(); | |
if (line == null || line.equals(END_OF_HEADER)) | |
break; | |
result.append(line); | |
result.append(System.lineSeparator()); | |
} | |
return result.toString(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment