redirector_asynch.py SampleΒΆ

 1# This is a sample ISAPI extension written in Python.
 2
 3# This is like the other 'redirector' samples, but uses asnch IO when writing
 4# back to the client (it does *not* use asynch io talking to the remote
 5# server!)
 6
 7from isapi import isapicon, threaded_extension
 8import sys
 9import traceback
10import urllib.request, urllib.parse, urllib.error
11
12# sys.isapidllhandle will exist when we are loaded by the IIS framework.
13# In this case we redirect our output to the win32traceutil collector.
14if hasattr(sys, "isapidllhandle"):
15    import win32traceutil
16
17# The site we are proxying.
18proxy = "http://www.python.org"
19
20# We synchronously read chunks of this size then asynchronously write them.
21CHUNK_SIZE = 8192
22
23# The callback made when IIS completes the asynch write.
24def io_callback(ecb, fp, cbIO, errcode):
25    print("IO callback", ecb, fp, cbIO, errcode)
26    chunk = fp.read(CHUNK_SIZE)
27    if chunk:
28        ecb.WriteClient(chunk, isapicon.HSE_IO_ASYNC)
29        # and wait for the next callback to say this chunk is done.
30    else:
31        # eof - say we are complete.
32        fp.close()
33        ecb.DoneWithSession()
34
35
36# The ISAPI extension - handles all requests in the site.
37class Extension(threaded_extension.ThreadPoolExtension):
38    "Python sample proxy server - asynch version."
39
40    def Dispatch(self, ecb):
41        print('IIS dispatching "%s"' % (ecb.GetServerVariable("URL"),))
42        url = ecb.GetServerVariable("URL")
43
44        new_url = proxy + url
45        print("Opening %s" % new_url)
46        fp = urllib.request.urlopen(new_url)
47        headers = fp.info()
48        ecb.SendResponseHeaders("200 OK", str(headers) + "\r\n", False)
49        # now send the first chunk asynchronously
50        ecb.ReqIOCompletion(io_callback, fp)
51        chunk = fp.read(CHUNK_SIZE)
52        if chunk:
53            ecb.WriteClient(chunk, isapicon.HSE_IO_ASYNC)
54            return isapicon.HSE_STATUS_PENDING
55        # no data - just close things now.
56        ecb.DoneWithSession()
57        return isapicon.HSE_STATUS_SUCCESS
58
59
60# The entry points for the ISAPI extension.
61def __ExtensionFactory__():
62    return Extension()
63
64
65if __name__ == "__main__":
66    # If run from the command-line, install ourselves.
67    from isapi.install import *
68
69    params = ISAPIParameters()
70    # Setup the virtual directories - this is a list of directories our
71    # extension uses - in this case only 1.
72    # Each extension has a "script map" - this is the mapping of ISAPI
73    # extensions.
74    sm = [ScriptMapParams(Extension="*", Flags=0)]
75    vd = VirtualDirParameters(
76        Name="/",
77        Description=Extension.__doc__,
78        ScriptMaps=sm,
79        ScriptMapUpdate="replace",
80    )
81    params.VirtualDirs = [vd]
82    HandleCommandLine(params)