zhxy/http服务器/appweb-4.3.4-0/doc/ref/appweb/architecture.html

544 lines
34 KiB
HTML

<!-- BeginDsi "dsi/head.html" -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Embedthis Appweb 4.3.4 Documentation</title>
<meta name="keywords" content="embedded web server, web server software, embedded HTTP, application web server,
embedded server, small web server, HTTP server, library web server, library HTTP, HTTP library" />
<meta name="description" content="Embedthis Sofware provides commercial and open source embedded web servers for
devices and applications." />
<meta name="robots" content="index,follow" />
<link href="../../doc.css" rel="stylesheet" type="text/css" />
<link href="../../print.css" rel="stylesheet" type="text/css" media="print"/>
<!--[if IE]>
<link href="../../iehacks.css" rel="stylesheet" type="text/css" />
<![endif]-->
<link href="http://www.google.com/cse/style/look/default.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div class="top">
<a class="logo" href="http://appwebserver.org/">&nbsp;</a>
<div class="topRight">
<div class="search">
<div id="cse-search-form"></div>
<div class="version">Embedthis Appweb 4.3.4</div>
</div>
</div>
<div class="crumbs">
<a href="../../index.html">Home</a>
<!-- EndDsi -->
&gt; <a href="index.html">Programmers Reference</a> &gt; <b>Architecture</b>
</div>
</div>
<div class="content">
<div class="contentRight">
<h1>Quick Nav</h1>
<ul>
<li><a href="#deployment">Deployment Models</a></li>
<li><a href="#processing">Processing Architecture</a></li>
<li><a href="#modules">Appweb Modules</a></li>
<li><a href="#configuration">Appweb Configuration</a></li>
<li><a href="#requests">Request Processing</a></li>
<li><a href="#pipeline">Request Pipeline</a></li>
<li><a href="#frameworks">Web Frameworks</a></li>
<li><a href="#security">Security</a></li>
<li><a href="#mpr">Portable Runtime</a></li>
</ul>
<h1>See Also</h1>
<ul>
<li><a href="../../guide/appweb/overview.html">User Guide Overview</a></li>
<li><a href="../../guide/appweb/users/authentication.html">Authorization</a></li>
<li><a href="../../guide/appweb/users/configuration.html">Configuration</a></li>
<li><a href="../../guide/appweb/users/configuration.html#directives">Configuration Directives</a></li>
<li><a href="../../guide/appweb/users/stages.html">Pipeline Stages</a></li>
<li><a href="../../guide/appweb/users/client.html">HTTP Client</a></li>
<li><a href="../../guide/appweb/users/modules.html">Loadable Modules</a></li>
<li><a href="../../guide/appweb/users/ports.html">Ports and Binding</a></li>
<li><a href="../../guide/appweb/users/ssl.html">Secure Sockets Layer</a></li>
<li><a href="../../guide/appweb/users/vhosts.html">Virtual Hosts</a></li>
</ul>
</div>
<div class="contentLeft">
<h1>Appweb Architecture</h1><!--
Diagrams:
- Process diagram
- Request pipeline
- Module Block diagram
- Key objects
-->
<p>The Appweb HTTP web server is the fastest little web server. It is a high-performance yet compact
embeddable webserver that has a modular, secure core. It supports an extensive feature set including:
HTTP/1.1, TLS/SSL, CGI, PHP, ESP, Ejscript, Virtual Hosts, Digest
Authentication, Apache style configuration, and logging and security sandboxing. Yet Appweb remains very
small (from 1MB) and exceptionally fast (&gt; 7,000 requests per second).</p>
<p>Appweb supports dynamic web application frameworks like ESP, Ejscript and PHP. It also supports older
web creation strategies like CGI.</p>
<p>Appweb is an event-driven, multi-threaded web server and is able to support many
thousands of requests per second but it does not try to scale out like an enterprise class server for
top-tier web sites.
Rather, it aims to be robust, secure and blazing fast with low and predictable memory utilization.</p>
<a id="deployment"></a>
<h2 class="section">Deployment Models</h2>
<p>Appweb can be deployed in several ways:</p>
<ul>
<li>As a stand-alone web server</li>
<li>Embedded in applications and devices</li>
<li>Proxied behind front-end web servers</li>
</ul>
<h3>Stand-Alone Web Server</h3>
<p>The Appweb distribution contains a robust, secure, stand-alone web server. The binary installation will
install this web server to be automatically started as a system daemon/service. It is supervised by an
manager process which acts as a guardian to start, monitor and restart Appweb if required.</p>
<h3>Embedded in Applications and Devices</h3>
<p>Appweb provides an embeddable server and client library so that any application can be web-enabled. When
embedded, the application can provide data and respond to requests over HTTP. For devices, Appweb can be
configured with the minimal required set of features for minimal memory and security footprint.</p>
<h3>Proxied</h3>
<p>Appweb is an ideal application web server when running behind a reverse proxy. The
reverse proxy dispatches incoming requests to a set of Appweb instances which can effectively host
ESP, Ejscript or PHP applications.</p>
<a id="processing"></a>
<h2 class="section">Processing Architecture</h2>
<p>Appweb typically runs one, multi-threaded, event driven process. Appweb uses a non-blocking
event driven architecture and is capable of running many requests simultaneously.</p>
<h3>Event Driven and Multi-threaded</h3>
<p>While Appweb is multi-threaded, it does not consume a thread per request. A high performance thread pool
is used to temporarily loan worker threads as required to service incoming requests. While waiting for
incoming and outgoing I/O, the worker thread is returned to the pool for use by other requests. This
architecture minimizes memory usage by reusing threads and provides excellent performance due to the thread
pool. Further, it scales well, as one thread can service many requests.</p>
<a id="modules"></a>
<h2 class="section">Appweb Modules</h2>
<p>Embeddable web servers have several competing goals:</p>
<ul>
<li>Minimize memory footprint</li>
<li>Minimize CPU consumption</li>
<li>Maximize security</li>
<li>Provide a strong and standard feature set</li>
</ul>
<p>To meet all these goals in one server is difficult. Appweb uses loadable modules so that the core Appweb
HTTP server may be compact, secure, and fast while still having the ability to grow functionality as
required.</p>
<p>An Appweb loadable module is a discrete unit of functionality that may be linked into Appweb to enhance
the core HTTP server. A module may be a request handler, filter, network connector, or simply a "lump" of
code.</p>
<h3>Core Components</h3>
<p>Appweb has a modular architecture where modules are dynamically loaded at runtime depending on the
desired configuration. The key components of Appweb are:</p>
<p><img src="../../images/modules.jpg" alt="Appweb Architecture" /></p>
<table title="Components">
<thead>
<tr>
<th>Component</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="nowrap">Multithreaded Portable Runtime</td>
<td>Cross-platform, multi-threaded portable runtime. Includes services for memory allocation,
dynamic module loading, safe string handling, lists, hashing, command execution, socket
communications, threads, thread synchronization, thread-pool, events, timers, debug trace and
logging.</td>
</tr>
<tr>
<td>Appweb HTTP Core Library</td>
<td>Core HTTP server. Includes services for initialization, HTTP protocol handling, socket
connection management, logging, virtual hosts, directory and location blocks, request processing
pipeline, and module loading and management.</td>
</tr>
<tr>
<td>File Handler</td>
<td>The File handler serves static content such as HTML pages, images and PDF files. It works
cooperatively with the Send connector to eliminate reading such content into memory. The File
handler sends details of the content name via the processing pipeline to the Send connector which
uses special O/S APIs to directly copy files to the network.</td>
</tr>
<tr>
<td>ESP Handler</td>
<td>The Embedded Server Pages (ESP) web framework is an advanced, Model,View,Controller "C"
language web framework.</td>
</tr>
<tr>
<td>Ejscript Handler</td>
<td>Ejscript Web Framework Handler. This is a Server-Side JavaScript web application framework.
Ideal for dynamic web applications.</td>
</tr>
<tr>
<td>PHP Handler</td>
<td>In-memory handler module for the PHP web environment.</td>
</tr>
<tr>
<td>CGI Handler</td>
<td>Common Gateway Interface handler.</td>
</tr>
<tr>
<td>Chunk Filter</td>
<td>The Chunk applies Transfer Chunk Encoding to outgoing data. Chunk encoding enables the HTTP
connection to be reused for subsequent requests without having to establish a new TCP/IP
connection. This can significantly improve network and application performance.</td>
</tr>
<tr>
<td>Range Filter</td>
<td>The Range filter selects the requested I/O range by the client. The Range filter works
cooperatively with the File handler and Send connector to eliminate copying and reading static
content for ranged requests.</td>
</tr>
<tr>
<td>Net Connector</td>
<td>The Net connector is the general purpose transmitter of content to the client. It supports
vectored gather/scatter writes for optimal performance.</td>
</tr>
<tr>
<td>Send Connector</td>
<td>The Send connector is a special purpose transmitter of static file content to the client. It
uses operating system APIs to send file data to the client without reading the data into Appweb. It
also uses vectored gather/scatter I/O to blend response, chunk, and range headers into the static
data. These strategies dramatically boost the performance of serving static data.</td>
</tr>
<tr>
<td>Secure Sockets Layer (SSL)</td>
<td>Secure Socket Layer protocol stack. This is a virtual interface that can selectively support a
variety of SSL providers including: the Peersec MatrixSSL and OpenSSL stacks.</td>
</tr>
</tbody>
</table>
<a id="httpServer"></a>
<h3>Appweb HTTP Server Core</h3>
<p>The core Appweb HTTP server is one of the relatively 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, filters and connectors to use when serving content to clients. The goal is to centralize any
facilities for the modules so it will not be replicated.</p>
<p>The core services include: the main HTTP processing and socket communications, initialization and
parsing the Appweb configuration file, server, virtual host and directory authorization management, request
pipeline management and request processing.</p>
<p>The core server also configures and enforces any sandbox resource limits that have been requested in the
configuration file, for example: thread limits and request URI and body 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 multi-threaded. With appropriate sandbox limits, it can serve
thousands of requests per second if required.</p>
<a id="configuration"></a>
<h2 class="section">Appweb Configuration</h2>
<p>Appweb uses an Apache style configuration file. This configuration file is read when Appweb starts and
it manages every aspect of Appweb's configuration including what ports and addresses to listen to, what
modules to load, where to find the web pages, and how to log requests.</p>
<p>The configuration file supports a wide variety of directives such as virtual hosting, directory
authentication, port binding, aliasing, logging, and request pipeline configuration. It has conditional
declarations and supports the inclusion of other configuration files. Appweb uses a one-pass traversal of the
configuration file which means that the order of directives matters.</p>
<a id="requests"></a>
<h2 class="section">Request Processing</h2><!--
- Header parsing
- Request Matching
- By extension
- By location block
- Pipeline construction
- Run pipeline
- Pipeline input
- Pipeline output
- Header generation
- Filters
- Chunking
- Keep alive
-->
<p>The Appweb HTTP core manages the processing of requests and the construction of the request processing
pipeline. When a new HTTP request arrives, Appweb 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. If name based virtual hosting is configured, 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 <a href="../../guide/appweb/users/vhosts.html">Virtual
Hosts</a> for more information.</p>
<h3>HTTP Header Parsing</h3>
<p>The first line of the HTTP request specifies the HTTP operation method to use, the URI to access and the
variant of the HTTP protocol to use. This typically looks like:</p>
<pre>
GET /index.html HTTP/1.1
</pre>
<p>This example is asking for the /index.html document via the GET method using the HTTP/1.1 protocol.</p>
<p>After the request line, follow a set of HTTP headers. Typically there are 5-15 headers which specify
further information to help the server process the request. Headers are of the format:</p>
<pre>
HeaderName: value
</pre>
<p>Some typical headers are:</p>
<table title="Headers">
<thead>
<tr>
<th>Header</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Authorization</td>
<td>Authorization details including user name, realm, password digest and other authorization
parameters to implement Basic and Digest authentication.</td>
</tr>
<tr>
<td>Connection</td>
<td>Describe how the TCP/IP connection should be managed when the request completes.</td>
</tr>
<tr>
<td>Content-Length</td>
<td>Length of any addition data with a POST request.</td>
</tr>
<tr>
<td>Content-Type</td>
<td>Mime types the client prefers to accept in response to this request.</td>
</tr>
<tr>
<td>Cookie</td>
<td>Cookie associated with the URI in the clients cookie cache.</td>
</tr>
<tr>
<td>Host</td>
<td>Name to the target host to serve the request. This specifies the host name when using virtual
hosting.</td>
</tr>
<tr>
<td>If-Modified-Since</td>
<td>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.</td>
</tr>
<tr>
<td>Keep-Alive</td>
<td>Request the server to keep the connection alive so that subsequent requests can reuse the
connection.</td>
</tr>
</tbody>
</table>
<p>For example:</p>
<pre>
Connection: keep-alive
</pre>
<p>Appweb parses the HTTP headers and stores their values in a hash table for access by the request
handlers and pipeline stages. When all the headers have been processed Appweb proceeds 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.</p>
<h3>Request Routing</h3>
<p>Appweb has a powerful request routing engine that processes client HTTP requests. The engine is
configured with a set of routes from the Appweb configuration file. When a request is received,
it tests various routes and selects
the best route to handle the request. In the process, routes may redirect or rewrite the request as required.</p>
<p>An Appweb configuration will typically have many routes. The configured routes are tested in order
by matching the route regular expression pattern against the request URI. A route may require that
further preconditions
be met before it is suitable to process the request. If the required conditions are not met, the next
route in the configuration will be tested. There is always a catch-all route that will process the
request if all prior routes fail to qualify.</p>
<p>To define a route, use the <a href=
"../../guide/appweb/users/dir/route.html">Route</a> directive. For example:</p>
<pre>
&lt;Route /projects/video&gt;
SetHandler videoHandler
&lt;/Route&gt;
</pre>
<p>This will cause the videoHandler to respond to any URI that begins with "/projects/video" after the
http://site portion of the URI.</p>
<p>To associate a handler to a given extension, use the <a href=
"../../guide/appweb/users/dir/route.html#addHandler">AddHandler</a> directive. For example:</p>
<pre>
AddHandler espHandler myDoc
</pre>
<p>This will cause the ejsHandler to respond to any URI that has a "<em>.myDoc</em>" extension.</p>
<p>Multiple routes may match a URI. In this case they are applied in the order they are specified in the
Appweb configuration file.
<p>Once the route has been selected, the request pipeline is constructed and the request handler is started
to create the response for the client.</p>
<a id="pipeline"></a>
<h2 class="section">Request Pipeline</h2>
<p>The Appweb core uses a bidirectional pipeline to process requests and generate responses. This consists
of a mechanism of queues, packets, buffering and event scheduling. The pipeline architecture is highly
optimized and supports the efficient transmission of data without copying. It uses vectored, scatter/gather
writes to the network to avoid the costly aggregation of data and headers in a single buffer before writing
to the network.</p>
<h3>Pipeline Stages</h3>
<p>The request pipeline is comprised of an incoming and outgoing stream. Each stream is in turn comprised
of <b>stages</b>. Each stage has a data queue with two service routines, one to accept data without queuing
and one for delayed servicing of previously queued data. Pipeline stages support flow-control and can queue
data for delayed servicing if the downstream stage cannot currently accept data.</p><img src=
"../../images/pipeline.jpg" alt="" />
<p>A typical pipeline consists of the following <b>stages</b>.</p>
<ul>
<li>One handler</li>
<li>Zero or more filters</li>
<li>One network connector</li>
</ul>
<h3>Http Core</h3>
<p>The Appweb HTTP core is responsible for parsing the incoming HTTP request. The HTTP request first line
specifies the request URI resource and the request headers provide additional context. The HTTP core stores
the parsed headers for use by the routing engine and creates a new request pipeline to process the request.
The incoming and outgoing pipelines are constructed separately as each direction may require a different set
of filters.</p>
<h3>Routing Engine</h3>
<p>The routing engine matches the request against the configured request routes and selects the best
route for the request. A route specifies the handler to manage the request and other context such as where
to find documents to serve. The routing engine may rewrite the request and then reroute. The engine
also manages HTTP authorization.</p>
<p>Depending on the request URI and headers, the appropriate handler will be selected. There are handlers
for ESP, PHP, CGI, Ejscript and static file data.</p>
<h3>Handlers</h3>
<p>The handler is responsible for receiving the request and creating a response. It generates response
content based on the HTTP request URI, headers, any associated body data, and potential application session
state. The output data flows through the output pipeline before transmission by the network connector to
the client.</p>
<p>There is one handler for each request. The Appweb core selects that handler based on a request matching
algorithm. Handlers are configured in the Appweb configure file via the <a href=
"../../guide/appweb/users/dir/route.html#addHandler">AddHandler</a> and the <a href=
"../../guide/appweb/users/dir/route.html#setHandler">SetHandler</a> directives.</p>
<h3>Filters</h3>
<p>The filters job is to permute the data in some way and pass it on to the next stage in the pipeline.
Filters connect one to another and multiple filters may be used in both the incoming and outgoing pipeline
directions.</p>
<p>The order of filters typically does matter. For example, compressing data before encrypting is not the
same as encrypting then compressing. Appweb provides the <a href=
"../../guide/appweb/users/dir/route.html#addInputFilter">AddInputFilter</a> and <a href=
"../../guide/appweb/users/dir/route.html#addOutputFilter">AddOutputFilter</a> directives to assist in
constructing filter pipelines.</p>
<p>Appweb uses filters to implement Transfer Authorization, Chunk Encoding and HTTP Ranged requests. By
using filters to implement these features, they automatically become available to all handlers and all
content types.</p>
<h3>Connectors</h3>
<p>The connector is responsible for transmitting the outgoing data to the client. It receives a set of
packets representing the data to send to the client. The connector is responsible for requesting the Appweb
HTTP core to create a packet with the HTTP response headers. It is at this stage that Appweb can determine
if the TCP/IP connection can be kept alive for subsequent requests on the same connection.</p>
<h4>Delayed Headers</h4>
<p>Connectors will receive an empty header packet which must first be filled with the HTTP response
headers. By delaying the generation of the HTTP headers until the last possible moment, Appweb maximizes
every opportunity to optimize the response and use the HTTP/1.1 Keep-Alive feature even for dynamically
generated data.</p>
<h4>Send Connector</h4>
<p>If the File handler is communicating directly to the Send connector, it will optimize its operation by
not reading the static file data. Rather, it will send empty packets to the Send connector which will use
the operating system <b>sendfile</b> (or equivalent) primitive. This avoids reading the static file data
into the Appweb user process.</p>
<h4>Net Connector</h4>
<p>The Net connector is a generalized network connector that can transmit content from any handler to the
client. It supports vectored writes to avoid copying data when interleaving with HTTP, range or chunk
headers.</p>
<a id="frameworks"></a>
<h2 class="section">Web Frameworks</h2>
<p>Appweb supports loadable modules for the ESP, Ejscript and PHP web frameworks.</p>
<h3>Embedded Server Pages Web Framework</h3>
<p>The ESP web framework is a high performance, Model/View/Controller web framework.
It uses the "C" language embedded in HTML web pages and for Controllers. It provides
an application generator, templating and layout engine, a Model/View/Controller framework, extensive caching,
and a library of Ajax view controls. It is blazing fast via the use of "C" and caching of
compiled web pages and rendered HTML.
<h3>Ejscript Web Framework</h3>
<p>The Ejscript Web Framework was designed to make it easier to create dynamic web applications. It uses
server-side JavaScript as the application language and provides provides an application generator,
templating engine, a powerful Model/View/Controller framework, and a library of Ajax view controls. See
the <a href="ejsArchitecture.html">Ejscript Web Framework</a> for more details.</p>
<h3>PHP</h3>
<p>PHP is a widely-used general-purpose scripting language that is especially suited for Web development
and can be embedded into HTML. Appweb provides a fast, in-memory handler for the PHP web framework.</p>
<a id="security"></a>
<h2 class="section">Security</h2>
<p>Appweb provides a suite of measures designed to increase the security of your web server:</p>
<ul>
<li>Secure Sockets Layer</li>
<li>Authorization directives</li>
<li>Sandbox directives</li>
<li>MPR &mdash; secure portable runtime</li>
<li>Manager monitoring process</li>
</ul>
<h4>Secure Sockets</h4>
<p>Appweb supports the OpenSSL and MatrixSSL SSL stacks. You can configure server and/or client
certificate-based authentication. SSL and TLS are supported.</p>
<h4>Authentication</h4>Appweb provides the Digest authentication mechanism and supports both file and
PAM-based authentication backends.
<h4>Sandboxing</h4>
<p>Sandboxing is the term applied to running Appweb in a confined environment. Appweb has a set of
configuration file directives that allow you to define a sandbox which limits the resources that Appweb may
used for a given request. By using well defined sandbox directives, you can help ensure that your
application and system will not be compromised by malicious requests.</p>
<a id="mpr"></a>
<h2 class="section">Multithreaded Portable Runtime (MPR)</h2>
<p>Appweb is built upon a portable runtime layer called the MPR. This layer insulates the rest of the
product from the underlying platform and allows it to be highly portable to new operating systems or
hardware.</p>
<p>The MPR provides a suite of services that facilitate the creation of high performance,
multi-threaded management and server applications, including: thread management, dynamic module loading,
networking, safe string handling, timers, XML parsing and logging.</p>
<p>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.</p>
<p>The MPR event processing mechanism can be easily integrated into existing applications. It supports
single and multi-threaded 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.</p>
<p>The MPR includes a high performance memory allocator and generational garbage collector.
The allocator is a fast, coalescing allocator that exhibits very low fragmentation. It is optimized
for frequent allocations of small blocks and uses a background collector for freeing unused memory.</p>
<p>The garbage collector is somewhat unusual in a C program. However, garbage collection is
especially well suited for long running applications like a web server as it virtually eliminates
memory leaks. Unlike traditional memory allocation where free must be called, Appweb 4 uses the
opposite approach where memory that must be retained, needs to be actively managed to prevent
garbage collection. This means that a managed reference must be held for all active memory.
See <a href="memory.html">Memory Allocation</a> for more details.</p>
<a id="misc"></a>
<h2 class="section">Misc Features</h2>
<h3>IP Networking</h3>
<p>Appweb fully supports both IPv4 and IPv6 for both server and client operations. You can configure Appweb
to listen on both IPv4 and IPv6 addresses.</p>
<h2 class="section">Embedding APIs</h2>
<p>The Appweb HTTP server library can be embedded in an application to web-enable that application.
Appweb provides two levels of embedding:</p>
<h3>One Line Embedding</h3>
<p>Appweb can be embedded in one C statement. This will create a web server instance based on the given
configuration file.:</p>
<pre>
maRunWebServer("appweb.conf");
</pre>
<h3>Expanded Control</h3>
<p>Appweb also provides a detailed API so you can create an embedded web server instance and control
virtual hosts, port binding, directory and location blocks and every other part of Appweb. See the <a href=
"../../api/appweb.html">Appweb Native API</a> for full details.</p>
</div>
</div>
<!-- BeginDsi "dsi/bottom.html" -->
<div class="bottom">
<p class="footnote">
<a href="../../product/copyright.html" >&copy; Embedthis Software LLC, 2003-2013.
All rights reserved. Embedthis, Appweb, ESP, Ejscript and Embedthis GoAhead are trademarks of Embedthis Software LLC.</a>
</p>
</div>
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
google.load('search', '1', {language : 'en'});
google.setOnLoadCallback(function() {
var customSearchControl = new google.search.CustomSearchControl(
'000262706376373952077:1hs0lhenihk');
customSearchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET);
var options = new google.search.DrawOptions();
options.enableSearchboxOnly("http://appwebserver.org/search.html");
customSearchControl.draw('cse-search-form', options);
}, true);
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-179169-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>