import java.io.*; import java.net.*; import java.util.*; // HTTPServer class. This server sends named HTML files // (ending in .htm or html) as long as the client request // indicates it can handle html docs. public class HTTPServer { public static void main(String[] args) { String RootDir; try { // command line arg is the directory in which we want // to look for files when we get an HTTP request. // This is used later to create an HTTPResponse object // that will server the specified directory. RootDir = args[0]; System.out.println("Document Root: " + RootDir); // Connect to the specified host and port ServerSocket s = new ServerSocket(0); // Print out our port number System.out.println("Port: " + s.getLocalPort()); // process clients forever... while (true) { System.out.println("Looking for new client"); // get the next client connection Socket client = s.accept(); HTTPRequest r = new HTTPRequest(client); // The request object can tell us about the request, // including the URI and headers. For this sample // program we just print them out. System.out.println("METHOD: " + r.getMethod()); System.out.println("URI: " + r.getURI()); System.out.println("Version: " + r.getVersion()); // The headers are stored in a hash table Hashtable hdrs = r.headers; // Find out what the client can handle - Accept header System.out.println("Client can handle: " + hdrs.get("Accept")); HTTPResponse resp = new HTTPResponse(client,r,RootDir); client.close(); } // If anything goes wrong, print an error message } catch (IOException e) { System.err.println(e); } catch (ArrayIndexOutOfBoundsException e) { System.err.println("Usage: HTTPServer "); } } } // HTTPResponse generates an HTTP response // This class includes methods that take care of a single request. // The constructor actually creates the response and sends it // to the client, so creating an HTTPResponse object is all you need // to do... // // The constructor needs a socket (current connected to the client), // an HTTPRequest object that hold the current request, and // a string that specifies the root directory served by this // HTTP server (where to look for files). The root directory is // prepended to all received URIs to resolve the actual file name. class HTTPResponse { HTTPRequest request; Socket client; OutputStream toClient; String RootDir; HTTPResponse(Socket client,HTTPRequest req, String rootdir) throws IOException{ this.client = client; this.request = req; toClient = client.getOutputStream(); RootDir = rootdir; SendFile(); } void SendFile() { try { // We need to prepend the root directory to the requested file // path - the server only looks in that directory. // A "real" server would make sure that the URI does // not include things like ".." so that the server // wouldn't send back anything not contained in the root // directory (but this sample doesn't handle this). String path = RootDir + request.getURI(); // open the file and associate an input stream with it. // (The file could hold anything, so we don't assume it is // just text we are reading - if it was just text we would // probably want to use a reader). FileInputStream f = new FileInputStream(path); // Some debugging info - log this request to stdout System.out.println("REQUEST FOR: " + path ); StatusLine(200,"OK"); // Send back content-type header. We assume the file is // and HTML file! Header("Content-type","text/HTML"); // blank line ends the headers WriteLine(""); // Now send the file (as raw bytes) byte b[] = new byte[1000]; int n; while ((n=f.read(b))>0) { toClient.write(b,0,n); } f.close(); } catch (WriteAbortedException e) { System.out.println(e); } catch (FileNotFoundException e) { // Generate HTTP error 400 try { StatusLine(400,"No such resource: " + request.getURI()); WriteLine(""); WriteLine("

Error: No such resource found: " + request.getURI()); } catch (IOException ie) { System.out.println(ie); } } catch (IOException e) { System.out.println(e); } } void StatusLine(int ecode,String msg) throws IOException { StringBuffer cd = new StringBuffer(); cd.append(ecode/100); cd.append((ecode%100)/10); cd.append(ecode%10); WriteLine(request.getVersion() + " " + cd.toString()+ " " + msg); } void Header(String name, String value) throws IOException { WriteLine(name+": "+value); } void WriteLine(String s) throws IOException { toClient.write(s.getBytes()); toClient.write("\r\n".getBytes()); } } // HTTPRequest extracts a HTTP request from a socket // and can report on the various parts of the request // (URI, headers, method, etc.) class HTTPRequest { String Method; // hold the method extracted from the request String URI; // the requested URI String Version; // HTTP version public Hashtable headers; // has table that holds all found request headers // constructor gets a socket that corresponds to an // active client connection. HTTPRequest(Socket c) throws IOException { InputStream in = c.getInputStream(); // The first line is the request line // NOTE: Using my own method GetLine - should probably use a // a reader and readLine (although a buffered reader could make // it difficult to read raw data that comes as part of the content // of the request). StringBuffer request = GetLine(in); System.out.println("Request was: " + request); headers = new Hashtable(); try { StringTokenizer st = new StringTokenizer(request.toString()); Method = st.nextToken(); URI = st.nextToken(); // If there is no HTTP version found in the request line, // this is a version 0.9 request if (st.hasMoreElements()) { Version = st.nextToken(); // read in headers and store in Hash Table StringBuffer header = GetLine(in); // keep processing until we see an empty header line while (header.length()>0) { StringTokenizer hst = new StringTokenizer(header.toString(),":"); String name=hst.nextToken(); String val=hst.nextToken(); // remove leading whitespace from header value while (val.charAt(0) == ' ') { val = val.substring(1); } headers.put(name,val); header = GetLine(in); } } else { Version = "HTTP/0.9"; // Old style request - no headers } } catch (NoSuchElementException e) { System.out.println("Invalid Request"); throw e; } } StringBuffer GetLine(InputStream in) throws IOException { StringBuffer b = new StringBuffer(); int x; x=in.read(); while (x!='\n') { if (x == -1) break; if (x != '\r') b.append((char)x); x = in.read(); } return(b); } public String getMethod() { return(Method); } public String getURI() { return(URI); } public String getVersion() { return(Version); } }