WEB开发网
开发学院软件开发Python 用 Python WSGI 混和并匹配 Web 组件 阅读

用 Python WSGI 混和并匹配 Web 组件

 2010-09-22 11:13:19 来源:WEB开发网   
核心提示: 清单 1(safexhtml.py). WSGI 中间件为不能处理 XHTML 的浏览器把 XHTML 翻译成 HTMLimport cStringIOfrom xml import saxfrom Ft.Xml import CreateInputSourcefrom Ft.Xml.Sa

清单 1(safexhtml.py). WSGI 中间件为不能处理 XHTML 的浏览器把 XHTML 翻译成 HTML

import cStringIO
from xml import sax
from Ft.Xml import CreateInputSource
from Ft.Xml.Sax import SaxPrinter
from Ft.Xml.Lib.HtmlPrinter import HtmlPrinter
XHTML_IMT = "application/xhtml+xml"
HTML_CONTENT_TYPE = 'text/html; charset=UTF-8'
class safexhtml(object):
  """
  Middleware that checks for XHTML capability in the client and translates
  XHTML to HTML if the client can't handle it
  """
  def __init__(self, app):
    #Set-up phase
    self.wrapped_app = app
    return
  def __call__(self, environ, start_response):
    #Handling a client request phase.
    #Called for each client request routed through this middleware
    #Does the client specifically say it supports XHTML?
    #Note saying it accepts */* or application/* will not be enough
    xhtml_ok = XHTML_IMT in environ.get('HTTP_ACCEPT', '')
    #Specialized start_response function for this middleware
    def start_response_wrapper(status, response_headers, exc_info=None):
      #Assume response is not XHTML; do not activate transformation
      environ['safexhtml.active'] = False
      #Check for response content type to see whether it is XHTML
      #That needs to be transformed
      for name, value in response_headers:
        #content-type value is a media type, defined as
        #media-type = type "/" subtype *( ";" parameter )
        if ( name.lower() == 'content-type'
           and value.split(';')[0] == XHTML_IMT ):
          #Strip content-length if present (needs to be
          #recalculated by server)
          #Also strip content-type, which will be replaced below
          response_headers = [ (name, value)
            for name, value in response_headers
              if ( name.lower()
                 not in ['content-length', 'content-type'])
          ]
          #Put in the updated content type
          response_headers.append(('content-type', HTML_CONTENT_TYPE))
          #Response is XHTML, so activate transformation
          environ['safexhtml.active'] = True
          break
      #We ignore the return value from start_response
      start_response(status, response_headers, exc_info)
      #Replace any write() callable with a dummy that gives an error
      #The idea is to refuse support for apps that use write()
      def dummy_write(data):
        raise RuntimeError('safexhtml does not support the deprecated
                    write() callable in WSGI clients')
      return dummy_write
    if xhtml_ok:
      #The client can handle XHTML, so nothing for this middleware to do
      #Notice that the original start_response function is passed
      #On, not this middleware's start_response_wrapper
      for data in self.wrapped_app(environ, start_response):
        yield data
    else:
      response_blocks = [] #Gather output strings for concatenation
      for data in self.wrapped_app(environ, start_response_wrapper):
        if environ['safexhtml.active']:
          response_blocks.append(data)
          yield '' #Obey buffering rules for WSGI
        else:
          yield data
      if environ['safexhtml.active']:
        #Need to convert response from XHTML to HTML
        xhtmlstr = ''.join(response_blocks) #First concatenate response
        #Now use 4Suite to transform XHTML to HTML
        htmlstr = cStringIO.StringIO() #Will hold the HTML result
        parser = sax.make_parser(['Ft.Xml.Sax'])
        handler = SaxPrinter(HtmlPrinter(htmlstr, 'UTF-8'))
        parser.setContentHandler(handler)
        #Don't load the XHTML DTDs from the Internet
        parser.setFeature(sax.handler.feature_external_pes, False)
        parser.parse(CreateInputSource(xhtmlstr))
        yield htmlstr.getvalue()
        return

上一页  1 2 3 4 5 6 7  下一页

Tags:Python WSGI 匹配

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接