# This is a sample configuration file for an ISAPI filter and extension # written in Python. # # Please see README.txt in this directory, and specifically the # information about the "loader" DLL - installing this sample will create # "_redirector_with_filter.dll" in the current directory. The readme explains # this. # Executing this script (or any server config script) will install the extension # into your web server. As the server executes, the PyISAPI framework will load # this module and create your Extension and Filter objects. # This sample provides sample redirector: # It is implemented by a filter and an extension, so that some requests can # be ignored. Compare with 'redirector_simple' which avoids the filter, but # is unable to selectively ignore certain requests. # The process is sample uses is: # * The filter is installed globally, as all filters are. # * A Virtual Directory named "python" is setup. This dir has our ISAPI # extension as the only application, mapped to file-extension '*'. Thus, our # extension handles *all* requests in this directory. # The basic process is that the filter does URL rewriting, redirecting every # URL to our Virtual Directory. Our extension then handles this request, # forwarding the data from the proxied site. # For example: # * URL of "index.html" comes in. # * Filter rewrites this to "/python/index.html" # * Our extension sees the full "/python/index.html", removes the leading # portion, and opens and forwards the remote URL. # This sample is very small - it avoid most error handling, etc. It is for # demonstration purposes only. from isapi import isapicon, threaded_extension from isapi.simple import SimpleFilter import sys import traceback import urllib.request, urllib.parse, urllib.error # sys.isapidllhandle will exist when we are loaded by the IIS framework. # In this case we redirect our output to the win32traceutil collector. if hasattr(sys, "isapidllhandle"): import win32traceutil # The site we are proxying. proxy = "http://www.python.org" # The name of the virtual directory we install in, and redirect from. virtualdir = "/python" # The key feature of this redirector over the simple redirector is that it # can choose to ignore certain responses by having the filter not rewrite them # to our virtual dir. For this sample, we just exclude the IIS help directory. # The ISAPI extension - handles requests in our virtual dir, and sends the # response to the client. class Extension(threaded_extension.ThreadPoolExtension): "Python sample Extension" def Dispatch(self, ecb): # Note that our ThreadPoolExtension base class will catch exceptions # in our Dispatch method, and write the traceback to the client. # That is perfect for this sample, so we don't catch our own. #print 'IIS dispatching "%s"' % (ecb.GetServerVariable("URL"),) url = ecb.GetServerVariable("URL") if url.startswith(virtualdir): new_url = proxy + url[len(virtualdir):] print("Opening", new_url) fp = urllib.request.urlopen(new_url) headers = fp.info() ecb.SendResponseHeaders("200 OK", str(headers) + "\r\n", False) ecb.WriteClient(fp.read()) ecb.DoneWithSession() print("Returned data from '%s'!" % (new_url,)) else: # this should never happen - we should only see requests that # start with our virtual directory name. print("Not proxying '%s'" % (url,)) # The ISAPI filter. class Filter(SimpleFilter): "Sample Python Redirector" filter_flags = isapicon.SF_NOTIFY_PREPROC_HEADERS | \ isapicon.SF_NOTIFY_ORDER_DEFAULT def HttpFilterProc(self, fc): #print "Filter Dispatch" nt = fc.NotificationType if nt != isapicon.SF_NOTIFY_PREPROC_HEADERS: return isapicon.SF_STATUS_REQ_NEXT_NOTIFICATION pp = fc.GetData() url = pp.GetHeader("url") #print "URL is '%s'" % (url,) prefix = virtualdir if not url.startswith(prefix): new_url = prefix + url print("New proxied URL is '%s'" % (new_url,)) pp.SetHeader("url", new_url) # For the sake of demonstration, show how the FilterContext # attribute is used. It always starts out life as None, and # any assignments made are automatically decref'd by the # framework during a SF_NOTIFY_END_OF_NET_SESSION notification. if fc.FilterContext is None: fc.FilterContext = 0 fc.FilterContext += 1 print("This is request number %d on this connection" % fc.FilterContext) return isapicon.SF_STATUS_REQ_HANDLED_NOTIFICATION else: print("Filter ignoring URL '%s'" % (url,)) # Some older code that handled SF_NOTIFY_URL_MAP. #~ print "Have URL_MAP notify" #~ urlmap = fc.GetData() #~ print "URI is", urlmap.URL #~ print "Path is", urlmap.PhysicalPath #~ if urlmap.URL.startswith("/UC/"): #~ # Find the /UC/ in the physical path, and nuke it (except #~ # as the path is physical, it is \) #~ p = urlmap.PhysicalPath #~ pos = p.index("\\UC\\") #~ p = p[:pos] + p[pos+3:] #~ p = r"E:\src\pyisapi\webroot\PyTest\formTest.htm" #~ print "New path is", p #~ urlmap.PhysicalPath = p # The entry points for the ISAPI extension. def __FilterFactory__(): return Filter() def __ExtensionFactory__(): return Extension() if __name__=='__main__': # If run from the command-line, install ourselves. from isapi.install import * params = ISAPIParameters() # Setup all filters - these are global to the site. params.Filters = [ FilterParameters(Name="PythonRedirector", Description=Filter.__doc__), ] # Setup the virtual directories - this is a list of directories our # extension uses - in this case only 1. # Each extension has a "script map" - this is the mapping of ISAPI # extensions. sm = [ ScriptMapParams(Extension="*", Flags=0) ] vd = VirtualDirParameters(Name=virtualdir[1:], Description = Extension.__doc__, ScriptMaps = sm, ScriptMapUpdate = "replace" ) params.VirtualDirs = [vd] HandleCommandLine(params)