def send_status_response(environ, start_response, e, add_headers=None): """Start a WSGI response for a DAVError or status code.""" status = get_http_status_string(e) headers = [] if add_headers: headers.extend(add_headers) # if 'keep-alive' in environ.get('HTTP_CONNECTION', '').lower(): # headers += [ # ('Connection', 'keep-alive'), # ] if e in (HTTP_NOT_MODIFIED, HTTP_NO_CONTENT): # See paste.lint: these code don't have content start_response(status, [("Content-Length", "0"), ("Date", get_rfc1123_time())] + headers) return [b""] if e in (HTTP_OK, HTTP_CREATED): e = DAVError(e) assert isinstance(e, DAVError) content_type, body = e.get_response_page() assert compat.is_bytes(body), body # If not, Content-Length is wrong! start_response( status, [ ("Content-Type", content_type), ("Date", get_rfc1123_time()), ("Content-Length", str(len(body))), ] + headers, ) return [body]
def send_status_response(environ, start_response, e, add_headers=None, is_head=False): """Start a WSGI response for a DAVError or status code.""" status = get_http_status_string(e) headers = [] if add_headers: headers.extend(add_headers) # if 'keep-alive' in environ.get('HTTP_CONNECTION', '').lower(): # headers += [ # ('Connection', 'keep-alive'), # ] if e in (HTTP_NOT_MODIFIED, HTTP_NO_CONTENT): # See paste.lint: these code don't have content start_response( status, [("Content-Length", "0"), ("Date", get_rfc1123_time())] + headers ) return [b""] if e in (HTTP_OK, HTTP_CREATED): e = DAVError(e) assert isinstance(e, DAVError) content_type, body = e.get_response_page() if is_head: body = compat.b_empty assert compat.is_bytes(body), body # If not, Content-Length is wrong! start_response( status, [ ("Content-Type", content_type), ("Date", get_rfc1123_time()), ("Content-Length", str(len(body))), ] + headers, ) return [body]
def add_property_response(multistatusEL, href, propList): """Append <response> element to <multistatus> element. <prop> node depends on the value type: - str or unicode: add element with this content - None: add an empty element - etree.Element: add XML element as child - DAVError: add an empty element to an own <propstatus> for this status code @param multistatusEL: etree.Element @param href: global URL of the resource, e.g. 'http://server:port/path'. @param propList: list of 2-tuples (name, value) """ # Split propList by status code and build a unique list of namespaces nsCount = 1 nsDict = {} nsMap = {} propDict = {} for name, value in propList: status = "200 OK" if isinstance(value, DAVError): status = get_http_status_string(value) # Always generate *empty* elements for props with error status value = None # Collect namespaces, so we can declare them in the <response> for # compacter output ns, _ = split_namespace(name) if ns != "DAV:" and ns not in nsDict and ns != "": nsDict[ns] = True nsMap["NS{}".format(nsCount)] = ns nsCount += 1 propDict.setdefault(status, []).append((name, value)) # <response> responseEL = make_sub_element(multistatusEL, "{DAV:}response", nsmap=nsMap) # log("href value:{}".format(string_repr(href))) # etree.SubElement(responseEL, "{DAV:}href").text = toUnicode(href) etree.SubElement(responseEL, "{DAV:}href").text = href # etree.SubElement(responseEL, "{DAV:}href").text = compat.quote(href, safe="/" + "!*'()," # + "$-_|.") # One <propstat> per status code for status in propDict: propstatEL = etree.SubElement(responseEL, "{DAV:}propstat") # List of <prop> propEL = etree.SubElement(propstatEL, "{DAV:}prop") for name, value in propDict[status]: if value is None: etree.SubElement(propEL, name) elif is_etree_element(value): propEL.append(value) else: # value must be string or unicode # log("{} value:{}".format(name, string_repr(value))) # etree.SubElement(propEL, name).text = value etree.SubElement(propEL, name).text = to_unicode_safe(value) # <status> etree.SubElement(propstatEL, "{DAV:}status").text = "HTTP/1.1 {}".format(status)
def __call__(self, environ, start_response): # Intercept start_response sub_app_start_response = util.SubAppStartResponse() try: try: # request_server app may be a generator (for example the GET handler) # So we must iterate - not return self.next_app(..)! # Otherwise the we could not catch exceptions here. response_started = False app_iter = self.next_app(environ, sub_app_start_response) for v in app_iter: # Start response (the first time) if not response_started: # Success! start_response( sub_app_start_response.status, sub_app_start_response.response_headers, sub_app_start_response.exc_info, ) response_started = True yield v # Close out iterator if hasattr(app_iter, "close"): app_iter.close() # Start response (if it hasn't been done yet) if not response_started: # Success! start_response( sub_app_start_response.status, sub_app_start_response.response_headers, sub_app_start_response.exc_info, ) return except DAVError as e: _logger.debug("re-raising {}".format(e)) raise except Exception as e: # Caught a non-DAVError if self._catch_all_exceptions: # Catch all exceptions to return as 500 Internal Error # traceback.print_exc(10, environ.get("wsgi.errors") or sys.stderr) _logger.error("{}".format(traceback.format_exc(10))) raise as_DAVError(e) else: _logger.error("Caught Exception\n{}".format( traceback.format_exc(10))) # traceback.print_exc(10, sys.stderr) raise except DAVError as e: _logger.debug("caught {}".format(e)) status = get_http_status_string(e) # Dump internal errors to console if e.value == HTTP_INTERNAL_ERROR: tb = traceback.format_exc(10) _logger.error( "Caught HTTPRequestException(HTTP_INTERNAL_ERROR)\n{}". format(tb)) # traceback.print_exc(10, environ.get("wsgi.errors") or sys.stdout) _logger.error("e.srcexception:\n{}".format(e.srcexception)) elif e.value in (HTTP_NOT_MODIFIED, HTTP_NO_CONTENT): # _logger.warn("Forcing empty error response for {}".format(e.value)) # See paste.lint: these code don't have content start_response(status, [("Content-Length", "0"), ("Date", util.get_rfc1123_time())]) yield b"" return # If exception has pre-/post-condition: return as XML response, # else return as HTML content_type, body = e.get_response_page() # TODO: provide exc_info=sys.exc_info()? start_response( status, [ ("Content-Type", content_type), ("Content-Length", str(len(body))), ("Date", util.get_rfc1123_time()), ], ) yield body return
def __call__(self, environ, start_response): # Intercept start_response sub_app_start_response = util.SubAppStartResponse() try: try: # request_server app may be a generator (for example the GET handler) # So we must iterate - not return self.next_app(..)! # Otherwise the we could not catch exceptions here. response_started = False app_iter = self.next_app(environ, sub_app_start_response) for v in app_iter: # Start response (the first time) if not response_started: # Success! start_response( sub_app_start_response.status, sub_app_start_response.response_headers, sub_app_start_response.exc_info, ) response_started = True yield v # Close out iterator if hasattr(app_iter, "close"): app_iter.close() # Start response (if it hasn't been done yet) if not response_started: # Success! start_response( sub_app_start_response.status, sub_app_start_response.response_headers, sub_app_start_response.exc_info, ) return except DAVError as e: _logger.debug("re-raising {}".format(e)) raise except Exception as e: # Caught a non-DAVError if self.catch_all_exceptions: # Catch all exceptions to return as 500 Internal Error # traceback.print_exc(10, environ.get("wsgi.errors") or sys.stderr) _logger.error("{}".format(traceback.format_exc(10))) raise as_DAVError(e) else: _logger.error( "Caught Exception\n{}".format(traceback.format_exc(10)) ) # traceback.print_exc(10, sys.stderr) raise except DAVError as e: _logger.debug("caught {}".format(e)) status = get_http_status_string(e) # Dump internal errors to console if e.value == HTTP_INTERNAL_ERROR: tb = traceback.format_exc(10) _logger.error( "Caught HTTPRequestException(HTTP_INTERNAL_ERROR)\n{}".format(tb) ) # traceback.print_exc(10, environ.get("wsgi.errors") or sys.stdout) _logger.error("e.src_exception:\n{}".format(e.src_exception)) elif e.value in (HTTP_NOT_MODIFIED, HTTP_NO_CONTENT): # _logger.warning("Forcing empty error response for {}".format(e.value)) # See paste.lint: these code don't have content start_response( status, [("Content-Length", "0"), ("Date", util.get_rfc1123_time())] ) yield b"" return # If exception has pre-/post-condition: return as XML response, # else return as HTML content_type, body = e.get_response_page() # TODO: provide exc_info=sys.exc_info()? start_response( status, [ ("Content-Type", content_type), ("Content-Length", str(len(body))), ("Date", util.get_rfc1123_time()), ], ) yield body return