Skip to content

Instantly share code, notes, and snippets.

@svenoaks
Last active August 29, 2015 13:56
Show Gist options
  • Save svenoaks/9148060 to your computer and use it in GitHub Desktop.
Save svenoaks/9148060 to your computer and use it in GitHub Desktop.
A very primitive Java web server
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