How Java Web Servers Work
Pages: 1, 2, 3
The Request Class
The Request class represents an HTTP request. An instance of
this class is constructed by passing the InputStream object
obtained from a Socket that handles the communication with the
client. Call one of the read methods of the
InputStream object to obtain the HTTP request raw data.
The Request class has two public methods: parse
and getUri. The parse method parses the raw data in
the HTTP request. It doesn't do much--the only information it makes available
is the URI of the HTTP request, which it obtains by calling the private method
parseUri. The parseUri method stores the URI in the
uri variable. Invoke the public getUri method to
return the URI of the HTTP request.
To understand how the parse and parseUri methods
work, you need to know the structure of an HTTP request, which is defined in RFC 2616(.pdf).
An HTTP request contains three parts:
- Request line
- Headers
- Message body
For now, we are only interested in the first part of the HTTP request, the
request line. A request line begins with a method token, is followed by the
request URI and the protocol version, and ends with carriage-return linefeed
(CRLF) characters. Elements in the request line are separated by a space
character. For instance, the request line for a request for the
index.html file using the GET method is:
GET /index.html HTTP/1.1
The parse method reads the whole byte stream from the socket's
InputStream passed to the Request object, and stores
the byte array in a buffer. It then populates a StringBuffer
object called request using the bytes in the buffer
byte array, and passes the String representation of the
StringBuffer to the parseUri method.
The parse method is given in Listing 1.2.
Listing 1.2. The Request class' parse
method
public void parse() {
// Read a set of characters from the socket
StringBuffer request = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];
try {
i = input.read(buffer);
}
catch (IOException e) {
e.printStackTrace();
i = -1;
}
for (int j=0; j<i; j++) {
request.append((char) buffer[j]);
}
System.out.print(request.toString());
uri = parseUri(request.toString());
}
The parseUri method then obtains the URI from the request line.
Listing 1.3 shows the parseUri method. The parseUri
method searches for the first and the second spaces in the request and obtains
the URI from there.
Listing 1.3. The Request class' parseUri
method
private String parseUri(String requestString) {
int index1, index2;
index1 = requestString.indexOf(' ');
if (index1 != -1) {
index2 = requestString.indexOf(' ', index1 + 1);
if (index2 > index1)
return requestString.substring(index1 + 1, index2);
}
return null;
}
The Response Class
The Response class represents an HTTP response. Its constructor
accepts an OutputStream object, such as the following:
public Response(OutputStream output) {
this.output = output;
}
A Response object is constructed by the HttpServer
class' await method by passing the OutputStream
object obtained from the socket.
The Response class has two public methods:
setRequest and sendStaticResource. The
setRequest method is used to pass a Request object to
the Response object. It is as simple as the code in Listing
1.4.
Listing 1.4. The Response class' setRequest
method
public void setRequest(Request request) {
this.request = request;
}
The sendStaticResource method is used to send a static
resource, such as an HTML file. Its implementation is given in Listing 1.5.
Listing 1.5. The Response class'
sendStaticResource method
public void sendStaticResource() throws IOException {
byte[] bytes = new byte[BUFFER_SIZE];
FileInputStream fis = null;
try {
File file = new File(HttpServer.WEB_ROOT, request.getUri());
if (file.exists()) {
fis = new FileInputStream(file);
int ch = fis.read(bytes, 0, BUFFER_SIZE);
while (ch != -1) {
output.write(bytes, 0, ch);
ch = fis.read(bytes, 0, BUFFER_SIZE);
}
}
else {
// file not found
String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: 23\r\n" +
"\r\n" +
"<h1>File Not Found</h1>";
output.write(errorMessage.getBytes());
}
}
catch (Exception e) {
// thrown if cannot instantiate a File object
System.out.println(e.toString() );
}
finally {
if (fis != null)
fis.close();
}
}
The sendStaticResource method is very simple. It first
instantiates the java.io.File class by passing the parent and
child paths to the File class' constructor.
File file = new File(HttpServer.WEB_ROOT, request.getUri());
It then checks if the file exists. If it does, the
sendStaticResource method constructs a
java.io.FileInputStream object by passing the File
object. It then invokes the read method of the
FileInputStream and writes the byte array to the
OutputStream output. Note that in this case, the content of the
static resource is sent to the browser as raw data.
if (file.exists()) {
fis = new FileInputStream(file);
int ch = fis.read(bytes, 0, BUFFER_SIZE);
while (ch != -1) {
output.write(bytes, 0, ch);
ch = fis.read(bytes, 0, BUFFER_SIZE);
}
}
If the file does not exist, the sendStaticResource method sends
an error message to the browser.
String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: 23\r\n" +
"\r\n" +
"<h1>File Not Found</h1>";
output.write(errorMessage.getBytes());
Compiling and Running the Application
To compile and run the application, you first need to extract the .zip file containing the application for this article. The directory you extract the .zip file into is called the working directory and will have three sub-directories: src/, classes/, and lib/. To compile the application, type the following from the working directory:
javac -d . src/ex01/pyrmont/*.java
The -d option writes the results to the current, not the
src/, directory.
To run the application, type the following from the working directory:
java ex01.pyrmont.HttpServer
To test the application, open your browser and type the following in the URL or Address box:
http://localhost:8080/index.html
You will see the index.html page displayed in your browser, as in Figure 1.

Figure 1. The output from the web server
On the console, you can see something like the following:
GET /index.html HTTP/1.1
Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
Host: localhost:8080
Connection: Keep-Alive
GET /images/logo.gif HTTP/1.1
Accept: */*
Referer: http://localhost:8080/index.html
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
Host: localhost:8080
Connection: Keep-Alive
Summary
In this article, you have seen how a simple web server works. The application accompanying this article consists of only three classes and is not fully functional. Nevertheless, it serves as a good learning tool.
Budi Kurniawan is a senior J2EE architect and author.
Return to ONJava.com.
-
Thanks a lot.
2007-10-08 02:58:22 NewbiX [View]
-
Thanks a lot.
2007-10-08 02:57:55 NewbiX [View]
-
Java
2007-07-09 01:44:39 apeksha [View]
-
Nice One...
2006-03-04 04:13:56 Joeras [View]
-
Nice work
2005-08-31 08:25:46 minoopy [View]
-
Good start
2005-04-17 17:03:44 siv_s_g [View]
-
Good Article
2005-03-23 22:20:21 kuttus [View]
-
Queries
2005-02-05 04:20:06 hemanti [View]
- Trackback from http://blog.csdn.net/freeknightlcw/archive/2004/11/18/186411.aspx
How Servlet Containers Workï¼zz ï¼
2004-11-18 04:04:07 [View]
-
Another comment on Http Client source
2004-05-11 00:32:00 Pissalou [View]
-
Another comment on Http Client source
2004-05-11 00:29:03 Pissalou [View]
-
dymanic web pages
2004-03-23 05:52:19 hobgoblin [View]
-
Would you add some code processing request parameters?
2004-02-03 19:51:23 zerol [View]
-
A very very good article.
2004-01-10 03:58:18 anonymous2 [View]
-
This is one of a kind
2003-07-09 22:34:19 anonymous2 [View]
-
This is one of a kind
2004-01-05 03:25:20 anonymous2 [View]
-
This is one of a kind
2003-08-28 03:20:49 anonymous2 [View]
-
This is one of a kind
2003-08-28 05:34:44 anonymous2 [View]
-
Quite Informative
2003-07-02 05:27:07 anonymous2 [View]
-
Concise and Precise
2003-06-09 08:45:51 anonymous2 [View]
-
very good
2003-05-27 10:06:41 anonymous2 [View]
-
very good
2006-03-04 04:11:05 Joeras [View]
-
Error in first example
2003-05-21 01:49:56 anonymous2 [View]
-
Simple, Clear and Concise
2003-05-17 12:09:54 anonymous2 [View]
-
Very good article
2003-05-06 08:24:10 anonymous2 [View]
-
Excellent One
2003-05-01 20:51:10 anonymous2 [View]
-
basic server operation
2003-04-25 07:32:45 mjjava [View]
-
Nice article
2003-04-24 08:27:43 anonymous2 [View]