{"id":651,"date":"2021-04-16T19:59:26","date_gmt":"2021-04-16T19:59:26","guid":{"rendered":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/?page_id=651"},"modified":"2021-04-16T20:52:41","modified_gmt":"2021-04-16T20:52:41","slug":"http-web-servers","status":"publish","type":"page","link":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/","title":{"rendered":"HTTP &#038; Web Servers"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a6d46c362e98\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a6d46c362e98\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#What_is_HTTP\" >What is HTTP?<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#The_HTTP_Request\" >The HTTP Request<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#The_HTTP_Response\" >The HTTP Response<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#HTTP_Status_Codes\" >HTTP Status Codes<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#A_Simple_Java_Web_Server\" >A Simple Java Web Server<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#The_HttpServer_class\" >The HttpServer class<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#The_RequestHandler_Class\" >The RequestHandler Class<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#The_MIMEType_class\" >The MIMEType class<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#The_TeeWriter_Class\" >The TeeWriter Class<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#The_Common_Gateway_Interface_CGI\" >The Common Gateway Interface (CGI)<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#The_Problems_with_CGI\" >The Problems with CGI<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#Java_Servlets\" >Java Servlets<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/servlets\/http-web-servers\/#Apache_Tomcat\" >Apache Tomcat<\/a><\/li><\/ul><\/nav><\/div>\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_is_HTTP\"><\/span>What is HTTP?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The HyperText Transfer Protocol (HTTP) is a stateless, TCP\/IP-based protocol for communication over the World-Wide Web.&nbsp; It is typically used between a client browser and a web server:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The client browser issues a request to the web server.&nbsp; The client:<ul><li>Opens a TCP connection to the web server&#8217;s HTTP port (usually port 80)<\/li><li>Sends an HTTP request message to the web server<\/li><\/ul><\/li><li>The web server:<ul><li>Receives the request<\/li><li>Does the requested work<\/li><li>Returns the information requested in a response message back to the client<\/li><li>The connection is closed<\/li><\/ul><\/li><\/ol>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_HTTP_Request\"><\/span>The HTTP Request<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The most common form of request from a browser is a GET.&nbsp; In its simplest form, it looks like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>GET \/index.html HTTP\/1.0<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">a single line, where:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The first item on the line is called the&nbsp;<em>method<\/em>&nbsp;(here a&nbsp;<code><strong>GET<\/strong><\/code>)<\/li><li>The second item is the pathname of the requested file<\/li><li>The third item indicates we are using the HTTP protocol, and specifies the version.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A GET request can also include a request header.&nbsp; Here&#8217;s an example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/index.html HTTP\/1.0\nHost: localhost:90\nPragma: no-cache\nAccept: image\/gif, image\/x-xbitmap, image\/jpeg, image\/pjpeg, application\/msword, \napplication\/vnd.ms-powerpoint, application\/vnd.ms-excel, *\/*\niM-Running: 2.42SE+\nConnection: close\nUser-Agent: Mozilla\/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YComp 5.0.0.0)\nAccept-Language: en-us<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As you can see, this GET request was generated by the Microsoft Internet Explorer 6.0 browser, and there is lots of other information you could extract.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_HTTP_Response\"><\/span>The HTTP Response<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">In response to the above HTTP request, the web server generates an HTTP response.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the request was successfully satisfied by the web server, then the first line of the response will look like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>HTTP\/1.0 200 OK<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The 200 is the status code for success.&nbsp; &#8220;OK&#8221; is a human-readable description of the meaning of 200.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Following the first line are a number of response header lines, which communicate a number of useful pieces of information about the server, and a description of the contents of the file that follows in the response. A blank line which separates the header from the file contents.&nbsp; For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/1.0 200 OK\nServer: Apache\/1.3.9 (Win32)\nContent-Type: text\/html\nContent-Length: 94\n\n&lt;HTML&gt;\n&lt;HEAD&gt;\n&lt;TITLE&gt;HTTP Request Successful&lt;\/TITLE&gt;\n&lt;\/HEAD&gt;\n&lt;BODY&gt;\nIt Worked!\n&lt;\/BODY&gt;\n&lt;\/HTML&gt;<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Note the blank line after the &#8216;Content-Length: &#8221; line<\/p><\/blockquote>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"HTTP_Status_Codes\"><\/span>HTTP Status Codes<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">If the web server encountered problems &#8212; perhaps it could not find the requested file &#8212; then the first line of the response contains one of a number of error status codes.&nbsp; Status codes are organized numerically to indicate the level\/type of error:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><th>Code Range<\/th><th>Category<\/th><th>Description<\/th><\/tr><tr><td><code><strong>1xx<\/strong><\/code><\/td><td>Informational<\/td><td>Mostly experimental application codes.&nbsp; HTTP\/1.0 does not define any Informational status codes;&nbsp; HTTP\/1.1 does.<\/td><\/tr><tr><td><code><strong>2xx<\/strong><\/code><\/td><td>Successful<\/td><td>Request was received, understood and accepted.<\/td><\/tr><tr><td><code><strong>3xx<\/strong><\/code><\/td><td>Redirection<\/td><td>The server is redirecting the client to another URL.<\/td><\/tr><tr><td><code><strong>4xx<\/strong><\/code><\/td><td>Client Error<\/td><td>The request is improperly formatted, or cannot be fulfilled.<\/td><\/tr><tr><td><code><strong>5xx<\/strong><\/code><\/td><td>Server Error<\/td><td>A valid request was received, but the server cannot fulfill it.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Here are some actual status codes (this is not a complete list):<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><th>Status Code<\/th><th>Description<\/th><\/tr><tr><td><strong><code>200 OK<\/code><\/strong><\/td><td>The request succeeded.<\/td><\/tr><tr><td><strong><code>201 Created<\/code><\/strong><\/td><td>The request was successful, and resulted in the creation of a new resource.<\/td><\/tr><tr><td><strong><code>301 Moved Permanently<\/code><\/strong><\/td><td>The resource has been moved permanently.&nbsp; The&nbsp;<code>Location<\/code>&nbsp;header field specifies the new location.<\/td><\/tr><tr><td><strong><code>302 Moved Temporarily<\/code><\/strong><\/td><td>The resource has been moved temporarily.&nbsp; The&nbsp;<code>Location<\/code>&nbsp;header field specifies the new location.<\/td><\/tr><tr><td><strong><code>400 Bad Request<\/code><\/strong><\/td><td>The request used invalid syntax.<\/td><\/tr><tr><td><strong><code>401 Unauthorized<\/code><\/strong><\/td><td>Authorization, such as username and password, is required to access this resource.&nbsp; A WWW_Authenticate header field containing an authorization challenge is returned.&nbsp; The web browser will normally display a username\/password dialog box to the user<\/td><\/tr><tr><td><strong><code>403 Forbidden<\/code><\/strong><\/td><td>The server refuses to fulfill the response.<\/td><\/tr><tr><td><strong><code>404 Not Found<\/code><\/strong><\/td><td>No resource matching the requested URL exists on the server.<\/td><\/tr><tr><td><strong><code>500 Internal Server Error<\/code><\/strong><\/td><td>The server encountered an unexpected problem.<\/td><\/tr><tr><td><strong><code>501 Not Implemented<\/code><\/strong><\/td><td>The server does not implement the requested functionality.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"A_Simple_Java_Web_Server\"><\/span>A Simple Java Web Server<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To make things perhaps a little clearer, let&#8217;s implement a very simple web server.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_HttpServer_class\"><\/span>The HttpServer class<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">First, here&#8217;s the main class,&nbsp;<code><strong>HttpServer<\/strong><\/code>, which opens a server socket, and responds to client connections<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; notranslate\" title=\"\">\nimport java.io.IOException;\nimport java.net.ServerSocket;\nimport java.util.Date;\n\n\/**\n * Java HTTP Server\n *\n * This is a very simple HTTP server.\n *\n *\/\npublic class HttpServer\n{\n\n  public static boolean VERBOSE = false;\n\n  \/**\n   * Usage\n   *\/\n  private static void usage()\n  {\n    \/\/print instructions to standard out\n    String instructions\n            = &quot;usage: java HttpServer &#x5B;-options] &#x5B;port-number]\\n\\n&quot;\n            + &quot;where options include:\\n&quot;\n            + &quot;    -? -help\\t print out this message\\n&quot;\n            + &quot;    -v -verbose\\t turn on verbose mode\\n\\n&quot;\n            + &quot;  and port-number is the port number to listen on&quot;;\n\n    System.out.println(instructions);\n    System.out.flush();\n  }\n\n  \/**\n   * Extract command line arguments\n   *\/\n  private static void extractArguments(String&#x5B;] args)\n  {\n    if (args.length &gt; 0)\n    {\n      int arg = 0;\n      if (args&#x5B;arg].equals(&quot;-?&quot;) || args&#x5B;arg].equals(&quot;-help&quot;))\n      {\n        usage();\n        arg++;\n      }\n\n      if (args.length &gt;= arg)\n      {\n        if (args&#x5B;arg].equals(&quot;-v&quot;) || args&#x5B;arg].equals(&quot;-verbose&quot;))\n        {\n          VERBOSE = true;\n          arg++;\n        }\n      }\n\n      if (args.length &gt;= arg)\n      {\n        try\n        {\n          m_port = Integer.parseInt(args&#x5B;arg]);\n        }\n        catch (java.lang.NumberFormatException nfe)\n        {\n          System.err.println(&quot;Invalid port number specified: &quot; + args&#x5B;arg]);\n          System.err.println(&quot;  Defaulting to: &quot; + m_port);\n        }\n      }\n    }\n  }\n  \n  \/**\n   * Main method\n   *\n   * @param args &#x5B;-options] &#x5B;port-number]\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    extractArguments(args);\n\n    ServerSocket serverConnect = null;\n    try\n    {\n      System.out.println(&quot;\\nConnecting to port &quot; + m_port + &quot;...\\n&quot;);\n      serverConnect = new ServerSocket(m_port); \/\/listen on port\n      System.out.println(&quot;Listening for connections on port &quot; + m_port + &quot;...\\n&quot;);\n      while (true) \/\/listen until user halts execution\n      {\n        RequestHandler handler = new RequestHandler(serverConnect.accept());\n        if (VERBOSE)\n        {\n          System.out.println(&quot;Connection opened. (&quot; + new Date() + &quot;)&quot;);\n        }\n        handler.start(); \/\/ Start the request handler thread\n      }\n    }\n    catch (IOException e)\n    {\n      System.err.println(&quot;Server error: &quot; + e);\n    }\n  }\n\n  \/\/\/\/\/ Private data \/\/\/\/\/\n  private static int m_port = 8080; \/\/default port value\n}\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In its main method, it connects to the specified port, and when it accepts a client connection, it creates a new instance of the&nbsp;<strong><code>RequestHandler<\/code><\/strong>&nbsp;class, which will receive the request, and process it.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_RequestHandler_Class\"><\/span>The RequestHandler Class<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s&nbsp;<strong><code>RequestHandler<\/code><\/strong>, which is the class that does most of the work:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\nimport java.io.BufferedReader;\nimport java.io.BufferedOutputStream;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.InputStreamReader;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.io.OutputStreamWriter;\nimport java.io.PrintWriter;\nimport java.net.Socket;\nimport java.util.StringTokenizer;\nimport java.util.Date;\n\n\/**\n * HTTP Request Handler\n *\n * This class handles a single request received by the HTTP server. It currently\n * supports only the GET method.\n *\n *\/\npublic class RequestHandler extends Thread\n{\n  \/\/ Constructor\n  public RequestHandler(Socket connect)\n  {\n    m_connect = connect;\n  }\n\n  \/**\n   * Services each request in a separate thread\n   *\/\n  public void run()\n  {\n    BufferedReader in = null;\n    PrintWriter out = null;\n    BufferedOutputStream dataOut = null;\n    try\n    {\n      \/\/ Get character input stream from the client\n      in = new BufferedReader(new InputStreamReader(m_connect.getInputStream()));\n      \/\/ Get output stream to client\n      OutputStream clientOut = m_connect.getOutputStream();\n      \/\/ Get character output stream to client (for headers)\n      if (HttpServer.VERBOSE)\n      {\n        \/\/ Insert a TeeWriter to capture the response header\n        \/\/ output by the rest of the program.\n        out = new PrintWriter(\n                new TeeWriter(\n                        new OutputStreamWriter(clientOut),\n                        new OutputStreamWriter(System.out)\n                )\n        );\n\n      }\n      else\n      {\n        out = new PrintWriter(m_connect.getOutputStream());\n      }\n      \/\/ Get binary output stream to client (for requested data)\n      dataOut = new BufferedOutputStream(clientOut);\n\n      \/\/ Get first line of request from client\n      String input = in.readLine();\n      \/\/ Save the header for this request\n      m_requestHeader = input;\n      while (true)\n      {\n        String line = in.readLine();\n        \/\/ Read until end of stream, or blank line\n        if (line == null || line.length() == 0)\n        {\n          break;\n        }\n        m_requestHeader += (&quot;\\n&lt;br&gt;&quot; + line);\n      }\n\n      \/\/ Use StringTokenizer to parse request&#039;s first line, which is of the form:\n      \/\/    method file-requested HTTP\/version-number\n      \/\/ where:\n      \/\/    method is GET, HEAD, POST, etc.\n      \/\/    version-number is 1.0, 1.1, etc.\n      \/\/\n      StringTokenizer parse = new StringTokenizer(input);\n      String method = parse.nextToken().toUpperCase();\/\/ Parse out method\n      String fileRequested = parse.nextToken().toLowerCase();\/\/ file\n\n      if (HttpServer.VERBOSE)\n      {\n        System.out.println(&quot;--------Begin Request-----&quot;);\n        System.out.println(m_requestHeader);\n        System.out.println(&quot;--------End Request-------&quot;);\n        System.out.flush();\n      }\n\n      \/\/ Dispatch, based on method type\n      if (method.equals(&quot;GET&quot;))\n      {\n        processGetRequest(fileRequested, in, out, dataOut);\n      }\n      else\n      {\n        \/\/ Other HTTP methods are not yet implemented in this HTTP server\n        unsupportedRequest(method, in, out);\n      }\n    }\n    catch (IOException e)\n    {\n      System.err.println(&quot;Server Error: &quot; + e);\n    } finally\n    {\n      \/\/ Ensure all streams are closed\n      try\n      {\n        if (in != null)\n        {\n          in.close();\n        }\n        if (out != null)\n        {\n          out.close();\n        }\n        if (dataOut != null)\n        {\n          dataOut.close();\n        }\n\n        \/\/ Ensure the connection is closed\n        m_connect.close();\n        if (HttpServer.VERBOSE)\n        {\n          System.out.println(&quot;Connection closed.\\n&quot;);\n        }\n      }\n      catch (IOException ioe)\n      {\n        \/\/ Do nothing -- no recovery possible.\n      }\n    }\n  }\n\n  \/**\n   * Process a GET request\n   *\/\n  private void processGetRequest(String fileRequested,\n          BufferedReader in,\n          PrintWriter out,\n          BufferedOutputStream dataOut)\n          throws IOException\n  {\n    \/\/ Handle &quot;special&quot; requests\n    int index = fileRequested.indexOf(&quot;special\/&quot;);\n    if (index != -1)\n    {\n      processSpecialGetRequest(fileRequested, in, out);\n      return;\n    }\n\n    if (fileRequested.endsWith(&quot;\/&quot;))\n    {\n      \/\/append default file name to request\n      fileRequested += DEFAULT_FILE;\n    }\n\n    FileInputStream fileIn = null;\n    try\n    {\n      File file = new File(WEB_ROOT, fileRequested);\n      if (!file.exists())\n      {\n        throw new FileNotFoundException();\n      }\n\n      \/\/ Get the file&#039;s MIME content type\n      String content = MIMETypes.getType(fileRequested);\n\n      \/\/ Generate HTTP response header\n      out.println(&quot;HTTP\/1.0 200 OK&quot;);\n      out.println(&quot;Server: HttpServer 1.0&quot;);\n      out.println(&quot;Date: &quot; + new Date());\n      out.println(&quot;Content-type: &quot; + content);\n      out.println(&quot;Content-length: &quot; + file.length());\n      out.println(); \/\/ Blank line between headers and content\n      out.flush(); \/\/ Flush character output stream buffer\n\n      \/\/ Now the content...\n      \/\/ Open input stream on the file\n      fileIn = new FileInputStream(file);\n      \/\/ Create a byte array to store the file contents\n      byte&#x5B;] fileData = new byte&#x5B;(int) file.length()];\n      \/\/ Read file into byte array\n      fileIn.read(fileData);\n      \/\/ Write file to stream\n      dataOut.write(fileData, 0, (int) file.length());\n      dataOut.flush(); \/\/flush binary output stream buffer\n      if (HttpServer.VERBOSE)\n      {\n        System.out.println(&quot;File &quot; + fileRequested\n                + &quot; of type &quot; + content + &quot; returned.&quot;);\n      }\n    }\n    catch (IOException e)\n    {\n      \/\/ Tell client that file doesn&#039;t exist\n      fileNotFound(fileRequested, out);\n    } finally\n    {\n      \/\/ Ensure that the fileIn is closed.\n      if (fileIn != null)\n      {\n        fileIn.close();\n      }\n    }\n  }\n\n  \/**\n   * Process a &quot;special&quot; GET request. Currently, the only implementation of this\n   * is where the user specifies a &quot;special\/&quot; directory in the request. In this\n   * case, the special GET request simply returns the contents of the request\n   * header in a displayable form on the browser.\n   *\/\n  private void processSpecialGetRequest(String fileRequested,\n          BufferedReader in,\n          PrintWriter out)\n          throws IOException\n  {\n    String page\n            = &quot;&lt;HTML&gt;\\n&quot;\n            + &quot;&lt;HEAD&gt;&lt;TITLE&gt;Request Header Echo&lt;\/TITLE&gt;&lt;\/HEAD&gt;\\n&quot;\n            + &quot;&lt;BODY&gt;\\n&quot;\n            + &quot;&lt;H2&gt;The Header from this Request was:&lt;\/H2&gt;\\n&quot;\n            + m_requestHeader + &quot;\\n&quot;\n            + &quot;&lt;\/BODY&gt;\\n&quot;\n            + &quot;&lt;\/HTML&gt;&quot;;\n\n    \/\/ Generate HTTP response header\n    out.println(&quot;HTTP\/1.0 200 OK&quot;);\n    out.println(&quot;Server: HttpServer 1.0&quot;);\n    out.println(&quot;Date: &quot; + new Date());\n    out.println(&quot;Content-type: &quot; + &quot;text\/html&quot;);\n    out.println(&quot;Content-length: &quot; + page.length());\n    out.println(); \/\/ Blank line between headers and content\n    out.println(page);\n    out.flush(); \/\/ Flush character output stream buffer\n  }\n\n  \/**\n   * Process unsupported requests\n   *\/\n  private void unsupportedRequest(String method, BufferedReader in, PrintWriter out)\n  {\n    if (HttpServer.VERBOSE)\n    {\n      System.out.println(&quot;501 Not Implemented: &quot; + method + &quot; method.&quot;);\n    }\n\n    \/\/ Send Not Implemented message to client\n    out.println(&quot;HTTP\/1.0 501 Not Implemented&quot;);\n    out.println(&quot;Server: HttpServer 1.0&quot;);\n    out.println(&quot;Date: &quot; + new Date());\n    out.println(&quot;Content-Type: text\/html&quot;);\n    out.println(); \/\/ Blank line between headers and content\n    out.println(&quot;&lt;HTML&gt;&quot;);\n    out.println(&quot;&lt;HEAD&gt;&lt;TITLE&gt;Not Implemented&lt;\/TITLE&gt;&lt;\/HEAD&gt;&quot;);\n    out.println(&quot;&lt;BODY&gt;&quot;);\n    out.println(&quot;&lt;H2&gt;501 Not Implemented: &quot; + method + &quot; method.&lt;\/H2&gt;&quot;);\n    out.println(&quot;&lt;\/BODY&gt;&quot;);\n    out.println(&quot;&lt;\/HTML&gt;&quot;);\n    out.flush(); \/\/ Flush character output stream buffer\n  }\n\n  \/**\n   * Informs client that requested file does not exist.\n   *\/\n  private void fileNotFound(String fileRequested, PrintWriter out)\n          throws IOException\n  {\n    if (HttpServer.VERBOSE)\n    {\n      System.out.println(&quot;404 File Not Found: &quot; + fileRequested);\n    }\n\n    out.println(&quot;HTTP\/1.0 404 File Not Found&quot;);\n    out.println(&quot;Server: HttpServer 1.0&quot;);\n    out.println(&quot;Date: &quot; + new Date());\n    out.println(&quot;Content-Type: text\/html&quot;);\n    out.println();  \/\/ Blank line between headers and content\n    out.println(&quot;&lt;HTML&gt;&quot;);\n    out.println(&quot;&lt;HEAD&gt;&lt;TITLE&gt;File Not Found&lt;\/TITLE&gt;&lt;\/HEAD&gt;&quot;);\n    out.println(&quot;&lt;BODY&gt;&quot;);\n    out.println(&quot;&lt;H2&gt;404 File Not Found: &quot; + fileRequested + &quot;&lt;\/H2&gt;&quot;);\n    out.println(&quot;&lt;\/BODY&gt;&quot;);\n    out.println(&quot;&lt;\/HTML&gt;&quot;);\n    out.flush(); \/\/ Flush character output stream buffer\n  }\n\n  \/\/\/\/\/ Private data \/\/\/\/\/\n  \/\/ HttpServer root is the current directory\n  private static final File WEB_ROOT = new File(&quot;.&quot;);\n  \/\/ Default file name for unspecified request filename\n  private static final String DEFAULT_FILE = &quot;index.html&quot;;\n\n  private Socket m_connect;\n\n  private String m_requestHeader;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><strong><code>RequestHandler<\/code><\/strong>&nbsp;relies on some useful utility classes.&nbsp;<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_MIMEType_class\"><\/span>The MIMEType class<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">First, the&nbsp;<strong><code>MIMETypes<\/code><\/strong>&nbsp;class to map a filetype to a MIME type:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\n\n\/**\n * This class provides a mapping from filetype to MIME type.\n *\/\npublic class MIMETypes\n{\n\n  \/**\n   * Returns the MIME type, given a filename\n   *\/\n  public static String getType(String fileName)\n  {\n    String type = null;\n    \/\/ Extract the filetype from the filename\n    int dotIndex = fileName.lastIndexOf(&#039;.&#039;);\n    if (dotIndex != -1)\n    {\n      String fileType = fileName.substring(dotIndex);\n      \/\/ Now, look up the filetype to get the MIME type\n      type = (String) m_map.get(fileType);\n    }\n    if (type == null)\n    {\n      type = UNKNOWN_MIME_TYPE;\n    }\n    return type;\n  }\n\n  \/**\n   * Adds a file type\/MIME type mapping.\n   *\/\n  public static void add(String fileType, String MIMEType)\n  {\n    m_map.put(fileType, MIMEType);\n  }\n\n  \/**\n   * Removes a file type\/MIME type mapping\n   *\/\n  public static void remove(String fileType)\n  {\n    m_map.remove(fileType);\n  }\n\n  \/**\n   * Suppress the constructor, since all methods in this class are static.\n   *\/\n  private MIMETypes()\n  {\n  }\n\n  \/\/\/\/\/\/\/ Private data \/\/\/\/\/\/\/\n  \/\/ The HashMap used to store the relationships between filetype and MIME type\n  private static HashMap m_map = new HashMap();\n\n  \/\/ The MIME types this web server is initially aware of\n  private static final String&#x5B;]&#x5B;] m_initialValues =\n  {\n    {\n      &quot;.class&quot;, &quot;application\/x-java-vm&quot;\n    },\n    {\n      &quot;.css&quot;, &quot;text\/css&quot;\n    },\n    {\n      &quot;.doc&quot;, &quot;application\/msword&quot;\n    },\n    {\n      &quot;.gif&quot;, &quot;image\/gif&quot;\n    },\n    {\n      &quot;.htm&quot;, &quot;text\/html&quot;\n    },\n    {\n      &quot;.html&quot;, &quot;text\/html&quot;\n    },\n    {\n      &quot;.jar&quot;, &quot;application\/x-java-archive&quot;\n    },\n    {\n      &quot;.jpg&quot;, &quot;image\/jpeg&quot;\n    },\n    {\n      &quot;.jpeg&quot;, &quot;image\/jpeg&quot;\n    },\n    {\n      &quot;.mpg&quot;, &quot;video\/mpeg&quot;\n    },\n    {\n      &quot;.mpeg&quot;, &quot;video\/mpeg&quot;\n    },\n    {\n      &quot;.pdf&quot;, &quot;application\/pdf&quot;\n    },\n    {\n      &quot;.png&quot;, &quot;image\/png&quot;\n    },\n    {\n      &quot;.ppt&quot;, &quot;application\/vnd.ms-powerpoint&quot;\n    },\n    {\n      &quot;.ps&quot;, &quot;application\/postscript&quot;\n    },\n    {\n      &quot;.ser&quot;, &quot;application\/x-java-serialized-object&quot;\n    },\n    {\n      &quot;.tiff&quot;, &quot;image\/tiff&quot;\n    },\n    {\n      &quot;.txt&quot;, &quot;text\/plain&quot;\n    },\n    {\n      &quot;.xls&quot;, &quot;application\/vnd.ms-excel&quot;\n    },\n    {\n      &quot;.zip&quot;, &quot;application\/zip&quot;\n    },\n  };\n\n  \/\/ Populate the HashMap on class load.\n  static\n  {\n    for (int i = 0; i &lt; m_initialValues.length; i++)\n    {\n      String key = m_initialValues&#x5B;i]&#x5B;0];\n      String value = m_initialValues&#x5B;i]&#x5B;1];\n      m_map.put(key, value);\n    }\n  }\n\n  \/**\n   * Main entry point, for testing\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    System.out.println(&quot;----BEGIN-----&quot;);\n    for (Iterator iter = m_map.entrySet().iterator(); iter.hasNext();)\n    {\n      Map.Entry entry = (Map.Entry) iter.next();\n      String key = (String) entry.getKey();\n      String value = (String) entry.getValue();\n      System.out.println(key + &quot; : &quot; + value);\n    }\n    System.out.println(&quot;-----END-----&quot;);\n\n    String type = null;\n    type = getType(&quot;bar&quot;);\n    System.out.println(&quot;foo type is: &quot; + type);\n    type = getType(&quot;.foo&quot;);\n    System.out.println(&quot;.foo type is: &quot; + type);\n    type = getType(&quot;.css&quot;);\n    System.out.println(&quot;.css type is: &quot; + type);\n    type = getType(&quot;fromage.pdf&quot;);\n    System.out.println(&quot;fromage.pdf type is: &quot; + type);\n  }\n  \n    private static final String UNKNOWN_MIME_TYPE = &quot;application\/octet-stream&quot;;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that&nbsp;<strong><code>MIMETypes<\/code><\/strong>&nbsp;class has only static methods.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_TeeWriter_Class\"><\/span>The TeeWriter Class<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The second utility class is&nbsp;<strong><code>TeeWriter<\/code><\/strong>, which is a class for inserting a &#8220;Tee&#8221; into a stream, and &#8220;siphoning off&#8221; the output sent to the stream.&nbsp; It is used to capture the response header generated by different parts of the&nbsp;<strong><code>RequestHeader<\/code><\/strong>&nbsp;class.&nbsp; Here it is:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\nimport java.io.FileWriter;\nimport java.io.FilterWriter;\nimport java.io.IOException;\nimport java.io.OutputStreamWriter;\nimport java.io.PrintWriter;\nimport java.io.Writer;\n\n\/**\n * This class provides a &quot;Tee&quot; so that anything written to it is sent to both\n * its Writers. This can be quite useful for logging everything written to a\n * stream.\n *\/\npublic class TeeWriter extends FilterWriter\n{\n  \/**\n   * Constructor\n   *\/\n  public TeeWriter(Writer out1, Writer out2)\n  {\n    super(out1);\n    m_out = out2;\n  }\n\n  \/**\n   * Write a single character.\n   *\n   * @exception IOException If an I\/O error occurs\n   *\/\n  public void write(int c) throws IOException\n  {\n    super.write(c);\n    m_out.write(c);\n  }\n\n  \/**\n   * Write a portion of an array of characters.\n   *\n   * @param cbuf Buffer of characters to be written\n   * @param off Offset from which to start reading characters\n   * @param len Number of characters to be written\n   *\n   * @exception IOException If an I\/O error occurs\n   *\/\n  public void write(char cbuf&#x5B;], int off, int len) throws IOException\n  {\n    super.write(cbuf, off, len);\n    m_out.write(cbuf, off, len);\n  }\n\n  \/**\n   * Write a portion of a string.\n   *\n   * @param str A String\n   * @param off Offset from which to start writing characters\n   * @param len Number of characters to write\n   *\n   * @exception IOException If an I\/O error occurs\n   *\/\n  public void write(String str, int off, int len) throws IOException\n  {\n    super.write(str, off, len);\n    m_out.write(str, off, len);\n  }\n\n  \/**\n   * Flush the stream.\n   *\n   * @exception IOException If an I\/O error occurs\n   *\/\n  public void flush() throws IOException\n  {\n    super.flush();\n    m_out.flush();\n  }\n\n  \/**\n   * Close the stream.\n   *\n   * @exception IOException If an I\/O error occurs\n   *\/\n  public void close() throws IOException\n  {\n    super.close();\n    m_out.close();\n  }\n\n  \/**\n   * Main entry point, for testing.\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    PrintWriter pw = null;\n    try\n    {\n      FileWriter fileOut = new FileWriter(&quot;teeTest.out&quot;);\n      OutputStreamWriter stdOut = new OutputStreamWriter(System.out);\n      TeeWriter tee = new TeeWriter(fileOut, stdOut);\n      pw = new PrintWriter(tee);\n      pw.println(&quot;   Jabberwocky&quot;);\n      pw.println(&quot;       by &quot;);\n      pw.println(&quot;  Lewis Carroll&quot;);\n      pw.println();\n      pw.println(&quot;Twas brillig, and the slithy toves\\n&quot;\n              + &quot;Did gyre and gimble in the wabe:\\n&quot;\n              + &quot;All mimsy were the borogoves,\\n&quot;\n              + &quot;And the mome raths outgrabe.&quot;);\n      pw.flush();\n    }\n    catch (IOException ioe)\n    {\n      ioe.printStackTrace();\n    } finally\n    {\n      pw.close();\n    }\n  }\n\n  \/\/\/\/\/ Private data \/\/\/\/\/\/\n  private Writer m_out;\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Common_Gateway_Interface_CGI\"><\/span>The Common Gateway Interface (CGI)<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The problem with plain HTML pages is that they are static, and never change.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If we want to do something more dynamic &#8212; for example, show the details of a book which the user specifies &#8212; then we have to do something to cause HTML pages to be generated dynamically.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Common Gateway Interface (CGI) was the first solution to this problem.&nbsp; A Web server that implements CGI recognizes that certain requested resources are special, and redirects the request to a separate program for processing.&nbsp; The program may be written in just about any language: C, C++, Perl, Java, etc. and is dynamically launched by the web server as a result of receiving the request.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"643\" height=\"287\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Common-Gateway-Interface.png\" alt=\"\" class=\"wp-image-664\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Common-Gateway-Interface.png 643w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Common-Gateway-Interface-300x134.png 300w\" sizes=\"auto, (max-width: 643px) 100vw, 643px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:13px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The CGI request is typically handled like this:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The Web server receives a request for a resource (for example:&nbsp;<strong><code>\/cgi-bin\/foo<\/code><\/strong>)<\/li><li>The Web server recognizes that the resource either is in a &#8220;special folder&#8221;&nbsp;<strong><code>cgi-bin<\/code><\/strong>, or that it has a&nbsp;<strong><code>.cgi<\/code><\/strong>&nbsp;filetype, and so knows that it should launch the specified file&nbsp;<strong><code>foo<\/code><\/strong>&nbsp;as a program.&nbsp; The Web server passes to the CGI program a set of &#8220;CGI variables&#8221; in the form of environment variables, and other items in the form of command line arguments.&nbsp; The CGI program&#8217;s&nbsp;<strong><code>stdin<\/code><\/strong>&nbsp;is supplied by the web server, and its&nbsp;<strong><code>stdout<\/code><\/strong>&nbsp;and&nbsp;<strong><code>stderr<\/code><\/strong>&nbsp;go to the web server.<\/li><li>The foo program executes, processing the necessary information based on the command line arguments and environment variables, and generates a dynamic HTML document, which it outputs to its&nbsp;<strong><code>stdout<\/code><\/strong>.<\/li><li>The Web server receives the output from the CGI program, and returns it to the client.<\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Note that, to the client, this process is transparent. The client is not aware that a CGI program was involved.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So, every time you go to a Web search engine and type in something to search for, the search engine is doing something like this to generate its results dynamically.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Problems_with_CGI\"><\/span>The Problems with CGI<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">But there are problems with using CGI. The most obvious is that the overhead of firing up a new CGI process for every request is very large. And a typical web server has to deal with very many (thousands or more) simultaneous requests (think online businesses like Amazon, etc.). It is simply not feasible to have that many processes running simultaneously on a single server machine. And if the web server cannot keep up, it is likely to crash or run extremely slowly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Java_Servlets\"><\/span>Java Servlets<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Java Servlets<\/em> are Sun&#8217;s Java-based solution to the problems with CGI.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Later, we&#8217;ll see that Java Server Pages (JSPs) and servlets work together to provide an even better solution.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In order to use Servlets or JSPs, you must have a web server with a Java servlet &#8216;container&#8217;.&nbsp; There are a number of free servlet containers;&nbsp; the most popular, at least for development purposes, is the Apache Foundation&#8217;s Tomcat (since this was first written, many others have appeared).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Apache_Tomcat\"><\/span>Apache Tomcat<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Apache_Tomcat_Logo-1-1024x556.png\" alt=\"\" class=\"wp-image-669\" width=\"177\" height=\"96\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Apache_Tomcat_Logo-1-1024x556.png 1024w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Apache_Tomcat_Logo-1-300x163.png 300w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Apache_Tomcat_Logo-1-768x417.png 768w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Apache_Tomcat_Logo-1-1536x834.png 1536w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/04\/Apache_Tomcat_Logo-1-2048x1112.png 2048w\" sizes=\"auto, (max-width: 177px) 100vw, 177px\" \/><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Tomcat is a free, open-source implementation of Java Servlet and JavaServer Pages technologies developed under the Jakarta project at the Apache Software Foundation. Tomcat is available for commercial use, under the ASF license, from the Apache web site, in both binary and source versions.&nbsp;<\/p>\n\n\n\n<div style=\"height:13px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">To download your own version of Apache Tomcat, go to <a href=\"https:\/\/tomcat.apache.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/tomcat.apache.org\/<\/a>, and follow the instructions there. It will also tell you about the operational details of how to run it.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Note that the various Java IDEs often provide their own equivalent to Apache Tomcat, or even Tomcat itself, so you may not have to download Tomcat; just use what the IDE provides &#8212; often as an optional plugin.<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>What is HTTP? The HyperText Transfer Protocol (HTTP) is a stateless, TCP\/IP-based protocol for communication over the World-Wide Web.&nbsp; It is typically used between a client browser and a web server: The client browser issues a request to the web server.&nbsp; The client: Opens a TCP connection to the web server&#8217;s HTTP port (usually port [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":646,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_eb_attr":"","ocean_front_end_style_editor":"no","ocean_post_layout":"left-sidebar","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"ocs-course-topics-sidebar","ocean_second_sidebar":"0","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"0","ocean_custom_header_template":"0","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"0","ocean_menu_typo_font_family":"0","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"0","footnotes":""},"class_list":["post-651","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/651","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/comments?post=651"}],"version-history":[{"count":9,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/651\/revisions"}],"predecessor-version":[{"id":671,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/651\/revisions\/671"}],"up":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/646"}],"wp:attachment":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/media?parent=651"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}