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.

mmc_initial

Right click on the sandbox virtual directory and configure its properties as shown below.

mmc_sandbox_properties

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.

mmc_sandbox_content

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.

iis8_add_virtual_directory

Select the Add Virtual Directory…​ menu item and fill the dialog that comes up as shown.

iis8_add_virtual_directory_entry

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.

iis8_sandbox

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.

iis8_sandbox_handler_mapping

Fill out the dialog as shown below ensuring all checkboxes are selected.

iis8_sandbox_handler_mapping_entry

On clicking OK in the above dialog, you should see ISAPI-dll enabled in the Handler Mappings pane for the sandbox virtual directory.

iis8_sandbox_handler_mapping_enabled

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.

iis8_isapi_restriction

Click the Add item in the Actions pane and fill the presented dialog as below.

iis8_isapi_restriction_entry

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:

When the SCGI server sees the end of the request it sends back a response and closes the connection. The format of the response is not specified by this protocol.

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.

Table 1. Configuration variables
Variable Description Default

IOCPQueueMax

Integer value corresponding to the maximum number of queued IOCP requests.

50

KeepStatistics

If non-0, the extension keeps certain statistics that can be useful in troubleshooting or tuning.

0

LogFile

Path to the log file.

isapi_scgi.log in the same directory as isapi_scgi.dll.

LogLevel

Verbosity of logging. 0 turns off, 1 logs only errors.

1

NonParsedHeaders

Whether non-parsed headers (NPH) are in use. 1 to turn on NPH, 0 to turn off.

0

NumThreads

Integer value corresponding to the number of worker threads to be run.

10

SCGIServerAddress

IP address of the SCGI server.

127.0.0.1

SCGIServerPort

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.

SCGIServerStopCommand

Command to execute stop the SCGI application server. See Starting the SCGI server automatically.

None.

StatisticsLogInterval

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.