Exemplo n.º 1
0
def getErrorPage(status, **kwargs):
    """Return an HTML page, containing a pretty error response.
    
    status should be an int or a str.
    kwargs will be interpolated into the page template.
    """
    
    code, reason, message = cptools.validStatus(status)
    
    # We can't use setdefault here, because some
    # callers send None for kwarg values.
    if kwargs.get('status') is None:
        kwargs['status'] = "%s %s" % (code, reason)
    if kwargs.get('message') is None:
        kwargs['message'] = message
    if kwargs.get('traceback') is None:
        kwargs['traceback'] = ''
    if kwargs.get('version') is None:
        kwargs['version'] = cherrypy.__version__
    for k, v in kwargs.iteritems():
        if v is None:
            kwargs[k] = ""
        else:
            kwargs[k] = cgi.escape(kwargs[k])
    
    template = _HTTPErrorTemplate
    errorPageFile = cherrypy.config.get('errorPage.%s' % code, '')
    if errorPageFile:
        try:
            template = file(errorPageFile, 'rb').read()
        except:
            m = kwargs['message']
            if m:
                m += "<br />"
            m += ("In addition, the custom error page "
                  "failed:\n<br />%s" % (sys.exc_info()[1]))
            kwargs['message'] = m
    
    return template % kwargs
Exemplo n.º 2
0
def finalize():
    """Transform headerMap (and cookies) into cherrypy.response.headers."""
    
    response = cherrypy.response
    
    code, reason, _ = cptools.validStatus(response.status)
    response.status = "%s %s" % (code, reason)
    
    if response.body is None:
        response.body = []
    
    stream = cherrypy.config.get("streamResponse", False)
    # OPTIONS requests MUST include a Content-Length of 0 if no body.
    # Just punt and figure Content-Length for all OPTIONS requests.
    if cherrypy.request.method == "OPTIONS":
        stream = False
    
    if stream:
        try:
            del response.headerMap['Content-Length']
        except KeyError:
            pass
    else:
        # Responses which are not streamed should have a Content-Length,
        # but allow user code to set Content-Length if desired.
        if response.headerMap.get('Content-Length') is None:
            content = ''.join([chunk for chunk in response.body])
            response.body = [content]
            response.headerMap['Content-Length'] = len(content)
    
    # For some statuses, Internet Explorer 5+ shows "friendly error messages"
    # instead of our response.body if the body is smaller than a given size.
    # Fix this by returning a body over that size (by adding whitespace).
    # See http://support.microsoft.com/kb/q218155/
    s = int(response.status.split(" ")[0])
    s = _ie_friendly_error_sizes.get(s, 0)
    if s:
        s += 1
        # Since we are issuing an HTTP error status, we assume that
        # the entity is short, and we should just collapse it.
        content = ''.join([chunk for chunk in response.body])
        response.body = [content]
        l = len(content)
        if l and l < s:
            # IN ADDITION: the response must be written to IE
            # in one chunk or it will still get replaced! Bah.
            response.body = [response.body[0] + (" " * (s - l))]
            response.headerMap['Content-Length'] = s
    
    # Headers
    headers = []
    for key, valueList in response.headerMap.iteritems():
        order = _header_order_map.get(key, 3)
        if not isinstance(valueList, list):
            valueList = [valueList]
        for value in valueList:
            headers.append((order, (key, str(value))))
    # RFC 2616: '... it is "good practice" to send general-header fields
    # first, followed by request-header or response-header fields, and
    # ending with the entity-header fields.'
    headers.sort()
    response.headers = [item[1] for item in headers]
    
    cookie = response.simpleCookie.output()
    if cookie:
        lines = cookie.split("\n")
        for line in lines:
            name, value = line.split(": ", 1)
            response.headers.append((name, value))