I have implemented a simple HTTP server which can process GET
and POST
requests from the client. I have written it in Java. For the client part, I just simply type in localhost:8080(file_name_here.file_type_here)
in the browser. For the GET
request, the server tries to find the requested file in the directory. If it finds it successfully, it shows the file on the browser and shows an error message if it fails to do so. For the POST
request the server simply collects a username from a HTTP post form and shows the username in a HTML page. Any sort of constructive criticism on the code design or structure will be appreciated.
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Date;
public class HTTPServer {
static Writer writer;
private static ServerSocket serverConnect;
private static final int PORT = 8080;
static int id = 0;
private static void serverSocketCreate(){
try {
serverConnect = new ServerSocket(PORT);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Server started.\nListening for connections on port : " + PORT + " ...\n");
}
private static void logFileCreate(){
File logFile = new File("log.txt");
boolean result = false;
try {
result = Files.deleteIfExists(logFile.toPath());
if(result) logFile.createNewFile();
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(logFile), StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
serverSocketCreate();
logFileCreate();
while(true)
{
Socket s = serverConnect.accept();
WorkerThread wt = new WorkerThread(s);
Thread t = new Thread(wt);
t.start();
System.out.println("Thread number is: " + id);
}
}
}
class Information{
private String method;
private String fileName;
private String fileType;
public Information(){
method = fileName = fileType = "";
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
}
class WorkerThread implements Runnable{
private Socket s;
private BufferedReader in;
private DataOutputStream out;
private static String MIME_TYPE;
private static final String SUCCESS_HEADER = "HTTP/1.1 200 OK\r\n";
private static final String ERROR_HEADER = "HTTP/1.1 404 Not Found\r\n";
private static final String OUTPUT_HEADERS = "Content-Type: " + MIME_TYPE + "\r\nContent-Length: ";
private static final String OUTPUT_END_OF_HEADERS = "\r\n\r\n";
private static final String FILE_NOT_FOUND = "<html>\n<head>\n<title>\nError\n</title>\n</head>\n<body>\n<p>\n<h1>404-File Not Found</h1>\n</p>\n</body>\n</html>";
public WorkerThread(Socket s){
this.s = s;
try{
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new DataOutputStream(s.getOutputStream());
} catch (IOException e){
e.printStackTrace();
}
HTTPServer.id++;
}
private void closeConnection() throws IOException{
out.flush();
out.close();
in.close();
s.close();
//HTTPServer.writer.close();
}
private void sendData(byte [] data) throws IOException{
out.writeBytes(SUCCESS_HEADER);
out.writeBytes(OUTPUT_HEADERS);
out.write(data.length);
out.writeBytes(OUTPUT_END_OF_HEADERS);
out.write(data);
}
private void sendPostData(String POST_DATA) throws IOException{
out.writeBytes(SUCCESS_HEADER);
out.writeBytes(OUTPUT_HEADERS);
out.write(POST_DATA.length());
out.writeBytes(OUTPUT_END_OF_HEADERS);
out.writeBytes(POST_DATA);
}
private void sendErrorMessage() throws IOException{
out.writeBytes(ERROR_HEADER);
out.writeBytes(OUTPUT_HEADERS);
out.write(FILE_NOT_FOUND.length());
out.writeBytes(OUTPUT_END_OF_HEADERS);
out.writeBytes(FILE_NOT_FOUND);
}
private void setMimeType(String fileType){
if(fileType.equals("html")){
MIME_TYPE = "text/html";
} else if(fileType.equals("png")){
MIME_TYPE = "image/png";
} else if(fileType.equals("pdf")){
MIME_TYPE = "application/pdf";
} else if(fileType.equals("jpg")){
MIME_TYPE = "image/jpg";
} else if(fileType.equals("jpeg")){
MIME_TYPE = "image/jpeg";
} else if(fileType.equals("bmp")){
MIME_TYPE = "image/bmp";
} else if(fileType.equals("tiff")){
MIME_TYPE = "image/tiff";
} else if(fileType.equals("tif")){
MIME_TYPE = "image/tiff";
} else if(fileType.equals("default")){
MIME_TYPE = "text/html";
}
}
private byte [] readFileIntoByteArray(File file) throws IOException{
FileInputStream fileInputStream = new FileInputStream(file);
byte [] data = new byte[(int) file.length()];
fileInputStream.read(data);
fileInputStream.close();
return data;
}
private void writeToLogFile(String message,String statusCode,int fileSize) throws IOException {
HTTPServer.writer.write(InetAddress.getByName("localHost").getHostAddress() + "--" + "[" + new Date().toString() + "] \"" + message + "\" " + statusCode + " " + fileSize);
HTTPServer.writer.flush();
}
private void addNewLineToLogFile() throws IOException{
HTTPServer.writer.write("\r\n");
HTTPServer.writer.flush();
}
private String readRequest() throws IOException{
return in.readLine();
}
private Information extractInformation(String message){
Information information = new Information();
information.setMethod(message.substring(0,message.indexOf(' ')));
information.setFileName(message.substring(message.indexOf("/") + 1,message.lastIndexOf(' ')));
if(information.getFileName().isEmpty()) information.setFileName("index.html");
information.setFileType(information.getFileName().substring(information.getFileName().indexOf(".") + 1));
return information;
}
private int contentLength() throws IOException{
String str;
int postDataI = -1;
while((str = readRequest()) != null) {
if(str.isEmpty()) break;
final String contentHeader = "Content-Length: ";
if(str.contains(contentHeader)){
postDataI = Integer.parseInt(str.substring(contentHeader.length()));
}
}
return postDataI;
}
private String userName(int postDataI) throws IOException{
String USER_DATA = null;
char [] charArray = new char[postDataI];
in.read(charArray);
USER_DATA = new String(charArray);
return USER_DATA;
}
private String modifyUserName(String USER_DATA){
USER_DATA = USER_DATA.replaceAll("\\+"," ");
USER_DATA = USER_DATA.substring(USER_DATA.indexOf("=") + 1);
return USER_DATA;
}
@Override
public void run() {
try{
String message = readRequest();
Information info = new Information();
if(message != null){
info = extractInformation(message);
}
if(info.getMethod().equals("GET")){
File file = new File(info.getFileName());
// image format - bmp,jpg,png,tiff
// file type - pdf , html
if(file.isFile()){ // check if the file exists in the directory
// send the file
setMimeType(info.getFileType());
byte [] data = readFileIntoByteArray(file);
sendData(data);
writeToLogFile(message,"200",data.length);
} else{
// file not found - 404
setMimeType("default");
sendErrorMessage();
writeToLogFile(message,"404",FILE_NOT_FOUND.length());
}
} else if(info.getMethod().equals("POST")){
// read the post data
int postDataI = contentLength();
String USER_DATA = userName(postDataI);
USER_DATA = modifyUserName(USER_DATA);
if(!USER_DATA.isEmpty()){
String POST_DATA = "<html>\n<head>\n<title>\nPost Request\n</title>\n</head>\n<body>\n<p>\n<h1>" + USER_DATA +"</h1>\n</p>\n</body>\n</html>";
sendPostData(POST_DATA);
writeToLogFile(message,"200",USER_DATA.length());
} else{
// blank username
String POST_DATA = "<html>\n<head>\n<title>\nPost Request\n</title>\n</head>\n<body>\n<p>\n<h1>Blank User Name</h1>\n</p>\n</body>\n</html>";
sendPostData(POST_DATA);
writeToLogFile(message,"200",0);
}
}
addNewLineToLogFile();
closeConnection();
} catch (IOException e){
e.printStackTrace();
}
}
}