The iiswsgi
module implements a FastCGI to WSGI
gateway that
is compatible with IIS
's variation of the FastCGI protocol
. It also
provides distutils
commands for building, distributing and installing
Microsoft Web Deploy
(MSDeploy) packages through the Web Platform Installer
_ (WebPI).
.. contents::
The iiswsgi
distribution includes two sample IIS apps which can be
installed through WebPI once the custom feed has been added:
Web Platform Installer
_Web Matrix
Web Matrix
entry, thenInstall
in the lower-right and follow the instructions
Options
dialog by clicking the link on the lower-rightCustom Feeds
, add the URL for latest *.webpi.xml
filefrom the iiswsgi downloads
_ and click Add feed
Which Web Server...?
, check IIS Express
and then clickOK
pyramid
Pyramid Application
then Install
in thelower-right and follow the instructions
Assuming an existing Python
distribution with a Setup Script
using
setuptools
and a WSGI
*.ini
Paste config file
_, roughly
the following steps could be used to released to WebPI:
iiswsgi
_ into the Python environment used to build releases::C:\Python27\Scripts\easy_install.exe -U iiswsgi
examples/pyramid.msdeploy/Manifest.xml.in
examples/pyramid.msdeploy/Parameters.xml
examples/pyramid.msdeploy/iis_install.stamp.in
examples/pyramid.msdeploy/web.config.in
setup.py
::...
from iiswsgi import install_msdeploy
...
class install_custom_msdeploy(install_msdeploy.install_msdeploy):
def run(self):
"""Perform custom tasks."""
os.environ['WEB_CONFIG_VAR'] = 'foo'
self.pre_install()
CUSTOM_SETUP
self.post_install()
...
setup(
...
cmdclass=dict(install_msdeploy=install_custom_msdeploy),
...
>C:\Python27\python.exe setup.py bdist_msdeploy
setup.py
::...
setup(
...
extras_require=dict(install_msdeploy=['virtualenv'],
webpi_eggs=['virtualenv', 'iiswsgi']),
...
setup.py
:See examples/pyramid.msdeploy/setup.py
for an example.
Web Platform Installer
_:Install fciv.exe
_ to generate SHA1 hashes:Must be placed on the %PATH%
. The recommended place would be
%ProgramFiles%\Microsoft\Web Platform Installer
because it's
placed on the path when WebPI is installed.
WebPI feed
_::>C:\Python27\python.exe setup.py bdist_webpi -u "{msdeploy_package_url}" -m .
options
link to the bottom right,Add Feed
: ``file:///C:/Users/%USERNAME%/Documents/GitHub/%DIST_NAME%/dist/%DIST_NAME%-%VERSION%-py2.7-win32.webpi.xml``
OK
and wait for WebPI to parse the feed>C:\Python27\python.exe setup.py bdist_msdeploy bdist_webpi -m . upload
If everything is working correctly, both a MSDeploy zip package and
the WebPI feed should be uploaded to PyPI
_. Then you can instruct
users to add the feed to WebPI and they can install your package.
Releasing a WSGI app on IIS involves several steps and moving pieces.
See the Web Deploy Package Contents
and IIS WSGI Tools
sections
for more technical details. Here is an overview of the process and
the technologies involved.
This is a pre-requisite and is not at all specific to IIS, MSDeploy or
WebPI, only Python. This is just a directory with a setup.py
Setup Script
that defines the distribution and it's metadata and
very little is done differently from the standard Python distutils
and setuptools
ways of doing things. IOW, wherever possible,
iiswsgi
tries to re-use setup.py
metadata and where it needs new
metadata it uses setuptools
entry points
to add setup kwargs
.
If the app requires extra set up beyond just setting up a
virtualenv
_ and installing dependencies, this can also be
implemented in setup.py
by subclassing the install_msdeploy
Install MSDeploy
command. See the Quick Start
and the Install MSDeploy
_ command for more details.
Microsoft's Web Deploy Tool is what WebPI uses to install an IIS app
and expects a MSDeploy package
, simple zip file with some metadata
in it. There some special files
and three iiswsgi
distutils
_
commands that help in defining and building a MSDeploy package. The
commands can also be run indiviually or run all at once by running
just the last step which will run the others first. Running them
individually is useful to debug packaging problems.
#. `Build MSDeploy Package`_ ``build_msdeploy`` command
#. `Install MSDeploy`_ ``install_msdeploy`` command
#. `Test MSDeploy`_ ``test_msdeploy`` command
#. `Build MSDeploy Distribution`_ ``bdist_msdeploy`` command
On completion of the last command a MSDeploy zip file will be in the
dist
directory just like any other dist command, such as
sdist
. You can also upload the package using the upload
command.
Logging output or managing verbosity for building the package is no
different than for any other disutils/setup.py uses, output is on the
console and can be redirected if you wan to capture it. See
>C:\Python27\python.exe setup.py --help
for more details.
The Web Platform installer can be given additional feeds in it's
options dialog. This feed can define things that can be installed
along with their metadata including dependencies. The bdist_webpi
_
command can build this feed as another dist file, and can thus also be
released using the upload
command.
To test locally, use the bdist_webpi -u "{msdeploy_package_url}"
option to put file:///...
download URLs for the MSDeploy packages
in the feed. Then use the file:///...
URL for the feed
itself in WebPI's options dialog that is printed to the console when
the bdist_webpi
command is run.
WebPI logs information while processing the feed in the
%LOCALAPPDATA%\Microsoft/Web Platform Installer/logs/webpi
diretory. When debugging feed issues just look at the most recently
modified webpi#.txt
file in that directory.
Once the feed is included in WebPI, the entries can be searched for
and installed. After installation, but before WebPI reports
completion, any runCommand
providers in the MSDeploy Manifest
_ are
run which is when iiswsgi_install.exe
_ script is invoked to find the
installed app and to run distutils setup commands, install_msdeploy
_
and test_msdeploy
_ by default, in that distribution. Most apps will
want to use the iiswsgi_install.exe -e
option to setup a
virtualenv before running setup commands. See MSDeploy Manifest
_
and install_msdeploy
_ for more details and considerations.
While installing, WebPI and MSDeploy log output into
%LOCALAPPDATA%\Microsoft/Web Platform Installer/logs/install
.
When debugging installation issues just look at the App Title.txt
file in the most recently modified date-stamped direstory within that
directory. Verbosity can be controlled by adding the
iiswsgi_install.exe -v
option in your Manifest.xml
_
<runCommand path=...
attribute. It's also often valuable to run
the install_msdeploy
command locally in the installed app after an
installation error to debug further.
If installation has completed, there will be a
<fastCgi><application...
in the global IIS config, a corresponding
handler in the app's web.config
and when a request comes in for
the app, IIS will invoke the handler specified. For iiswsgi
, the
handler will be an paster serve
invocation that uses the
egg:iiswsgi#iis
FCGI server. To use a general purpose PasteDeploy INI configuration file
, you can use a handler like paster.exe serve -s "egg:iiswsgi#iis" ...
to use the iiswsgi
FCGI server with
a configuration file that doesn't specify it.
IIS swallows all FCGI process output if there are any errors starting
up which can make startup issues really hard to debug. The first step
should be manually invoking the FCGI process using the fullPath
and arguments
attributes from the <application...
element in
web.config
. In case that doesn't reproduce the error, the
egg:iiswsgi#iis
_ FCGI server tries to be conservative during startup
to ensure that output is logged somewhere. Check the following
locations for output:
* ``%IIS_USER_HOME%\Logs\%IISEXPRESS_SITENAME%\iiswsgi.log``
* ``%IIS_USER_HOME%\Logs\iiswsgi.log``
* ``%TEMP%\iiswsgi.log``
* ``\iiswsgi.log``
Verbosity is controlled by giving the paster serve -v...
option to
PasteScript
in the web.config.in
template.
A developer releasing a MSDeploy package of a Python web app,
interacts with iiswsgi
_ though the following files in a Python
distribution. Aside from these files, a Web Deploy package using
iiswsgi
is no different than any other Python distribution or
project nor should any of the iiswsgi
pieces interfere with any
other uses of the same distribution. In particular, it should be
possible to build and upload MSDeploy package and WebPI feed dists in
the same command as building and uploading any other dist.
As with other Python build, distribute, and install tasks, the
setup.py
script is where to control how the MSDeploy package is
built, what is distributed, and how it's installed.
Use Python's source distribution MANIFEST.in
template format to
declare what will be in the package. Distributions installing into a
virtualenv
with a lot of dependencies may want to include the eggs
in the virtualenv's site-packages
in the MSDeploy package such
that the one download will included all the needed eggs greatly
reducing network activity and install time::
recursive-include lib/site-packages *
recursive-include Lib\site-packages *
global-exclude *.pyc *.pyo
Use the Manifest.xml.in
template to generate the Web Deploy manifest
. When using iiswsgi
, it contains a runCommand
_
provider that invokes the iswsgi_install.exe
MSDeploy Install Bootstrap
script. Most packages will want to install into a
virtualenv
by including a -e
option to iiswsgi_install.exe
.
The build_msdeploy
command can be used to write runCommand option attributes
into the hash that MSDeploy uses when processing the
manifest during installation. Most apps will want to include the
successReturnCodes="0x0"
attribute to ensure that failures in the
command are reported back to the user. Many apps will also want to
adjust the waitAttempts="5"
and/or waitInterval="1000"
attributes to give the commands enough time to complete.
The Parameters.xml
_ file defines the parameters WebPI will prompt
the user for when installing. See
examples/pyramid.msdeploy/Parameters.xml
for an example of using
parameters to influence custom setup.
Use the web.config.in
template to generate the IIS site configuration file
. When using iiswsgi
, it contains a fastCgi
application that invokes the egg:iiswsgi#iis
iiswsgi FCGI Gateway
. Most packages will want to adjust the <application...
_
attributes that control process behavior. This is also where the
*.ini
config file or app_factory entry point
_ that define the
WSGI app to run are specified.
The iis_install.stamp.in
template copied into place to serve as
the iis_install.stamp
stamp file used by the
iiswsgi_install.exe
MSDeploy Install Bootstrap
_ script to find
the right APPL_PHYSICAL_PATH
at install time.
The setup.cfg
file is only necessary if your Setup Script
is not
using setuptools
. IOW, under setuptools
the commands are
automatically available is iiswsgi
is installed and there's no
need for this file. Without setuptools
, use the following to make
the iiswsgi
distutils commands available to your package::
[global]
command_packages = iiswsgi
The moving parts of iiswsgi
are as follows:
The egg:iiswsgi#iis
paste.server_runner
_ or
paste.server_factory
is the FastCGI to WSGI gateway. IIS invokes
the paster
script from PasteScript
with a PasteDeploy INI configuration file
to start a Python WSGI app as a FastCGI process.
Tell paster
to use the IIS FCGI gateway with paster.exe serve -s "egg:iiswsgi#iis" ...
or in the PasteDeploy INI configuration file
_::
[server:iis]
use = egg:iiswsgi#iis
This is not intrinsically related to the distutils
_ commands and can
be used independently of them if a project should need to.
IIS' implementation of the FastCGI protocol is not fully compliant.
Most significantly, what is passed in on STDIN_FILENO
is not a
handle to an open socket but rather to a Windows named pipe
. This
names pipe does not support socket-like behavior, at least under
Python. As such, the egg:iiswsgi#iis
gateway extends flup's WSGI to FCGI gateway
_ to support using STDIN_FILENO
opened twice, once
each approximating the recv
and send
end of a socket as is
specified in FastCGI.
The build_msdeploy
distutils command compiles a MSDeploy
Manifest.xml
converting any runCommand
attributes into the
necessary hash. It will also copy into place the IIS Install Stamp File
iis_install.stamp
stamp file used by the MSDeploy Install Bootstrap
_ iiswsgi_install.exe
script to find the right
APPL_PHYSICAL_PATH
at install time.
The install_msdeploy
distutils command performs common actions
needed to deploy Python web apps on IIS: install dependencies, do
variable substitution in web.config
_, and install the FastCGI
application into the IIS global config.
Since most apps will require path or parameter specific bits in the
web.config
file, the install_msdeploy
command will perform
variable substitution while writing the web.config.in
template to
web.config
. To add variables to the substitution, just use
Custom Set Up
to put them into os.environ
_ before calling the
base class's run()
method.
Since <fastCgi><application...
elements don't take effect in the
web.config
, the install_msdeploy
_ command will use. For
reference or debugging here's an example::
> appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='%SystemDrive%\Python27\python.exe',arguments='-u %SystemDrive%\Python27\Scripts\iiswsgi-script.py -c %HOMEDRIVE%%HOMEPATH%\Documents\My Web Sites\FooApp\test.ini',maxInstances='%NUMBER_OF_PROCESSORS%',monitorChangesTo='C:\Users\Administrator\Documents\My Web Sites\FooApp\test.ini']" /commit:apphost
See the IIS FastCGI Reference
_ for
more details on how to configure IIS for FastCGI. Note that you
cannot use environment variable in the monitorChangesTo
argument,
IIS will return an opaque 500 error.
This is also where to Custom Set Up
_ by subclassing the
install_msdeploy
Install MSDeploy
command in the setup.py
Setup Script
and using the distutils cmdclass
kwarg to
setup()
. See Quick Start
for a small example or
examples\pyramid.msdeploy\setup.py
for a working example.
The test_msdeploy
distutils command uses paster request
with a
PasteDeploy INI configuration file
to simulate sending a request to
the app. If it fails, the command fails, making this useful to run
during MSDeploy Package Installation
_ to ensure the user sees an
error in WebPI if the app isn't working even though the rest of the
install succeeded. See >C:\Python27\python.exe setup.py test_msdeploy --help
for more details.
The bdist_msdeploy
distutils command assembles an actual MSDeploy
package: It starts by running the build_msdeploy
Build MSDeploy Package
_ command. Then it runs the install_msdeploy
Install MSDeploy
command in case your package needs any of the results of
the installation process and to test the installation process.
Finally, it creates a MSDeploy package
zip file with the contents
contolled by the same tools that distutils
_ provides for sdist
distributions, including MANIFEST.in
.
The iiswsgi_install.exe
script bootstraps the MSDeploy package
install process optionally setting up a virtualenv first. It finds
the correct APPL_PHYSICAL_PATH
, changes to that directory and
invokes the Setup Script
_ with arguments.
This console script attempts to workaround the fact that WebPI and
MSDeploy don't provide any context to the app being installed.
Specifically, when using the runCommand
MSDeploy provider in the
Manifest.xml
, the process started by runCommand
has no way to
know which app it's being invoked for on install: not the current
working directory, not in an argument, nor in any environment
variable.
As such this script has to search for the app before calling it's
Setup Script
. It uses appcmd.exe
to look in virtual directories
whose site matches the app name and which contain a stamp file still
in place. See >Scripts\iiswsgi_install.exe --help
for more
details.
The bdist_webpi
distutils command assembles a WebPI feed from one
or more MSDeploy packages with dependencies. The MSDeploy packages to
include are defined by passing paths to distrubutions with
setup.py
files whose MSDeploy dist zip files have previously been
built in the --msdeploy-bdists
command option separated by
shlex.split
_. The download URLs for the MSDeploy zip files is
determined by expanding the msdeploy_url_template
setup()
kwarg with Python string.format()
_.
The global feed metadata is taken from the distribution the command is
being run for. Entries are added to the feed for the distributions
lited in the --msdeploy-bdists
command option and the
webpi_eggs
depdencies in extras_require
_. The WebPI dependencies
and related products are taken from the lists given in the
install_msdeploy
and install_webpi
setup()
kwargs
respectivels. The metadata for those entries is taken from the
corresponding distributions. The following are additional setup()
kwargs that are used in the feed if defined for a given distrubution:
* title
* author_url
* license_url
* display_url
* help_url
* published
* icon_url
* screenshot_url
* discovery_file
The clean_webpi
distutils command clears the WebPI caches
_ for
one or more MSDeploy package downloads and the feed itself. The
MSDeploy packages to be cleared from the cache are taken from the same
--msdeploy-bdists
command option.
One of the more important goals of iiswsgi
_ is to bring some greater
transparency and introspection to the process of integrating with
IIS. It's a very common experience for developers in the
non-Window/UNIX world that developing and even deploying on Windows is
much more fragile and opaque than on any other OS. Here's some of
what iiswsgi
does to try and address that.
Graceful Degredation on non-Windows
Fist and foremost, iiswsgi
tries to degrade gracefully when run
on non-windows platforms. Specifically, when some executable,
environment variable, or other Windows specific piece of the
environment is missing, the iiswsgi
operation will not raise an
exception but only log an error. This allows developing and, to a
limited extent, testing MSDeploy packages on NIX platforms. A
side-effect of this is that some errors may be missed when there
is a lot of console output from one of the distutils
_ commands
when running on Windows*, so check your output carefully.
Logging
Finding information about what went wrong when some part of the
process fails can be a lot more difficult on Windows than it is on
other platforms. See the sections of How it Works
_ for where to
look for log files for each part of the process.
Moved to GitHub issues
. In particular, please see if you can help
. If you're running into an issue that isn't described in one
of the open GitHub issues
, try looking through the closed issues
.
.. special files
: Web Deploy Package Contents
.. _bdist_webpi
: Build WebPI Feed Distribution
.. iiswsgi_install.exe
: MSDeploy Install Bootstrap
.. install_msdeploy
: Install MSDeploy
.. test_msdeploy
: Test MSDeploy
.. egg:iiswsgi#iis
: iiswsgi FCGI Gateway
.. build_msdeploy
: Build MSDeploy Package
.. web.config.in
: IIS Web Config
_
.. iiswsgi downloads
: https://github.com/rpatterson/iiswsgi/downloads
.. GitHub issues
: https://github.com/rpatterson/iiswsgi/issues
.. you can help
: https://github.com/rpatterson/iiswsgi/issues?labels=help+wanted&page=1&state=open
.. closed issues
: https://github.com/rpatterson/iiswsgi/issues?state=closed&page=1
.. Python
: http://python.org
.. os.environ
: http://docs.python.org/2/library/os.html#os.environ
.. shlex.split
: http://docs.python.org/2/library/shlex.html#shlex.split
.. distutils
: http://docs.python.org/distutils/
.. setup.cfg
: http://docs.python.org/distutils/configfile.html
.. cmdclass
: http://docs.python.org/distutils/extending.html#integrating-new-commands
.. Python string.format()
: http://docs.python.org/2/library/string.html#formatstrings
.. PyPI
: http://pypi.python.org/pypi
.. setuptools
: http://packages.python.org/distribute
.. entry points
: http://packages.python.org/distribute/setuptools.html#entry-points
.. setup kwargs
: http://packages.python.org/distribute/setuptools.html#adding-setup-arguments
.. extras_require
: http://packages.python.org/distribute/setuptools.html#declaring-extras-optional-features-with-their-own-dependencies
.. MANIFEST.in
: http://docs.python.org/distutils/sourcedist.html#the-manifest-in-template
.. WSGI
: http://wsgi.readthedocs.org/en/latest/
.. Paste config file
: http://pythonpaste.org/deploy/#config-format
.. PasteDeploy INI configuration file
: http://pythonpaste.org/deploy/index.html?highlight=loadapp#introduction
.. PasteScript
: http://pythonpaste.org/script/#paster-serve
.. paster
: PasteScript
.. paster serve
: PasteScript
.. paster request
: http://pythonpaste.org/modules/request.html
.. _app_factory entry point
: http://pythonpaste.org/deploy/#paste-app-factory
.. _paste.server_runner
: http://pythonpaste.org/deploy/#paste-server-runner
.. _paste.server_factory
: http://pythonpaste.org/deploy/#paste-server-factory
.. flup's WSGI to FCGI gateway
: http://trac.saddi.com/flup/wiki/FlupServers
.. virtualenv
: http://www.virtualenv.org
.. IIS
: http://www.iis.net
.. Microsoft Web Deploy
: http://www.iis.net/downloads/microsoft/web-deploy
.. Web Platform Installer
: http://www.microsoft.com/web/downloads/platform.aspx
.. WebPI feed
: http://technet.microsoft.com/en-us/library/ee424348(v=ws.10).aspx
.. WebPI caches
: http://www.iis.net/learn/troubleshoot/web-platform-installer-issues/troubleshooting-problems-with-microsoft-web-platform-installer
.. Install fciv.exe
: http://support.microsoft.com/kb/841290
.. Web Deploy manifest
: http://www.iis.net/learn/develop/windows-web-application-gallery/reference-for-the-web-application-package
.. Manifest.xml
: Web Deploy manifest
.. Parameters.xml
: Web Deploy manifest
.. MSDeploy package
: Web Deploy manifest
.. runCommand
: http://technet.microsoft.com/en-us/library/ee619740(v=ws.10).aspx
.. runcommand option attributes
: runCommand
.. IIS site configuration file
: http://technet.microsoft.com/en-us/library/cc754617(v=ws.10).aspx
.. web.config
: IIS site configuration file
.. fastCgi
: http://www.iis.net/configreference/system.webserver/fastcgi
.. _<application...
: http://www.iis.net/configreference/system.webserver/fastcgi/application
.. AppCmd.exe
: http://learn.iis.net/page.aspx/114/getting-started-with-appcmdexe
.. IIS FastCGI Reference
: http://www.iis.net/ConfigReference/system.webServer/fastCgi
.. FastCGI protocol
: http://www.fastcgi.com/drupal/
.. STDIN_FILENO
: http://www.fastcgi.com/drupal/node/6?q=node/22#S2.2
.. _Windows named pipe
: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365590(v=vs.85).aspx