Skip to content
100644 115 lines (92 sloc) 6.7 KB
0e97f81 @aaronsw Oops, needed three dashes instead of two.
aaronsw authored May 23, 2011
1 ---
4c9310e @ayaz Added guide to deploy on IIS7 and IIS6 using PyISAPIe.
ayaz authored May 21, 2011
2 layout: default
3 title: Deploying on IIS7 vai PyISAPIe
0e97f81 @aaronsw Oops, needed three dashes instead of two.
aaronsw authored May 23, 2011
4 ---
4c9310e @ayaz Added guide to deploy on IIS7 and IIS6 using PyISAPIe.
ayaz authored May 21, 2011
6 # Deploying on IIS7 via PyISAPIe
8 This guide is an account of the various steps, including snippets of relevant code that tweaked and added, in order to get a `` script to work on IIS7 using `PyISAPIe`. Please note that you must have Python as well as the [PyWin32 extensions][0] installed on Windows. _This guide was tested on two different 64-bit versions of Windows server with 32-bit versions of Python 2.6.6 installed and on IIS7 and IIS6_.
10 First and foremost, I had to install the `` module on the system. Having had trouble before with IIS with `` installed through `easy_install`, I decided to be safe and installed it from source. Getting `` to work with PyISAPIe required a small hack. In the file `Lib\site-packages\web\` lies the following function:
12 def _is_dev_mode():
13 # quick hack to check if the program is running in dev mode.
14 if os.environ.has_key('SERVER_SOFTWARE') \
15 or os.environ.has_key('PHP_FCGI_CHILDREN') \
16 or 'fcgi' in sys.argv or 'fastcgi' in sys.argv \
17 or 'mod_wsgi' in sys.argv:
18 return False
19 return True
21 In its pristine state, when `` is imported from a source file through PyISAPIe, an exception is thrown. The exception, while I don't have the exact message, is about it complaining about `sys.argv` not having an attribute `argv`, which reads fishy. Since the function `_is_dev_mode()` only checks whether `` is being run in development mode, I thought I didn't care about it since I wanted everything to run in production mode. I edited the function such that its body would be bypassed, while it returned a `False` boolean value. It looked like this:
23 def _is_dev_mode():
24 return False
25 # quick hack to check if the program is running in dev mode.
26 if os.environ.has_key('SERVER_SOFTWARE') \
27 or os.environ.has_key('PHP_FCGI_CHILDREN') \
28 or 'fcgi' in sys.argv or 'fastcgi' in sys.argv \
29 or 'mod_wsgi' in sys.argv:
30 return False
31 return True
33 This innocuous little addition did away with the exception.
35 Next up, I used default Hello World-esque example of ``. I called it `` (I placed it inside the folder `C:\websites\myproject`). It looked like this:
37 import web
38 urls = (
39 '/.*', 'hello',
40 )
41 class hello:
42 def GET(self):
43 return "Hello, world."
44 application = web.application(urls, globals()).wsgifunc()
46 It was pretty simple. You have to pay particular attention on the call to `web.application`. I called the `wsgifunc()` to return a WSGI-compatible function to boot the application.
48 I set up a website under IIS using the IIS Management Console. Since I was working on a 64-bit server edition of Windows and had chosen to use 32-bit version of Python and all modules, I made sure to enable **32-bit support** for the application pool being used for the website. This was important.
50 I decided to keep the PyISAPIe folder inside the folder where `` rested. This PyISAPIe folder contained the `PyISAPIe.dll` file, and the `Http` folder. Inside the `Http` folder, I placed the most important file of all: the ``. That file could be thought of as the starting point for each request that is made, what glues the Request to the proper Handler and code. I worked with the `Examples\WSGI\` available as part of PyISAPIe. I tweaked the file to look like this:
53 from Http.WSGI import RunWSGI
54 from Http import Env
55 #from md5 import md5
56 from hashlib import md5
57 import imp
58 import os
59 import sys
60 sys.path.append(r"C:\websites\myproject")
61 from code import application
62 ScriptHandlers = {
63 "/api/": application,
64 }
65 def RunScript(Path):
66 global ScriptHandlers
67 try:
68 # attempt to call an already-loaded request function.
69 return ScriptHandlers[Path]()
70 except KeyError:
71 # uses the script path's md5 hash to ensure a unique
72 # name - not the best way to do it, but it keeps
73 # undesired characters out of the name that will
74 # mess up the loading.
75 Name = '__'+md5(Path).hexdigest().upper()
76 ScriptHandlers[Path] = \
77 imp.load_source(Name, Env.SCRIPT_TRANSLATED).Request
78 return ScriptHandlers[Path]()
79 # URL prefixes to map to the roots of each application.
80 Apps = {
81 "/api/" : lambda P: RunWSGI(application),
82 }
83 # The main request handler.
84 def Request():
85 # Might be better to do some caching here?
86 Name = Env.SCRIPT_NAME
87 # Apps might be better off as a tuple-of-tuples,
88 # but for the sake of representation I leave it
89 # as a dict.
90 for App, Handler in Apps.items():
91 if Name.startswith(App):
92 return Handler(Name)
93 # Cause 500 error: there should be a 404 handler, eh?
94 raise Exception, "Handler not found."
96 The important bits to note in the above code are the following:
98 * I import `application` from my `code` module. I set the PATH to include the directory in which the file `` is so that the `import` statement does not complain. (I've to admit that the idea of import `application` and feeding it into `RunWSGI` came to while I was in the loo.)
99 * I defined a script handler which matches the URL prefix I want to associate with my `` script. (_In hindsight, this isn't necessary, as the `RunScript()` is not being used in this example_).
100 * In the `Apps` dictionary, I again route the URL prefix to the `lambda` function which actually calls the `RunWSGI` function and feeds it `application`.
101 * I also imported the `md5` function from the `hashlib` module instead of the `md5` module as originally defined in the file. This was because Python complained about `md5` module being deprecated and suggested instead of use `hashlib`.
103 I then defined a wild-card (Script map) extension in IIS for the website, mapping all requests to the `PyISAPIe.dll` file in _my project folder_. Which `PyISAPIe.dll` file is used is important. By default, it will look for the `Http` folder in the same directory where the DLL is. I restarted IIS (and possibly even Windows, just to be sure).
105 And that's pretty much it.
107 There's a caveat though. If you have specific URLs in your `` script, you will have to modify each of those URLs to add the `/api/` prefix to them (or whatever URL prefix you set in the ``). Without that, `` will not match any URLs in the file.
109 Good luck!
111 _PS: If you want to avoid using PyISAPIe, there is a simpler way of deploying on IIS. It is documented crudely over [here][1]._
113 [0]
114 [1]
Something went wrong with that request. Please try again.