This is a continuation in the series of post to build a static HTTP server from scratch. Previous post about Unit testing can be found here.
In this post we are going to refactor the code a little bit to make it somewhat more modular and configurable. Modular in the sense, break out from a single class into smaller classes based on functionality. Finally remove hard-coded configurations.
Break it down
At this point our entire code resides in one class
HttpServer. We will break this down into two, an Interface
HttpRequestHandler. The interface
Http is going to hold some of the constants like, status codes and header names and each instance of
HttpRequestHandler will service one incoming request. After the refactoring our main class
HttpServer will read the server configuration, based on the configuration create a
ServerSocket and listen to requests. When a request arrives, creates an instance of HttpRequestHandler and spawn a new thread to process the request.
Like any configurable application, our server will also have a default set of configuration and user can override them using command line arguments. For default configuration we will create a
server.properties file with the following contents in the resources directory.
# default server port server.port=8080 # default hostname server.name=localhost # default server root server.root=server # Server string server.response.version=Http Server v1.0
We will move all the “loose” HTML files into a directory called
server in the root of the repository. This directory will act as our fallback document root. Document root is the directory from which requests will be served.
Next we will create our Interface
Http which will define all the constants that we need. Inside this interface we will define three other interfaces
Each new request will be served by a new instance of
HttpRequestHandler. Create this class and move all the logic for the moment into the
run method. To help us serve a request we define four helper methods
log as shown below.
HTTP header Connection
Most browsers will send HTTP header
Connection: keep-alive. This is to use the same connection to request multiple resources. A quick way to speed up page load performance. Since our server only handles single resource request per connection, in our response we will set the header
Connection: close to indicate that we are closing this connection.
Code up to this point can be found on github branch step-2. After this we will refactor to support new config property
web.root. Also the run method’s
try/catch block is very big, that will also be broken down into finer chunks for better error handling to send a
500 Internal Server Error when an exceptions occurs.