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