Tracing the Life of an HTTP Request
HTTP request processing with IIS 6.0 and ASP.NET 1.1
The deep permeation of the
World Wide Web into the
life of the common man
has lent itself to a variety
of uses, most notably as a backbone
for business-to-consumer (B2C)
communication, creating a new
business model called e-commerce.
This article traces the lifetime of an
HTTP request from its inception
inside a Web browser to its interception
by IIS 6.0, its processing by
ASP.NET 1.1, and an HTTP response
being sent back to the browser.
The Hypertext Transfer Protocol
(HTTP) is the foundation of the
Web. HTTP was invented by Tim
Berners-Lee at the CERN Labs and
is documented in RFC 2068
(www.w3.org/Protocols/rfc2068/rfc2068). HTTP is a request/response,
text-based, stateless protocol used
to communicate between a Web
client (browser) and a Web server.
A typical Web interaction starts
when the browser sends an HTTP
request to the Web server. The Web
server listens for requests, generally
over TCP port 80. After receiving the
request, the Web server identifies
the resource associated with the
request, processes application logic
identified by that resource, and
returns an HTTP response that may
consist of text or binary data.
As you can see, this communication
process requires only that the
user have a browser to request a
resource from a remote Web server.
This zero-footprint install and the
ability to access the remote resource
from anywhere over the Internet are
the two main factors in the success
of this model.
IIS 6.0 is the latest offering from
Microsoft in the Web server domain.
Along with the application services
provided by ASP.NET 1.1, it stakes a
claim for the most reliable, scalable,
secure, and manageable HTTP
request processing engine available today.
A Simple HTTP Request/Response Dialog
Let us look at an example of a
simple HTTP request/response dialogue.
Suppose a file called
ILoveHttp.htm is deployed in the
root directory of your Web server
and is made accessible via the URL
http://www.example.org/ILoveHttp.htm.
The file contains some simple HTML:
<html>
<body>
<h1> I love HTTP! </h1>
<body>
</html>
Typing http://www.example.org/
ILoveHttp.htm in the address bar of
the browser (in this case Internet
Explorer 6.0) would generate an
HTTP request that would look
something like:
GET /ILoveHttp.htm HTTP 1.1
Accept: */*
Accept-Language: en-us
Connection: Keep-Alive
Host: www.example.org
User-Agent: Mozilla 4.0 (compatible;
MSIE 6.0; Windows NT 5.0)
Accept-Encoding: gzip, deflate
The first line of the request is
called the request line, which
includes the method (GET), the
resource path (/ILoveHttp.htm), and
the HTTP version (HTTP/1.1). After
the request line come the header
lines. The HTTP headers provide
additional information required to
process the request, such as the language
and encoding supported by
the Web browser. Notice the blank
line after the headers. This line separates
the headers from the body.
This request does not have a body
because it uses the GET method. A
body is only appropriate if the
request uses the POST method.
Assuming that ILoveHttp.htm
was found inside the root directory
of the Web server and it had the requisite
read permissions, the
response that the Web server sends
would look something like:
HTTP/1.1 200 OK
Server: Microsoft-IIS/6.0
Date: Sun, 14 Jul 2003 06:45:23
GMT
Content-Length: 57
Content-Type: text/html
Cache-control: private
<html>
<body>
<h1> I love HTTP! </h1>
<body>
</html>
The first line of the response,
called the status line, contains the
HTTP version used for the response,
the status code (200), and the reason
phrase. After the status line
come the header lines. The headers
in the HTTP response provide additional
information about the message
like its MIME content type and
its content length in bytes. The
header lines are followed by an
empty line, after which comes the
body of the response.
You can find more about HTTP
request and response header fields at
Microsoft.
The Web Server: IIS 6.0
IIS 6.0 is an HTTP, SMTP, FTP,
and NNTP server all in one. It is
available on all editions of Windows
2003. In this article I will discuss
only the Web server capabilities of
IIS 6.0. As a Web server, IIS 6.0
enables quick and easy deployment
of Web sites and provides the platform
to build powerful Web applications
using ASP.NET 1.1.
IIS 6.0 is capable of hosting multiple
Web sites in a single installation.
A Web site is a collection of
Web applications and is uniquely
identified by a host name, a port
number, and a host header. A Web
application is a collection of Web
resources (text and binary files) that
resides inside a virtual directory of a
Web site. Figure 1 shows a high-level
logical architecture of IIS 6.0.
Figure 1
The details of the various components
are as follows.
HTTP.sys
HTTP.sys is the operating system's
HTTP protocol stack and is
implemented as a kernel mode
component. It listens to requests,
parses them, and then routes them
to the appropriate request queue.
Each request queue corresponds to
a particular application pool.
Since no user code runs as part
of HTTP.sys, it is isolated from any
failure in application code. Even if a
Web application crashes, HTTP.sys
continues to receive and queue
requests for that application, ensuring
that the end user's experience is
not interrupted. Also, since
HTTP.sys runs as part of kernel
code, it is very efficient.
After a request has been
processed appropriately, HTTP.sys
caches and returns the response to
the Web browser.
Application Pools
An application pool is a logical
grouping of Web applications hosted
inside IIS 6.0. Each application
pool can have zero or more Web
applications in it. Each application
pool serves one request queue
maintained by HTTP.sys, as illustrated
by the dashed arrows in Figure 1.
Application pools can be created
using the IIS Manager (inetmgr.exe).
Web Server Administration and Monitoring Component
The Web server administration
and monitoring component (AKA
Web service) is a user mode configuration
and process manager that
manages server operations and
monitors the execution of application
code. Like HTTP.sys, this component
does not run any user code
as part of itself, therefore remaining
isolated from application failures.
This component (iisw3adm.dll)
gets loaded as a nonshared service
host process (svchost.exe). The
services provided by the Web service are:
Configuration: During initialization,
the Web service reads the inmemory
copy of metabase.xml
(the IIS 6.0 configuration file) and
initializes HTTP.sys with the
appropriate request/routing information.
Fault tolerance: If the Web service
sees a failed application, it
recycles and restarts the associated
worker process automatically.
Worker process management:
The user can configure when a
worker process will be started,
recycled, or restarted. This information
can be configured using the IIS Manager.
Worker Process
Each application pool is serviced
by one dedicated IIS 6.0 worker
process (w3wp.exe) per processor.
Having separate worker processes
for separate application pools provides
process isolation to the Web
applications. This means that a malfunctioning
Web application in an
application pool has no effect on
Web applications in other application
pools.
The worker process runs a Web
core component (w3core.dll). This
component is responsible for loading
the ASP.NET runtime
(aspnet_isapi.dll) in case the HTTP
request happens to be for an
ASP.NET resource.
The worker process fetches
requests directly from the kernel
request queues maintained by
HTTP.sys. This obviates the need for
user-mode interprocess communication,
making the fetch process
very efficient.
The worker process runs as
a network service – a Windows
account with bare minimum
privileges.
ASP.NET 1.1: The Application Server
ASP.NET is an extensible Web
programming model that works
with IIS 6.0 and assists developers in
producing dynamic Web applications.
ASP.NET is installed when IIS
6.0 is configured as an application server.
When IIS receives a request for
an ASP.NET resource, it hands over
the processing of the request to the
ASP.NET ISAPI filter (aspnet_isapi.
dll). The mapping of resource extensions
to ISAPI filters can be configured
using the IIS Manager.
ASP.NET protects applications
belonging to the same application
pool from each other by processing
each of them in separate AppDomains.
After a request is handed over by
IIS 6.0 to ASP.NET it is run through a
sequence of events commonly
referred to as the HTTP pipeline.
The first thing that ASP.NET does
after receiving a request is to instantiate
an object of an undocumented
type that inherits from the
HttpWorkerRequest (System.
Web.HttpWorkerRequest) abstract
class. This object is initialized with
information from the HTTP request.
Next, an instance of the
HttpRuntime (System.Web.HttpRuntime) class is created. This
class is a singleton in the scope of
the Web application; that is, only
one instance of the class exists per
application (or AppDomain). The
HttpWorker Request object is then
passed to the static ProcessRequest
method of the HttpRuntime
class. The HttpR untime class provides
a set of runtime services to
the ASP.NET applications.
The ProcessRequest method of
the HttpRuntime class carries out
the following sequence of steps.
1. Create an instance of the
HttpContext (System.Web.HttpContext) class. This object acts
like a memento for the request. It
stays with the request throughout
its life inside the ASP.NET HTTP
pipeline and request-specific
information can be persisted
within it. A partial (pun intended)
definition of HttpContext is
shown in Listing 1.
Notice that the constructor of
the HttpContext is passed the
HttpWorkerRequest object.
The constructor of HttpContext
instantiates a bunch of useful
objects of types like HttpRequest
(System.Web.HttpRequest),
HttpResponse (System.
Web.HttpResponse), Http
ServerUtililty (System.Web.
HttpServerUtility), and
HttpSessionState (System.
Web.HttpSessionState), and then
initializes them with the information
available from the
HttpWorkerRequest instance passed to it.
2. Next, the ProcessRequest method
calls the static GetApplication
Instance method of the Http
ApplicationFactory (System.
Web.HttpApplicationFactory)
class to get an instance of
HttpApplication (System.Web.HttpApplication).
The runtime maintains a pool
of HttpApplication objects. The
GetApplicationInstance method
either gets the HttpApplication
object from this pool (if available)
or instantiates a new one.
The signature of the GetApplicationInstance method is:
static IHttpHandler
GetApplicationInstance
(HttpContext context);
If the Web application has
a global.asax file in its virtual
directory the object returned by
GetApplicationInstance is of a
type derived from HttpApplication.
This class extends the
HttpApplication class by the code
defined in global. asax.
Now that the
HttpApplication object has
been created, it reads the
machine-level configuration
files (machine.config and
web.config) and loads the modules
required to pre- or postprocess
the request. Modules
are classes that implement the
System.Web.IHttpModule interface,
and are compiled and
placed in the bin directory of
the application. The section of
configuration files that configures
the modules looks like:
<httpModules>
<add name="OutputCache"
type="System.Web.Caching.OutputCacheModule"/>
<!— More like these ‡
</httpModules>
3. Next, the ProcessRequest method
calls the BeginProcessRequest
(System.Web.IAsyncHandler.Be
ginProcessRequest) method of
the HttpApplication object.
Using the information found in
the <httpHandlers> section of
the configuration files and the
URL of the request, the
BeginProcess Request method
tries to locate the appropriate
handler for the resource
requested. The <httpHandlers>
section of the configuration
files, which maps URLs to handlers
or handler factories, looks
like that shown in Listing 2.
In <httpHandlers> file extensions
(or filenames) are mapped
to either HTTP handlers (classes
that implement the System.Web.
IHttpHandler interface) or an
HTTP handler factory (classes
that implement the System.
Web.IHttp Handler Factory interface).
If the mapping is to an
HTTP handler factory, the
HttpApplication class uses the
GetHandler method to get a handle
to the HTTP handler.
The HttpApplication class also
fires a bunch of events like
BeginRequest, Authenticate
Request, and AuthorizeRequest.
These events can be handled
either in some of the HTTP modules
or in global.asax.
When the HttpApplication
object charged with servicing a
particular request invokes the
GetHandler method on the
System.Web.UI.PageHandler
Factory, what it gets is an instance
of a class derived from the Page
(System.Web.UI.Page) class. The
Page class implements the
IHttpHandler interface. Next, the
ProcessRequest (IHttpHand
ler.ProcessRequest) method of the
Page object is called. This method
– which does the actual request
processing – uses the page's
Response property to access the
HttpResponse object associated
with the request. The Http
Response object has several overloaded
Write methods that give
the Page object access to the
response stream back to the
browser. The Page object has
access to the request's
HttpContext object through its
Context property.
Conclusion
In this article I have shown you
the framework that IIS 6.0 and
ASP.NET 1.1 provide to process
HTTP requests. I hope you enjoyed
reading it.
References
Technical Overview of Internet
Information Services (IIS) 6.0:
www.microsoft.com/windowsserver2003/techinfo/overview/iis.mspx
Onion, F. (2003). Essential ASP.NET Programming. Addison-Wesley.
Esposito, D. (2003) Programming ASP.NET. Microsoft Press.
Author Bio
Mujtaba Syed is a software architect with Marlabs Inc. He is an MCSD in .NET (early achiever certificate) and an MCAD in .NET (charter member). He has six years of software architecting and developing experience, half of which focused on .NET.
mujtaba@marlabs.com
Listing 1
public sealed class HttpContext
{
// Constructor
public HttpContext(System.Web.HttpWorkerRequest wr);
// Properties
public HttpRequest Request { get; }
public HttpResponse Response { get; }
public HttpServerUtility Server { get; }
public HttpSessionState Session { get; }
}
Listing 2
<httpHandlers>
<add verb="*" path="*.aspx"
type="System.Web.UI.PageHandlerFactory"/>
<add verb="*" path="*.ashx"
type="System.Web.UI.SimpleHandlerFactory"/>
<add verb="*" path="*.config"
type="System.Web.HttpForbiddenHandler"/>
<add verb="*" path="*.cs"
type="System.Web.HttpForbiddenHandler"/>
<!— More like these ‡
</httpHandlers>
All Rights Reserved
Copyright © 2004 SYS-CON Media, Inc.
E-mail:
info@sys-con.com