""" WSGI wrapper for ASP. Example Global.asa for a CherryPy app called "mcontrol": Example handler.asp: <%@Language=Python%> <% from wsgiref.asp_gateway import handler from cherrypy.wsgiapp import wsgiApp h = handler(Application, Request, Response) h.run(wsgiApp) Response.status = handler.status %> """ import sys from wsgiref.handlers import BaseCGIHandler class ASPInputWrapper(object): def __init__(self, Request): self.stream = Request.BinaryRead size = Request.ServerVariables('CONTENT_LENGTH') self.remainder = self.size = int(size) def read(self, size=-1): if size < 0: size = self.remainder content, size = self.stream(size) self.remainder -= size return str(content) def readline(self): output = [] while True: # Use an internal buffer instead? Still have to check for \n char = self.read(1) if not char: break output.append(char) if char in ('\n', '\r'): break return ''.join(output) def readlines(self, hint=-1): lines = [] while True: line = self.readline() if not line: break lines.append(line) return lines def __iter__(self): line = self.readline() while line: yield line # Notice this won't prefetch the next line; it only # gets called if the generator is resumed. line = self.readline() class handler(BaseCGIHandler): def __init__(self, Application, Request, Response, buffering=True): # If you set buffering to False, you must not "Enable Buffering" in # the current Virtual Directory, NOR in any of its parent containers # (directory, site, or server). IIS 5 and 6 buffer by default. # See http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306805 # and http://www.aspfaq.com/show.asp?id=2262 Response.Buffer = buffering env = {} for name in Request.ServerVariables: try: # names and values are both probably unicode. coerce them. env[str(name)] = str(Request.ServerVariables(name)) except UnicodeEncodeError, x: # There's a potential problem lurking here, since some ASP # server var's which are required by WSGI may be high ASCII. x.args += ((u"Server Variable '%s'" % name),) raise x multiprocess = str(Application.Contents("multiprocess")) multithread = str(Application.Contents("multithread")) # You will probably need *some* form of rewriter to use ASP # with WSGI, since ASP requires one physical .asp file # per requestable-URL; so far, we support one: # Handle URL rewriting done by ISAPI_Rewrite Lite. # http://www.isapirewrite.com/ # Note that PATH_TRANSLATED is also rewritten, but we # don't make any provision for unmunging that. old_path = env.get("HTTP_X_REWRITE_URL", None) if old_path: # Tear off any params. env["PATH_INFO"] = old_path.split("?")[0] # ASP puts the same values in SCRIPT_NAME and PATH_INFO, # for some odd reason. Empty one of them. env["SCRIPT_NAME"] = "" BaseCGIHandler.__init__(self, stdin=ASPInputWrapper(Request), stdout=None, stderr=sys.stderr, environ=env, multiprocess=multiprocess, multithread=multithread ) self.Response = Response self._write = Response.Write def _flush(self): self.Response.Flush() def send_headers(self): self.cleanup_headers() self.headers_sent = True for key, val in self.headers.items(): self.Response.AddHeader(key, val) def start_response(self, *args, **kwargs): BaseCGIHandler.start_response(self, *args, **kwargs) self.Response.Status = self.status