Last active
December 16, 2015 16:39
-
-
Save tolinwei/5464447 to your computer and use it in GitHub Desktop.
The 1st assignment of Computer Network: 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.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