A multithreaded, IOCP-based, ISAPI extension for the Simple Common Gateway Protocol.
The isapi_scgi
ISAPI extension for Microsoft IIS implements the Simple
Common Gateway Interface (SCGI). SCGI is a standard for communicating
with web servers on the back end. Requests received by IIS are passed
on to the application server over the SCGI protocol and the response
sent back to the client. Unlike CGI, where the web server will start
a new process for every request, SCGI involves a long-running process
(the SCGI server) which is handed off requests from the web server and
responds as per the protocol. It has the following benefits compared
to CGI:
-
It is an order of magnitude or more faster as it avoids all the startup costs associated with the latter, such as process creation, interpreter initialization, loading of application code and re-establishing database connections.
-
Because communication with the web server is on top of TCP, the application code can actually run on a different server if desired for performance or security reasons.
This guide describes isapi_scgi
installation and usage but assumes you know how to configure your SCGI
application server.
Features
isapi_scgi
has the following features:
-
Supports Microsoft IIS versions 6, 7 and 8.
-
Can optionally start the SCGI application server automatically
-
Ability to control parameters like number of threads, outstanding IOCP requests etc. for tuning to your particular environment.
-
Implemented as an ISAPI C extension and uses I/O completion ports for minimal memory and CPU usage
-
Supports non-parsed headers
-
No other dependencies. Even the C runtime is either not needed or is statically bound
-
Open source with a liberal BSD license that allows free use even in commercial environments.
Downloading isapi_scgi
The latest version of isapi_scgi
can be downloaded from the Files
section of the
Sourceforge
isapi_scgi
project.
Extract
the files into a temporary folder before following the instructions
for installation.
Installing isapi_scgi
The examples and description in this document refer to the extension
DLL as isapi_scgi.dll which is the name of the distributed 32-bit DLL.
The distributed 64-bit DLL is called isapi_scgi64.dll and when
installing on 64-bit systems, either rename it to isapi_scgi.dll or
use isapi_scgi64.dll in place of isapi_scgi.dll in all instructions
below. Note the configuration file name is always isapi_scgi.ini .
|
isapi_scgi
is installed like any other ISAPI extension. The sample
sessions below illustrate installation under IIS 6 on Windows XP and
IIS 8 on Windows 8. Installation for other IIS versions are very
similar.
We assume a simple configuration where the extension will be accessed
under /sandbox/isapi_scgi.dll/
. All requests to URLs below this will
be passed by the extension to the SCGI server. Obviously you may use
techniques such as URL rewriting to hide the use of the DLL but that
is not described here.
Installing for IIS 6
Start up the MMC IIS manager and create a new virtual directory, sandbox, under the default Web site as shown in the screenshot below.
Right click on the sandbox virtual directory and configure its properties as shown below.
We have mapped the sandbox virtual directory to a physical directory,
c:\scgi-example
, on the local system. The important thing to note in
the above configuration screen is that 'Execute Permissions' have been
set to 'Scripts and Executables'. This is required for ISAPI extensions
to be enabled for the virtual directory. Also, setting the 'Application
Protection' value to 'Low' instead of 'Medium' as above will give higher
performance.
Copy the isapi_scgi.dll
from the temporary directory where you
extracted the distribution into the physical directory,
c:\scgi-example
, in the above example. The IIS manager console will
look as follows after refreshing.
The extension is now installed.
Installing for IIS 8
We now illustrate installing isapi_scgi
for IIS 8, this time using
the 64-bit extension isapi_scgi64.dll
.
Start up the IIS manager and right-click on the Default Web Site
node to bring up the menu.
Select the Add Virtual Directory…
menu item and fill the dialog
that comes up as shown.
We have mapped the sandbox virtual directory to a physical directory,
c:\scgi-example
, on the local system.
Copy the isapi_scgi64.dll
to this physical directory.
Now select the newly created sandbox
virtual directory node and in the middle
plane double click the Handler Mappings
item.
This will bring up the handler settings for the sandbox
virtual directory
as shown below. Note that ISAPI is disabled and needs to be enabled. To
do this, select the ISAPI-dll
line and click the Edit Feature Permissions…
item in the Actions
pane.
Fill out the dialog as shown below ensuring all checkboxes are selected.
On clicking OK
in the above dialog, you should see ISAPI-dll
enabled
in the Handler Mappings
pane for the sandbox
virtual directory.
This is required for ISAPI extensions to be enabled for the virtual directory.
There is one final step needed. By default, IIS will not allow unknown
extensions to run so we need to add it to the system-wide list of
permitted ISAPI extensions. To do this, select the system node
in IIS Manager and double click the ISAPI and CGI Restriction
item
in the middle pane.
Click the Add
item in the Actions
pane and fill the presented dialog
as below.
Click OK to save the configuration.
The extension is now installed.
Final steps
If you are not running the default SCGI server address and port,
follow the steps described in the configuration section to set up
isapi_scgi
options.
Finally, stop and restart IIS and the default Web site. The isapi_scgi
extension will now be invoked whenever a request for a URL beginning
with /sandbox/isapi_scgi.dll
or /sandbox/isapi_scgi64.dll
is received
as appropriate.
Upgrading from earlier versions
Please note that beginning with Version 0.8, isapi_scgi
will parse
SCGI response headers by default. This differs from earlier releases
which only supported non-parsed headers operation. To keep the
earlier behaviour, the NonParsedHeaders
configuration option must be set to
a non-0 value. See SCGI response headers.
SCGI request headers
As recommended in the SCGI specification,
isapi_scgi
passes the following CGI headers to the SCGI server as part
of the request:
AUTH_TYPE
, CONTENT_LENGTH
, CONTENT_TYPE
, GATEWAY_INTERFACE
,
PATH_INFO
, PATH_TRANSLATED
, QUERY_STRING
, REMOTE_ADDR
,
REMOTE_HOST
, REMOTE_USER
, REQUEST_METHOD
, SCRIPT_NAME
,
SERVER_NAME
, SERVER_PORT
, SERVER_PORT_SECURE
,
SERVER_PROTOCOL
and SERVER_SOFTWARE
.
In addition, it passes the following protocol specific headers
if they were present in the client request:
HTTP_CONNECTION
, HTTP_ACCEPT
, HTTP_ACCEPT_ENCODING
,
HTTP_ACCEPT_LANGUAGE
, HTTP_COOKIE
, HTTP_HOST
, HTTP_REFERER
,
HTTP_USER_AGENT
, HTTP_UA_CPU
and HTTPS
.
Please refer to RFC3875 for the meaning of the above headers.
If any URL rewriters generate the HTTP_X_ORIGINAL_URL
header,
it is passed as well.
In the case where the request is over an HTTPS connection, the following
additional headers are added:
HTTPS_KEYSIZE
, HTTPS_SECRETKEYSIZE
, HTTPS_SERVER_ISSUER
and
HTTPS_SERVER_SUBJECT
,
CERT_COOKIE
, CERT_FLAGS
, CERT_ISSUER
, CERT_KEYSIZE
,
CERT_SECRETKEYSIZE
, CERT_SERIALNUMBER
, CERT_SERVER_ISSUER
,
CERT_SERVER_SUBJECT
and CERT_SUBJECT
.
Please refer to the IIS documentation for the meaning of the above headers.
Handling custom headers
For the SCGI server to be passed any additional or custom headers,
they have to be explicitly configured in the isapi_scgi.ini
configuration file. These may be specific to IIS such as
APPL_MD_PATH
, APPL_PHYSICAL_PATH
, AUTH_PASSWORD
,
AUTH_USER
, INSTANCE_ID
, INSTANCE_META_PATH
, LOCAL_ADDR
,
LOGON_USER
, SERVER_PORT_SECURE
and URL
. They may also
be based on custom HTTP headers sent from the client or generated
by other extensions or filters such as URL rewriters.
To have these headers passed by isapi_scgi
they must be added as
keys to the SCGI_HEADER_EXTENSIONS
section of the isapi_scgi.ini
configuration file. In the case of custom HTTP headers, the
key is formed by prefixing the actual header name with HTTP_
and
replacing any -
characters in the name with _
. An example section
is shown below:
[SCGI_HEADER_EXTENSIONS]
INSTANCE_ID= (1)
HTTP_X_REWRITE_URL= (2)
HTTP_X_CUSTOM_HEADER= (3)
1 | Passes the IIS-specific header containing the IIS instance id |
2 | Passes the header generated by an installed URL rewriting filter |
3 | Passes the X-Custom-Header non-standard header sent by the client |
Note that the value assigned to the keys is currently immaterial but should be left empty.
SCGI response headers
The SCGI specification states:
Two formats for the response are supported by isapi_scgi
corresponding
to the equivalent CGI specification defined by
RFC3875.
In the normal CGI case, the SCGI server sends a response header
separated from the body by a blank line. The header may contain
a 'Status:' line indicating the HTTP status. If absent, a status
of "200 Ok" is assumed. The isapi_scgi
extension will then generate
HTTP headers based on the SCGI response headers.
The non-parsed header (NPH) case is enabled when the
NonParsedHeaders
configuration setting is set to a non-0 value.
In this case, isapi_scgi
passes all bytes sent from the SCGI
server back to the client with no modification at all.
The SCGI server is responsible for the entire content passed back
to the client.
See RFC3875 for more details about these behaviours.
Configuring isapi_scgi
isapi_scgi
is configured through the isapi_scgi.ini
file which
must be located in the same directory as the isapi_scgi.dll
extension. This file is in the standard Windows INI file format and
may contain the variables described below. These must be defined in
the [SCGI]
section of the file.
Note that the file is only needed if the defaults described below do not match your desired configuration.
Variable | Description | Default |
---|---|---|
|
Integer value corresponding to the maximum number of queued IOCP requests. |
50 |
|
If non-0, the extension keeps certain statistics that can be useful in troubleshooting or tuning. |
0 |
|
Path to the log file. |
|
|
Verbosity of logging. 0 turns off, 1 logs only errors. |
1 |
|
Whether non-parsed headers (NPH) are in use. 1 to turn on NPH, 0 to turn off. |
0 |
|
Integer value corresponding to the number of worker threads to be run. |
10 |
|
IP address of the SCGI server. |
127.0.0.1 |
|
Port the SCGI server is listening on. |
9999 |
SCGIServerStartCommand |
Command to execute to start the SCGI application server. See Starting SCGI servers automatically. |
None. No server is started by default. |
|
Command to execute stop the SCGI application server. See Starting the SCGI server automatically. |
None. |
|
Controls how often statistics are written to the log file. The interval is given in seconds. |
60 |
The optimal values for NumThreads
and IOCPQueueMax
depend on the
system (memory, number of processors and their speed, etc.) and
configuration (for example, whether the SCGI server on a different
system). On heavily loaded systems, you should determine these values
empirically through load testing.
Starting SCGI servers automatically
You may choose to start your SCGI server automatically and
independently of IIS. Alternatively, you can configure isapi_scgi
to
start the server automatically when the first request is received and
to shut it down when IIS unloads the extension (for example, when IIS
is shut down).
To have isapi_scgi
automatically start the SCGI server, set the
configuration variable SCGIServerStartCommand
. The value must be the
full command including a full path and arguments, if any. isapi_scgi
will execute this command without any validation or error
checking. Similarly, to have isapi_scgi
automatically shut down the
SCGI server, set the configuration variable SCGIServerStopCommand
. For
example, if your SCGI server runs as the Windows service myscgiapp
,
you might have the following two lines in the isapi_scgi
configuration
file:
[SCGI] SCGIServerStartCommand= net start myscgiapp SCGIServerStopCommand= net stop myscgiapp
Logging in isapi_scgi
By default, isapi_scgi
will log to the file isapi_scgi.log
in the same
directory where isapi_scgi.dll
is located. This can be changed by
setting the LogFile
variable in the configuration.
The messages logged can be controlled by setting the LogLevel
. By
default, only errors are logged (LogLevel=1
). Setting its value to 0
will turn off all logging and setting it to 2
will log informational
messages as well as errors, including connection requests.
Support and source code
Support for isapi_scgi
can be obtained through the
Tickets
section of the
SourceForge
isapi_scgi
project.
The source code for isapi_scgi
is also available through
Sourceforge
and is covered by a BSD license that allows free use for any
purpose.