/** * The default implementation of this method attempts to resolve an {@link HttpRequestHandler} for * the request URI of the given request and, if found, executes its {@link * HttpRequestHandler#handle(HttpRequest, HttpResponse, HttpContext)} method. * * <p>Super-classes can override this method in order to provide a custom implementation of the * request processing logic. * * @param request the HTTP request. * @param response the HTTP response. * @param context the execution context. * @throws IOException in case of an I/O error. * @throws HttpException in case of HTTP protocol violation or a processing problem. */ protected void doService( final HttpRequest request, final HttpResponse response, final HttpContext context) throws HttpException, IOException { HttpRequestHandler handler = null; if (this.handlerResolver != null) { String requestURI = request.getRequestLine().getUri(); handler = this.handlerResolver.lookup(requestURI); } if (handler != null) { handler.handle(request, response, context); } else { response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED); } }
public void runServer( final Socket socket, BufferedReader in, String line, final ThreadPool threads) throws InterruptedException { /** * Special URL control Returns page with a: student information b: list of all threads in the * thread pool c: status of each thread (waiting or URL it is currently handling) d: a button * that shuts down the server */ final HttpRequestHandler controlHandler = new HttpRequestHandler() { public void handle(HttpRequest request, HttpResponse response) { String threadsStatus = threads.getThreadsStatus(request.path); String msg = ("<!DOCTYPE html><html><body>" + "<h1>Student Information</h1><p>Name: James Jin Park</p>" + "<p>SEAS login: jamespj</p>" + "<h1>Server Information</h1>" + "<p>" + threadsStatus + "</p>" + "<button onclick=\"location.href='/errorLog'\">View Error Log</button></br>" + "<p> </p>" + "<button onclick=\"location.href='/shutdown'\">Shutdown Server</button>" + "</body></html>"); response.headers.put("Content-Type", "text/html"); response.setBody(msg); } }; final HttpRequestHandler logHandler = new HttpRequestHandler() { public void handle(HttpRequest request, HttpResponse response) { File file = new File(rootDir + "/ErrorLog.txt"); try { BufferedReader reader = new BufferedReader(new FileReader(file)); StringBuilder builder = new StringBuilder(); String line = reader.readLine(); while (line != null) { builder.append(line); builder.append(System.lineSeparator()); line = reader.readLine(); } String errorString = builder.toString(); String msg = ("<!DOCTYPE html><html><body>" + "<h1>Student Information</h1><p>Name: James Jin Park</p>" + "<p>SEAS login: jamespj</p>" + "<h1>Error Log</h1>" + "<p>" + errorString + "</p>" + "<button onclick=\"location.href='/control'\">Back to Control</button>" + "</body></html>"); response.headers.put("Content-Type", "text/html"); response.setBody(msg); reader.close(); } catch (Exception e) { e.printStackTrace(); String msg = ("<!DOCTYPE html><html><body>" + "<h1>Student Information</h1><p>Name: James Jin Park</p>" + "<p>SEAS login: jamespj</p>" + "<h1>Missing Error Log</h1>" + "<button onclick=\"location.href='/control'\">Back to Control</button>" + "</body></html>"); response.setBody(msg); } } }; // try (ServerSocket serverSocket = new ServerSocket(this.port, 200)) { // serverSocket.setSoTimeout(200); // timeout so we can periodically check flag // System.out.println("Server started and listening for connections."); // // while (!ShutdownHook.isShutdown.get()) { // try { // final Socket socket = serverSocket.accept(); // Runnable runnable = new Runnable() { // // @Override // public void run() { try ( // all these are closeable by putting them in as arguments for try() // InputStreamReader reader = new // InputStreamReader(socket.getInputStream()); // BufferedReader in = new BufferedReader(reader); PrintWriter out = new PrintWriter(socket.getOutputStream()); ) { HttpRequest request = httpRequestParser.parse(line, in); HttpResponse response = new HttpResponse(); String absoluteSpecialPath = null; if (request.headers.get("Host") != null) { absoluteSpecialPath = ("http://" + request.headers.get("Host")); } // System.out.println("Here is the request: \n" + request + "\n\nEnd of Transmission\n"); Route requestedRoute = null; HttpRequestHandler handler = null; if (request.method.toUpperCase().equals("HEAD") && !request.path.equals("/shutdown") && !request.path.equals(absoluteSpecialPath + "/shutdown") && !request.path.equals(absoluteSpecialPath + "/control") && !request.path.equals("/control")) { request.isHead = true; request.method = "GET"; } if (request.method.toUpperCase().equals("HEAD") && request.path.equals("/shutdown") || request.path.equals(absoluteSpecialPath + "/shutdown") || request.path.equals(absoluteSpecialPath + "/control") || request.path.equals("/control")) { requestedRoute = Route.of(request.method, "405Error"); handler = routes.get(requestedRoute); } if (request.method.toUpperCase().equals("POST")) { requestedRoute = Route.of(request.method, "405Error"); handler = routes.get(requestedRoute); } String absolutePath = null; if (request.headers.get("Host") != null) { absolutePath = request.path; request.path = request.path.replace("http://", "").replace(request.headers.get("Host"), ""); } else if ((request.path.contains("http://")) && request.version.equals("HTTP/1.0")) { absolutePath = request.path; request.path = request.path.replace("http://", ""); request.path = request.path.replace(request.path.split("\\/")[0], ""); } else { absolutePath = "http://localhost:" + port + "/" + request.path; } File absoluteFile = null; if (request.path.equals("/")) { absoluteFile = new File(rootDir + "/" + request.path); } else { absoluteFile = new File("." + request.path); } // complicated path String HTMLregex = "([^\\s]+(\\.(?i)(html))$)"; String ImageRegex = "([^\\s]+(\\.(?i)(jpg|png|gif|bmp|))$)"; String pdfRegex = "([^\\s]+(\\.(?i)(pdf))$)"; String relativePathRegex = "([^\\s]+(\\.(?i)(.))$)"; Matcher htmlFinder = Pattern.compile(HTMLregex).matcher(request.path); Matcher imageFinder = Pattern.compile(ImageRegex).matcher(request.path); Matcher pdfFinder = Pattern.compile(pdfRegex).matcher(request.path); Matcher relativePathFinder = Pattern.compile(relativePathRegex).matcher(request.path); if (relativePathFinder.find()) { request.path = request.path.substring(0, request.path.lastIndexOf('/')); } File f = new File(rootDir + "/" + request.path); if (htmlFinder.find() && f.isFile()) { // System.out.println("Successfully found html"); requestedRoute = Route.of(request.method, "html"); handler = routes.get(requestedRoute); } else if (htmlFinder.find() && absoluteFile.isFile()) { // System.out.println("Successfully found html"); request.path = absolutePath; requestedRoute = Route.of(request.method, "html"); handler = routes.get(requestedRoute); } else if (imageFinder.find() && f.isFile()) { // System.out.println("Successfully found image"); requestedRoute = Route.of(request.method, "image"); handler = routes.get(requestedRoute); } else if (imageFinder.find() && absoluteFile.isFile()) { // System.out.println("Successfully found image"); request.path = absolutePath; requestedRoute = Route.of(request.method, "image"); handler = routes.get(requestedRoute); } else if (f.isDirectory()) { // System.out.println("Successfully found directory"); requestedRoute = Route.of(request.method, "directory"); handler = routes.get(requestedRoute); } else if (absoluteFile.isDirectory()) { // System.out.println("Successfully found directory"); request.path = absolutePath; requestedRoute = Route.of(request.method, "directory"); handler = routes.get(requestedRoute); } else if (pdfFinder.find() && f.isFile()) { // System.out.println("Successfully found pdf file."); requestedRoute = Route.of(request.method, "pdf"); handler = routes.get(requestedRoute); } else if (pdfFinder.find() && absoluteFile.isFile()) { // System.out.println("Successfully found pdf file."); request.path = absolutePath; requestedRoute = Route.of(request.method, "pdf"); handler = routes.get(requestedRoute); } else if (f.isFile()) { // System.out.println("Treat like text file."); requestedRoute = Route.of(request.method, "plainText"); handler = routes.get(requestedRoute); } else if (absoluteFile.isFile()) { // System.out.println("Treat like text file."); request.path = absolutePath; requestedRoute = Route.of(request.method, "plainText"); handler = routes.get(requestedRoute); } else { // root, special URLs requestedRoute = Route.of(request.method, request.path); handler = routes.get(requestedRoute); } if ((requestedRoute.method.equals(Route.of("GET", "/control").method) && requestedRoute.path.equals(Route.of("GET", "/control").path)) || ((requestedRoute.method.equals(Route.of("GET", absolutePath + "/control").method) && requestedRoute.path.equals(Route.of("GET", absolutePath + "/control").path)))) { handler = controlHandler; } // shutdown handler if ((requestedRoute.method.equals(Route.of("GET", "/shutdown").method) && requestedRoute.path.equals(Route.of("GET", "/shutdown").path)) || ((requestedRoute.method.equals( Route.of("GET", absoluteSpecialPath + "/shutdown").method) && requestedRoute.path.equals( Route.of("GET", absoluteSpecialPath + "/shutdown").path)))) { handler = shutdownHandler; } // log handler if ((requestedRoute.method.equals(Route.of("GET", "/errorLog").method) && requestedRoute.path.equals(Route.of("GET", "/errorLog").path)) || ((requestedRoute.method.equals( Route.of("GET", absoluteSpecialPath + "/errorLog").method) && requestedRoute.path.equals( Route.of("GET", absoluteSpecialPath + "/errorLog").path)))) { handler = logHandler; } if ((request.method.equals("Missing")) || (request.path.equals("Missing")) || (request.version.equals("Missing")) || (request.headers.get("Host") == null && request.version.equals("HTTP/1.1"))) { requestedRoute = Route.of("GET", "400Error"); handler = routes.get(requestedRoute); } if ((!request.method.equals("GET") || request.method.equals("HEAD")) && (!request.method.equals("Missing"))) { requestedRoute = Route.of("GET", "501Error"); handler = routes.get(requestedRoute); } if (handler == null) { requestedRoute = Route.of("GET", "404Error"); handler = routes.get(requestedRoute); } else { // handler is not null but we need to check if-modified header if (request.headers.get("If-Modified-Since") != null && request.version.equals("HTTP/1.1")) { if (!request.isHead) { File file = new File("." + request.path); boolean tempIsModified = false; try { tempIsModified = httpRequestParser.checkDate(request.headers.get("If-Modified-Since"), file); } catch (ParseException e) { e.printStackTrace(); } if (!tempIsModified) { requestedRoute = Route.of("GET", "304Error"); // Not modified error. sets isModified to false handler = routes.get(requestedRoute); } } else { // If-Modified-Since does not work methods other than "GET" requestedRoute = Route.of("GET", "501Error"); handler = routes.get(requestedRoute); } } if (request.headers.get("If-Unmodified-Since") != null && request.version.equals("HTTP/1.1")) { File file = new File("." + request.path); boolean tempIsModified = false; try { tempIsModified = httpRequestParser.checkDate(request.headers.get("If-Unmodified-Since"), file); } catch (ParseException e) { e.printStackTrace(); } if (tempIsModified) { requestedRoute = Route.of("GET", "412Error"); // Not modified error. sets isModified to false handler = routes.get(requestedRoute); } } } handler.handle(request, response); if (request.version.equals("HTTP/1.1")) { out.println("HTTP/1.1 100 Continue"); out.println(""); } out.println("HTTP/1.1 " + response.getStatus()); // Response includes HTTP version final Date currentTime = new Date(); final SimpleDateFormat dateTemplate = new SimpleDateFormat("EEE, d MMM yyyy hh:mm:ss"); dateTemplate.setTimeZone(TimeZone.getTimeZone("GMT")); if (!request.isError) { // if the response is not error response out.println("Date: " + dateTemplate.format(currentTime) + " GMT"); // Response includes date out.println("Server: James's HTTP Server"); // Response includes host // System.out.println("HTTP/1.1 " + // response.getStatus());//DELETE } if (!request.isModified) { // should only get in here if the document IS NOT MODIFIED or FALSE out.println("Date: " + dateTemplate.format(currentTime) + " GMT"); // Response includes date out.println(""); } if (!request.isModified) { // should only get in here if the document IS NOT MODIFIED or FALSE out.println(""); } for (Map.Entry<String, Object> header : response.headers.entrySet()) { out.println(header.getKey() + ": " + header.getValue()); // System.out.println("test " + header.getKey() + ": " + // header.getValue());//DELETE } if (!request.isHead) { // if the request was not a HEAD method and is modified if (request.isModified) { if (response.getBody() != null && response.getBody().length() > 0) { out.println(""); out.println(response.getBody()); out.flush(); } if (response.getMyBytes() != null) { BufferedOutputStream output = new BufferedOutputStream(socket.getOutputStream()); output.write( ("HTTP/1.1 " + response.getStatus()).getBytes()); // Response includes HTTP version output.write("\r\n".getBytes()); output.write( ("Date: " + dateTemplate.format(currentTime) + " GMT") .getBytes()); // Response includes date output.write("\r\n".getBytes()); output.write("Server: James's HTTP Server".getBytes()); // Response includes host for (Map.Entry<String, Object> header : response.headers.entrySet()) { output.write("\r\n".getBytes()); output.write((header.getKey() + ": " + header.getValue()).getBytes()); } output.write("\r\n".getBytes()); output.write("\r\n".getBytes()); output.write(response.getMyBytes(), 0, response.getMyBytes().length); output.flush(); output.close(); } } } else { out.flush(); } out.println( "Connection: close"); // Connection automatically closes. No persistent connection. if (request.headers.get("Connection").equals("close")) { // currently do nothing. } } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } // } // }; // threads.run(runnable);//adds this instance of runnable (request) to the // queue of the thread pool // } catch (SocketTimeoutException ste) { // // fine poll flag; should be timing out // } // } // threads.killAllThreads(); // serverSocket.close(); // } catch (Exception e) { // System.err.println("Error! Could not connect to socket:"); // e.printStackTrace(); // System.exit(1); //server shuts down due to error // } // try { // Thread.sleep(2000); // } catch (InterruptedException e) { // } // int count = 1; // while(threads.howManyThreadsAlive() > 0 ){ // if (count < 6){ // System.out.println("Waiting on " + threads.howManyThreadsAlive() + " thread(s) to // exit. " + "Loop #" + count); // } else { // System.out.println("Manually shutting down thread(s)."); // threads.emergencyShutdown(); // break; // } // try { // count += 1; // Thread.sleep(3000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // } // System.out.println("Server shut down."); }