This document describes the Appweb architecture and how it
processes HTTP requests. It describes the main Appweb components
and the flow of processing.
The Appweb HTTP servers has a modular architecture where
components may be dynamically loaded at runtime depending on the
desired configuration. The key components of Appweb are:
Component
|
Description
|
Mbedthis Portable Runtime
|
Cross-platform, multithreaded portable
runtime. Includes services for memory allocation, dynamic
module loading, safe string handling, socket
communications, threads, thread synchronization,
thread-pool, tasks, timers and debug trace and
logging.
|
Appweb HTTP Server
|
Core HTTP server. Includes services for
initialization, HTTP protocol handling, socket connection
management, logging, virtual hosts, directory and location
blocks, data stream output buffering and background
flushing.
|
Auth Handler
|
Authorization handler. Supports Basic and
Digest authorization on a per directory or virtual host
basis.
|
Static Handler
|
Static content handler. Serves HTML pages,
graphics and other static content.
|
EGI Handler
|
Embedded Gateway Interface handler.
In-process CGI.
|
CGI Handler
|
Common Gateway Interface handler.
|
EJS Module
|
Embedded JavaScript module.
|
ESP Handler
|
Embedded Server Pages handler. Serves
dynamic content based on ESP pages.
|
PHP5 Handler
|
PHP5 handler. Supports PHP version
5.X.X
|
SSL Module
|
Secure Sockets Module. Implements an SSL
provider interface so different SSL protocol stacks can be
loaded from 3rd party vendors.
|
Open SSL Module |
OpenSSL Secure Socket Layer protocol
stack.
|
Matrix SSL Module
|
Peersec Matrix Secure Sockets Layer protocol
stack.
|
Admin Handler
|
Administration handler for management of
Appweb.
|
Mbedthis Portable Runtime (MPR)
The Appweb HTTP Server is built upon a portability layer
called the Mbedthis Portable Runtime (MPR) runtime. This
insulates the rest of the product from the underlying platform
and allows it to be highly portable to new operating systems or
platforms. The MPR also provides a suite of services that
facilitate the creation of high performance, multithreaded
management and server applications, including: thread and
communications management, dynamic module loading, timers, tasks
and logging.
The MPR also provides a safer environment in which to program
as it replaces C APIs that are prone to buffer overflows and
other similar security exploits. The MPR includes a high
performance, safe string library that supports a secure
programming style.
The MPR event processing mechanism can be easily integrated
into existing applications. It supports single and multithreaded
architectures, polled or async event notification, POSIX select
waiting and Windows message loops. When coupled with C and C++
APIs, API web can be easily integrated into most C/C++
applications.
Appweb HTTP Server
The core Appweb
HTTP server is relatively one of the smaller components of the
Appweb product when compared to the dynamic modules that run atop
it. The core server provides a set of services for the handlers
to use when serving content to clients. The goal is to centralize
any facilities that handles might need so the code will not be
replicated in each handler. These services include: the main HTTP
processing and socket communications, initialization and parsing
the Apache style configuration file, buffering, server, virtual
host and directory authorization management.
The core server also configures and enforces any
sandbox resource limits that have been requested in
the configuration file. The include thread limits and HTTP and
URL request size limitations. This enables Appweb to be
deterministic in its use of system resources and to be a good
system citizen. The core Appweb server can be configured to
execute single or multithreaded and with appropriate sandbox
limits, it can scale to serve thousands of requests per second if
required.
Handler Processing
By using the
dynamic module capability of the MPR, Appweb provides a suite of
loadable handlers that serve specialized content for
clients.
HTTP Request Processing
This
section describes the flow of processing with the Appweb server.
While this is not essential information, having a background
understanding of how Appweb works may assist you to better
utilize Appweb in your applications.
Initialization
Appweb uses a one-pass traversal of the
configuration file. This means that the order of directives in
the file does matter. In contrast, Apache uses a two pass parser.
While parsing the configuration file,
LoadModule directives will cause the specified
loadable modules to be added to Appweb. The
AddHandler
directives will cause the specified URL handlers to be activated
and configured for service. The
Listen directives will cause Appweb to open and
bind to the specified IP addresses for incoming HTTP requests.
The
StartThread and
ThreadLimit directives will cause Appweb to
preallocate the number of threads specified by StartThread and to
configure the MPR thread pool not to exceed the
ThreadLimit.
During configuration, Appweb pre-creates handler instances for
all active handlers. When requests arrive, these pristine
instances are cloned for rapid initialization of the required
handlers to service the request.
After performing some security checks and validation tests, the
Appweb server writes the configuration to the error log and then
waits for incoming requests.
Request Acceptance
When a HTTP request arrives, the
Appweb server will examine the network interface on which the
request arrived and if it is assigned to an IP based virtual
host, Appweb will route the request to be handled by that virtual
host. NOTE: this is all internal to Appweb. If name based virtual
hosting is being used, the determination of which virtual host
will process the request must be deferred until the HTTP header
has been parsed and the default server is used to initially parse
the request. See the
Virtual Hosts for
more information.
HTTP Header Parsing
According to the HTTP protocol,
Appweb will read the first line of the HTTP request which
specifies the operation method to use, requested URL and the
variant of the HTTP protocol to use. This typically looks like
this:
GET /index.html HTTP/1.1
This example is asking for the
/index.html document via the
GET method using the HTTP/1.1 protocol. Appweb then proceeds to
read the HTTP headers. Typically there are 5-15 headers which
specify further information to help the server process the
request. Headers are of the format:
Header: value
Some typical headers are:
Header
|
Description
|
AUTHORIZATION
|
Authorization details including user name,
realm, password digest and other authorization parameters
to implement Basic and Digest authentication.
|
CONTENT_LENGTH
|
Length of any addition data with a POST
request.
|
CONTENT_TYPE
|
Mime types the client prefers to accept in
response to this request.
|
COOKIE
|
Cookie associated with the URL in the
clients cookie cache.
|
HOST
|
Name to the target host to serve the
request. This specifies the host name when using virtual
hosting.
|
IF_MODIFIED_SINCE
|
Only return the content if it has been
modified since the date specified. Clients who have cached
copies of a document (or graphics) use this header to allow
the server to skip copying the document if it has not
changed.
|
KEEP-ALIVE
|
Request the server to keep the connection
alive so that subsequent requests can reuse the
connection. |
Appweb stores the values of all the HTTP headers in a hash lookup
table for fast access. When all the headers have been read and
parsed, Appweb proceed to do handler matching. This will occur
before any associated POST data has been read from the client.
POST data may be form data submitted by the client or it may be a
file upload using the PUT method.
Handler Matching
Appweb has a powerful handler matching
algorithm that adaptable to most requirements. Handlers may match
requests based on the URL extension or on the leading portion of
a URL (called prefix matching). Both forms are specified per
handler in the Appweb configuration file.
To associate a handler to a given extension, use the
AddHandler
directive. For example:
AddHandler espHandler .myDoc
This will cause the espHandler to respond to any URL that has a
".myDoc" extension.
To associate a handler to a URL prefix, use the
Location
directive. For example:
<Location /projects/myVideo>
SetHandler myVideoHandler
</Location>
This will cause the myVideoHandler to respond to any URL that
begins with /projects/myVideo after the
http://site portion of the URL.
Running Handlers
Multiple handlers may match a URL. In this case they are
applied in the order they are specified in the Appweb
configuration file. In the default configuration, the copyHandler
is specified last without any extension and it thus becomes a
catch-all. It will process any document not matched by other
handlers and it will return the document without processing back
to the client.
Once the handlers have been matched, they are run in order.
The first hander to either successfully process the request or to
abort processing the request will terminate the running of
subsequent handlers. A handler may rewrite the request and it may
re-execute or even rematch the handlers. This is used to handle
redirects internally where permissible.
The authHandler
Appweb configures the authHandler first without an extension
so it will match every document and will always run first. If the
accessing user is not authorized, the authHandler will will
terminate processing of the request and return an authorization
error back to the client. If the user is authorized, the
authHandler will do nothing further. Appweb will then run
subsequent matching handlers until a handler processes the
request.
Output Buffering
The various handlers have quite
different output buffering needs. The copyHandler needs to be
able to copy static content from the file system back to the
client. The espHandler needs to be able to buffer generated
output to compute a content length and then flush the buffer.
Other custom handlers may need to write large volumes of
unbuffered data. The problem is that the Appweb HTTP server needs
a uniform way to manage this variety of output data.
Appweb solves this problem by providing a DataStream interface
for output buffering. The DataStream interface supports all these
output needs with one interface.
Request Completion
When the handler has completed
processing the request and the output data has been flushed, the
Appweb server will determine if HTTP Keep-Alive can be used.
Keep-Alive allows a socket connection to be reused for subsequent
requests which typically boosts throughput performance by 50% or
more. To use Keep-Alive the length of the generated content must
be known and the client must have not stipulated to not use
Keep-Alive.
Secure Sockets Layer
The SSL handler implements an open
SSL provider interface so that SSL provider handlers such as
openSslHandler and matrixSslHandler can be selected at
run-time.