You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
6.5 KiB
156 lines
6.5 KiB
# 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)
|