Skip to content

Instantly share code, notes, and snippets.

@tolinwei
Last active December 16, 2015 16:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tolinwei/5464447 to your computer and use it in GitHub Desktop.
Save tolinwei/5464447 to your computer and use it in GitHub Desktop.
The 1st assignment of Computer Network: Java Web Server
import java.net.*;
import java.util.*; //for ArrayList and Date
import java.io.*;
class ConnectionThread extends Thread {
Socket client; //class member
int counter; //class member
//constructor
public ConnectionThread(Socket cl, int c) {
client = cl;
counter = c;
}
public void ReturnErrorHead(String sc, PrintWriter o) {//sc->Status Code, wrong always HTTP 1.1!!!
if (sc.equals("301")) {
o.println("HTTP/1.1 301 Moved Permanent");
//DATE TIME
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
//Location to designate new place???
o.println("Content-Length: 313");
//o.println("Content-Length:" + fileToSend.length());
o.println("Content-Type: text/html; charset=iso-8859-1");
o.println();
} else if(sc.equals("304")) {
o.println("HTTP/1.1 304 Not Modified");
//DATE
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
o.println("ETag: \"c0e92-b1-4d42ba994aa00\"");
o.println("Vary: Accept-Encoding");
//not page return
} else if (sc.equals("400")) {
o.println("HTTP/1.1 400 Bad Request");
//Date:
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
o.println("Vary: Accept-Encoding");
o.println("Content-Length: 301");
//o.println("Content-Length:" + fileToSend.length());
o.println("Connection: close"); // must be closed, because it's wrong
o.println("Content-Type: text/html; charset=iso-8859-1");
o.println();
} else if(sc.equals("403")) {
o.println("HTTP/1.1 403 Forbidden");
//TIME
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
o.println("Vary: Accept-Encoding");
o.println("Content-Length: 288");
//o.println("Connection: close"); // must be closed, because it's wrong
o.println("Content-Type: text/html; charset=iso-8859-1");
o.println();
} else if(sc.equals("404")) {
o.println("HTTP/1.1 404 Not Found");
//TIME
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
o.println("Content-Length: 207");
o.println("Connection: close"); // must be closed, because it's wrong
o.println("Content-Type: text/html; charset=iso-8859-1");
o.println();
} else if(sc.equals("405")) {
o.println("HTTP/1.1 405 Method Not Allowed");
//TIME
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
//o.println("Content-Location: index.html.en");//don't know it's meaning
o.println("Vary: negotiate");
o.println("TCN: choice");
o.println("Allow: GET,HEAD,OPTIONS");
o.println("Content-Length: 308");
o.println("Connection: close"); // must be closed, because it's wrong
o.println("Content-Type: text/html; charset=iso-8859-1");
o.println();
} else if(sc.equals("412")) {
////////////////////////////////////////////////
//I don't know how to do
////////////////////////////////////////////////
o.println("HTTP/1.1 412 Precondition Failed");
//TIME
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
//o.println("Content-Location: index.html.en");
//o.println("Last-Modified: Fri, 08 Feb 2013 20:32:48 GMT");
//Last Modified
o.println("ETag: \"11638e1-0-4d53c76661c00\"");
o.println("Accept-Ranges: bytes");
o.println("Content-Length: 0");
//o.println("Connection: close");
o.println("Content-Type: text/html");
o.println();
//No Content Return
} else if(sc.equals("501")) {
o.println("HTTP/1.1 501 Method Not Implemented");
//TIME
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
//o.println("Content-Location: index.html.en");
o.println("Vary: negotiate");
o.println("TCN: choice");
o.println("Allow: GET,HEAD,OPTIONS");
o.println("Content-Length: 299");
//o.println("Connection: close"); // must be closed, because it's wrong
o.println("Content-Type: text/html; charset=iso-8859-1");
o.println();
} else if(sc.equals("505")) {
o.println("HTTP/1.1 505 HTTP Version Not Supported");
//TIME
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
o.println("Vary: negotiate");
o.println("TCN: choice");
o.println("Content-Length: 283");
o.println("Content-Type: text/html; charset=iso-8859-1");
o.println();
}
}
public void ReturnErrorPage(String sc, PrintWriter o, String m, String f) {
if (sc.equals("301")) {
//content
o.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
o.println("<html><head>");
o.println("<title>301 Moved Permanently</title>");
o.println("</head><body>");
o.println("<h1>Moved Permanently</h1>");
o.println("<p>The document has moved <a href=\"http://192.168.1.8/test_dir/\">here</a>.</p>");
o.println("</body></html>");
} else if(sc.equals("304")) {
//not page return
} else if (sc.equals("400")) {
//content
o.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
o.println("<html><head>");
o.println("<title>400 Bad Request</title>");
o.println("</head><body>");
o.println("<h1>Bad Request</h1>");
o.println("<p>Your browser sent a request that this server could not understand.</p>");
o.println("</body></html>");
} else if(sc.equals("403")) {
//content
o.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
o.println("<html><head>");
o.println("<title>403 Forbidden</title>");
o.println("</head><body>");
o.println("<h1>Forbidden</h1>");
o.println("<p>You don't have permission to access " + f + " + on this server.</p>");
o.println("</body></html>");
} else if(sc.equals("404")) {
//content
o.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
o.println("<html><head>");
o.println("<title>404 Not Found</title>");
o.println("</head><body>");
o.println("<h1>Not Found</h1>");
o.println("<p>The requested URL " + f + " was not found on this server.</p>");
o.println("</body></html>");
} else if(sc.equals("405")) {
//content
o.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
o.println("<html><head>");
o.println("<title>405 Method Not Allowed</title>");
o.println("</head><body>");
o.println("<h1>Method Not Allowed</h1>");
o.println("The requested method " + m + " is not allowed for the URL " + f + ".");
o.println("</body></html>");
} else if(sc.equals("412")) {
//No Content Return
} else if(sc.equals("501")) {
//content
o.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
o.println("<html><head>");
o.println("<title>501 Method Not Implemented</title>");
o.println("</head><body>");
o.println("<h1>Method Not Allowed</h1>");
o.println("The requested method " + m + " is not allowed for the URL " + f + ".");
o.println("</body></html>");
} else if(sc.equals("505")) {
o.println("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">");
o.println("<html><head>");
o.println("<title>505 HTTP Version Not Supported</title>");
o.println("</head><body>");
o.println("<h1>HTTP Version Not Supported</h1>");
o.println("The HTTP Version of your requested is not allowed for the URL " + f + ".");
o.println("</body></html>");
}
}
public void ReturnHead(File f, String hv, PrintWriter o) {
o.println(hv + " 200 OK");//"HTTP/1.x 200 OK"
//TIME
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
o.println("Vary: negotiate");
o.println("TCN: choice");
//LAST MODIFIED
o.println("ETag: \"154d00-2c-4c5c7409c6e00\"");
o.println("Accept-Ranges: bytes");
o.println("Content-Length:" + f.length());
o.println("Content-Type: text/html");
o.println("Content-Language: en");
o.println();
}
public void ReturnPage(File f, PrintWriter o) {
BufferedReader fileOut;
try {
fileOut = new BufferedReader(new FileReader(f));
String content;
while((content = fileOut.readLine()) != null) {
o.println(content);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void ReturnOptions(PrintWriter o, String hv) {
o.println("HTTP/1.1 200 OK");
//DATE
//o.println("Date: Fri, 08 Feb 2013 02:55:06 GMT");
o.println("Server: JAVA Web Server/0.1 (Wei_Lin)");
//o.println("Content-Location: index.html.en");
o.println("Vary: negotiate");
o.println("TCN: choice");
o.println("Allow: GET,HEAD,OPTIONS");
o.println("Content-Length: 0");
//o.println("Connection: close");
o.println("Content-Type: text/html");
o.println("Content-Language: en");
//o.println();
o.close();
}
public void DealRequest(String method, String file, String hv, PrintWriter o) {
File fileToSend = new File("/var/www" + file);
//add /index.html if is a directory
boolean isDirectory = false;
if(fileToSend.isDirectory() && file.charAt(file.length()-1) == '/') {//example: file = "/test_dir/"
isDirectory = true;
fileToSend = new File("/var/www" + file + "index.html");
} else if(fileToSend.isDirectory() && file.charAt(file.length()-1) != '/') {//example: file = "/test_dir"
isDirectory = true;
fileToSend = new File("/var/www" + file + "/index.html");
} //else: normal file, no need to add /index.html
System.out.println(fileToSend.toString());
//
//System.out.println(fileToSend.toString());
if(method.equals("GET")) {
if(fileToSend.exists() && fileToSend.canRead()) {
ReturnHead(fileToSend, hv, o);
ReturnPage(fileToSend, o);
//ReturnFile(fileToSend.toString(), o, hv);
} else if(fileToSend.exists() && !fileToSend.canRead()) {
ReturnErrorHead("403", o);
ReturnErrorPage("403", o, method, file);
} else if(!fileToSend.exists() && !isDirectory) {
//!!!!!
ReturnErrorHead("404", o);
ReturnErrorPage("404", o, method, file);
} else if(!fileToSend.exists() && isDirectory) {
ReturnErrorHead("301", o);
ReturnErrorPage("301", o, method, file);
}
} else if(method.equals("HEAD")) {
/*Last Things*/
/*Remove ReturnHead, compare to GET*/
} else if(method.equals("OPTIONS")) {
ReturnOptions(o, hv);
} else if(method.equals("POST") || method.equals("PUT") || method.equals("DELETE") || method.equals("TRACE") || method.equals("CONNECT")) {
//method not allowed
ReturnErrorHead("405", o);
ReturnErrorPage("405", o, method, file);
} else {
//method not implement
ReturnErrorHead("501", o);
ReturnErrorPage("501", o, method, file);
}
}
//class method
public void run() {//throws IOException {
//boolean timeout = true;
boolean persistent = true;
while(persistent) {
//System.out.println("Begin of while!");
try {
//Test multi-thread and persistent connection
String destIP = client.getInetAddress().toString();
int destport = client.getPort();
System.out.println("Thread " + counter + ": Connected from " + destIP + " on port " + destport + ".");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
String request = null;
String tempHeader = null;
ArrayList<String> header = new ArrayList<String>();
request = in.readLine();
int headerNo = 0;
boolean containHost = false;
boolean containModified = false;
boolean containUnmodified = false;
while((tempHeader = in.readLine()).length() != 0) {//Control to receive a space line
header.add(tempHeader);
headerNo++;
if(tempHeader.split(":")[0].equalsIgnoreCase("Host")) {
containHost = true;
}
if(tempHeader.split(":")[0].equalsIgnoreCase("If-Modified-Since")) {
containModified = true;
//containUnmodified = true;
}
if(tempHeader.split(":")[0].equalsIgnoreCase("If-Unmodified-Since")) {
//containModified = true;
containUnmodified = true;
}
}
//System.out.println(request);
/*
for(int i = 0; i < headerNo; i++) {
System.out.println(header.get(i));
}
System.out.println();
*/
//Think about the persistent control
String[] subRequest = request.split(" ");
//Can't exist both M and Unm
if(containModified == true && containUnmodified == true) {
ReturnErrorHead("400", out);
ReturnErrorPage("400", out, subRequest[0], subRequest[1]);
}
///////////////////////////////////////////////////////////////////////////////
//Request with less than 2 spaces
///////////////////////////////////////////////////////////////////////////////
if (subRequest.length <= 2) {//no enough space, 400
//400
ReturnErrorHead("400", out);
ReturnErrorPage("400", out, subRequest[0], subRequest[1]);
//persistent = false;
}
///////////////////////////////////////////////////////////////////////////////
//HTTP 1.1
///////////////////////////////////////////////////////////////////////////////
else if(subRequest[2].equals("HTTP/1.1") && containHost) {
//beginning of persistent connection
//System.out.println("HTTP 1.1");
//System.out.println(subRequest[1]);
DealRequest(subRequest[0], subRequest[1], subRequest[2], out);
///////////////////////////////////////////////////////////////////////////////
//HTTP 1.0
///////////////////////////////////////////////////////////////////////////////
} else if(subRequest[2].equals("HTTP/1.0")) {
//non-persistent
//System.out.println("HTTP 1.0");
//the same as 1.1, just change persistent to false
ReturnErrorHead("505", out);
ReturnErrorPage("505", out, subRequest[0], subRequest[1]);
/*
//DealRequest(subRequest[0], subRequest[1], subRequest[2], out);
//persistent = false;
*
*/
///////////////////////////////////////////////////////////////////////////////
//Wrong: Example: (!HTTP 1.0 || !HTTP 1.0) || (1.1 without Host)
///////////////////////////////////////////////////////////////////////////////
} else if((!subRequest[2].equals("HTTP/1.0") || !subRequest[2].equals("HTTP/1.1")) || subRequest[2].equals("HTTP/1.1") && !containHost) {
//400
ReturnErrorHead("400", out);
ReturnErrorPage("400", out, subRequest[0], subRequest[1]);
//persistent = false;
}
} catch(IOException e) {
try {
//timeout = true;
persistent = false;
System.out.println("Thread " + counter + " Timeout!");
client.close();
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println(e);
}
}
if(!persistent) {
//EXIT the persistent
try {
//this is for timeout connection
client.close();
System.out.println("Thread " + counter + " Closed!");
System.out.println("Server disconnect!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class WebServer {
public static void main(String[] args) throws IOException {
int i = 0;
int port = 12000;
ServerSocket server = null;
Socket client = null;
server = new ServerSocket(port);
System.out.println("JAVA Web Server on port " + server.getLocalPort());
while(true) {
try {
client = server.accept();
client.setSoTimeout(10000);
new ConnectionThread(client, i).start();
i++;
} catch(Exception e) {
System.out.println(e);
client.close();
}
//client.close();
}
//server.close();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment