def setBody(self, body, title='', is_error=False, lock=None): # allow locking of the body in the same way as the status if self._locked_body: return if isinstance(body, IOBase): body.seek(0, 2) length = body.tell() body.seek(0) self.setHeader('Content-Length', '%d' % length) self.body = body elif IStreamIterator.providedBy(body): self.body = body super().setBody(b'', title, is_error) elif IUnboundStreamIterator.providedBy(body): self.body = body self._streaming = 1 super().setBody(b'', title, is_error) else: super().setBody(body, title, is_error) # Have to apply the lock at the end in case the super class setBody # is called, which will observe the lock and do nothing if lock: self._locked_body = 1
def setBody(self, body, title='', is_error=False, lock=None): # allow locking of the body in the same way as the status if self._locked_body: return if isinstance(body, IOBase): body.seek(0, 2) length = body.tell() body.seek(0) self.setHeader('Content-Length', '%d' % length) self.body = body elif IStreamIterator.providedBy(body): self.body = body super(WSGIResponse, self).setBody(b'', title, is_error) elif IUnboundStreamIterator.providedBy(body): self.body = body self._streaming = 1 super(WSGIResponse, self).setBody(b'', title, is_error) else: super(WSGIResponse, self).setBody(body, title, is_error) # Have to apply the lock at the end in case the super class setBody # is called, which will observe the lock and do nothing if lock: self._locked_body = 1
def publish_module( environ, start_response, _publish=publish, # only for testing _response=None, _response_factory=WSGIResponse, _request=None, _request_factory=WSGIRequest, _module_name='Zope2'): module_info = get_module_info(_module_name) result = () with closing(BytesIO()) as stdout, closing(BytesIO()) as stderr: response = (_response if _response is not None else _response_factory( stdout=stdout, stderr=stderr)) response._http_version = environ['SERVER_PROTOCOL'].split('/')[1] response._server_version = environ.get('SERVER_SOFTWARE') request = (_request if _request is not None else _request_factory( environ['wsgi.input'], environ, response)) for i in range(getattr(request, 'retry_max_count', 3) + 1): setRequest(request) try: with load_app(module_info) as new_mod_info: with transaction_pubevents(request, response): response = _publish(request, new_mod_info) break except (ConflictError, TransientError) as exc: if request.supports_retry(): new_request = request.retry() request.close() request = new_request response = new_request.response else: raise finally: request.close() clearRequest() # Start the WSGI server response status, headers = response.finalize() start_response(status, headers) if (isinstance(response.body, _FILE_TYPES) or IUnboundStreamIterator.providedBy(response.body)): result = response.body else: # If somebody used response.write, that data will be in the # stdout BytesIO, so we put that before the body. result = (stdout.getvalue(), response.body) for func in response.after_list: func() # Return the result body iterable. return result
def setBody(self, body, title='', is_error=0): if isinstance(body, file): body.seek(0, 2) length = body.tell() body.seek(0) self.setHeader('Content-Length', '%d' % length) self.body = body elif IStreamIterator.providedBy(body): self.body = body HTTPResponse.setBody(self, '', title, is_error) elif IUnboundStreamIterator.providedBy(body): self.body = body self._streaming = 1 HTTPResponse.setBody(self, '', title, is_error) else: HTTPResponse.setBody(self, body, title, is_error)
def setBody(self, body, title='', is_error=False): if isinstance(body, IOBase): body.seek(0, 2) length = body.tell() body.seek(0) self.setHeader('Content-Length', '%d' % length) self.body = body elif IStreamIterator.providedBy(body): self.body = body super(WSGIResponse, self).setBody(b'', title, is_error) elif IUnboundStreamIterator.providedBy(body): self.body = body self._streaming = 1 super(WSGIResponse, self).setBody(b'', title, is_error) else: super(WSGIResponse, self).setBody(body, title, is_error)
def finish_response(self, app_iter): code, message = self.status.split(None, 1) code = int(code) self.request.setResponseCode(code, _wsgiStringToBytes(message)) for name, value in self.headers: # Don't allow the application to control these required headers. if name.lower() not in ("server", "date"): self.request.responseHeaders.addRawHeader( _wsgiStringToBytes(name), _wsgiStringToBytes(value)) if isinstance( app_iter, _FILE_TYPES) or IUnboundStreamIterator.providedBy(app_iter): if not self._requestFinished: self._producer = FileSender() d = self._producer.beginFileTransfer(app_iter, self.request) d.addBoth(lambda *args: self.stop()) else: for elem in app_iter: if not self._requestFinished: self.request.write(elem) self.stop()
def publish_module(environ, start_response, _publish=publish, # only for testing _response=None, _response_factory=WSGIResponse, _request=None, _request_factory=WSGIRequest, _module_name='Zope2'): module_info = get_module_info(_module_name) result = () path_info = environ.get('PATH_INFO') if path_info: # The WSGI server automatically treats the PATH_INFO as latin-1 encoded # bytestrings. Typically this is a false assumption as the browser # delivers utf-8 encoded PATH_INFO. We, therefore, need to encode it # again with latin-1 to get a utf-8 encoded bytestring. This is # sufficient for Python 2. path_info = path_info.encode('latin-1') if PY3: # In Python 3 we need unicode here, so we decode the bytestring. path_info = path_info.decode('utf-8') environ['PATH_INFO'] = path_info with closing(BytesIO()) as stdout, closing(BytesIO()) as stderr: response = (_response if _response is not None else _response_factory(stdout=stdout, stderr=stderr)) response._http_version = environ['SERVER_PROTOCOL'].split('/')[1] response._server_version = environ.get('SERVER_SOFTWARE') request = (_request if _request is not None else _request_factory(environ['wsgi.input'], environ, response)) for i in range(getattr(request, 'retry_max_count', 3) + 1): setRequest(request) try: with load_app(module_info) as new_mod_info: with transaction_pubevents(request, response): response = _publish(request, new_mod_info) break except (ConflictError, TransientError) as exc: if request.supports_retry(): new_request = request.retry() request.close() request = new_request response = new_request.response else: raise finally: request.close() clearRequest() # Start the WSGI server response status, headers = response.finalize() start_response(status, headers) if (isinstance(response.body, _FILE_TYPES) or IUnboundStreamIterator.providedBy(response.body)): result = response.body else: # If somebody used response.write, that data will be in the # response.stdout BytesIO, so we put that before the body. result = (response.stdout.getvalue(), response.body) for func in response.after_list: func() # Return the result body iterable. return result
def publish_module( environ, start_response, _publish=publish, # only for testing _response=None, _response_factory=WSGIResponse, _request=None, _request_factory=WSGIRequest, _module_name='Zope2'): module_info = get_module_info(_module_name) result = () path_info = environ.get('PATH_INFO') if path_info and PY3: # BIG Comment, see discussion at # https://github.com/zopefoundation/Zope/issues/575 # # The WSGI server automatically treats headers, including the # PATH_INFO, as latin-1 encoded bytestrings, according to PEP-3333. As # this causes headache I try to show the steps a URI takes in WebOb, # which is similar in other wsgi server implementations. # UTF-8 URL-encoded object-id 'täst': # http://localhost/t%C3%A4st # unquote('/t%C3%A4st'.decode('ascii')) results in utf-8 encoded bytes # b'/t\xc3\xa4st' # b'/t\xc3\xa4st'.decode('latin-1') latin-1 decoding due to PEP-3333 # '/täst' # We now have a latin-1 decoded text, which was actually utf-8 encoded. # To reverse this we have to encode with latin-1 first. path_info = path_info.encode('latin-1') # So we can now decode with the right (utf-8) encoding to get text. # This encode/decode two-step with different encodings works because # of the way PEP-3333 restricts the type of string allowable for # request and response metadata. The allowed characters match up in # both latin-1 and utf-8. path_info = path_info.decode('utf-8') environ['PATH_INFO'] = path_info with closing(BytesIO()) as stdout, closing(BytesIO()) as stderr: new_response = (_response if _response is not None else _response_factory(stdout=stdout, stderr=stderr)) new_response._http_version = environ['SERVER_PROTOCOL'].split('/')[1] new_response._server_version = environ.get('SERVER_SOFTWARE') new_request = (_request if _request is not None else _request_factory( environ['wsgi.input'], environ, new_response)) for i in range(getattr(new_request, 'retry_max_count', 3) + 1): request = new_request response = new_response setRequest(request) try: with load_app(module_info) as new_mod_info: with transaction_pubevents(request, response): response = _publish(request, new_mod_info) break except TransientError: if request.supports_retry(): new_request = request.retry() new_response = new_request.response else: raise finally: request.close() clearRequest() # Start the WSGI server response status, headers = response.finalize() start_response(status, headers) if isinstance(response.body, _FILE_TYPES) or \ IUnboundStreamIterator.providedBy(response.body): result = response.body else: # If somebody used response.write, that data will be in the # response.stdout BytesIO, so we put that before the body. result = (response.stdout.getvalue(), response.body) for func in response.after_list: func() # Return the result body iterable. return result
def publish_module( environ, start_response, _publish=publish, # only for testing _response=None, _response_factory=WSGIResponse, _request=None, _request_factory=WSGIRequest, _module_name='Zope2'): module_info = get_module_info(_module_name) result = () path_info = environ.get('PATH_INFO') if path_info and PY3: # The WSGI server automatically treats the PATH_INFO as latin-1 encoded # bytestrings. Typically this is a false assumption as the browser # delivers utf-8 encoded PATH_INFO. We, therefore, need to encode it # again with latin-1 to get a utf-8 encoded bytestring. path_info = path_info.encode('latin-1') # But in Python 3 we need text here, so we decode the bytestring. path_info = path_info.decode('utf-8') environ['PATH_INFO'] = path_info with closing(BytesIO()) as stdout, closing(BytesIO()) as stderr: new_response = (_response if _response is not None else _response_factory(stdout=stdout, stderr=stderr)) new_response._http_version = environ['SERVER_PROTOCOL'].split('/')[1] new_response._server_version = environ.get('SERVER_SOFTWARE') new_request = (_request if _request is not None else _request_factory( environ['wsgi.input'], environ, new_response)) for i in range(getattr(new_request, 'retry_max_count', 3) + 1): request = new_request response = new_response setRequest(request) try: with load_app(module_info) as new_mod_info: with transaction_pubevents(request, response): response = _publish(request, new_mod_info) break except TransientError as exc: if request.supports_retry(): new_request = request.retry() new_response = new_request.response else: raise finally: request.close() clearRequest() # Start the WSGI server response status, headers = response.finalize() start_response(status, headers) if (isinstance(response.body, _FILE_TYPES) or IUnboundStreamIterator.providedBy(response.body)): result = response.body else: # If somebody used response.write, that data will be in the # response.stdout BytesIO, so we put that before the body. result = (response.stdout.getvalue(), response.body) for func in response.after_list: func() # Return the result body iterable. return result
setDefaultSkin(request) try: response = _publish(request, 'Zope2') except Unauthorized, v: response._unauthorized() except Redirect, v: response.redirect(v) # Start the WSGI server response status, headers = response.finalize() start_response(status, headers) body = response.body if isinstance(body, file) or IUnboundStreamIterator.providedBy(body): result = body else: # If somebody used response.write, that data will be in the # stdout StringIO, so we put that before the body. # XXX This still needs verification that it really works. result = (stdout.getvalue(), response.body) if 'repoze.tm.active' not in environ: request.close() # this aborts the transation! stdout.close() for callable in response.after_list: callable()
def publish_module( environ, start_response, _publish=publish, # only for testing _response=None, _response_factory=WSGIResponse, _request=None, _request_factory=WSGIRequest, _module_name='Zope2'): module_info = get_module_info(_module_name) result = () path_info = environ.get('PATH_INFO') if path_info: # BIG Comment, see discussion at # https://github.com/zopefoundation/Zope/issues/575 # # The WSGI server automatically treats headers, including the # PATH_INFO, as latin-1 encoded bytestrings, according to PEP-3333. As # this causes headache I try to show the steps a URI takes in WebOb, # which is similar in other wsgi server implementations. # UTF-8 URL-encoded object-id 'täst': # http://localhost/t%C3%A4st # unquote('/t%C3%A4st'.decode('ascii')) results in utf-8 encoded bytes # b'/t\xc3\xa4st' # b'/t\xc3\xa4st'.decode('latin-1') latin-1 decoding due to PEP-3333 # '/täst' # We now have a latin-1 decoded text, which was actually utf-8 encoded. # To reverse this we have to encode with latin-1 first. path_info = path_info.encode('latin-1') # So we can now decode with the right (utf-8) encoding to get text. # This encode/decode two-step with different encodings works because # of the way PEP-3333 restricts the type of string allowable for # request and response metadata. The allowed characters match up in # both latin-1 and utf-8. path_info = path_info.decode('utf-8') environ['PATH_INFO'] = path_info # See if this should be be marked up as WebDAV request. try: server_port = int(environ['SERVER_PORT']) except (KeyError, ValueError): server_port = 0 if _WEBDAV_SOURCE_PORT and _WEBDAV_SOURCE_PORT == server_port: environ['WEBDAV_SOURCE_PORT'] = 1 # GET needs special treatment. Traversal is forced to the # manage_DAVget method to get the unrendered sources. if environ['REQUEST_METHOD'].upper() == 'GET': environ['PATH_INFO'] = '%s/manage_DAVget' % environ['PATH_INFO'] with closing(BytesIO()) as stdout, closing(BytesIO()) as stderr: new_response = (_response if _response is not None else _response_factory(stdout=stdout, stderr=stderr)) new_response._http_version = environ['SERVER_PROTOCOL'].split('/')[1] new_response._server_version = environ.get('SERVER_SOFTWARE') new_request = (_request if _request is not None else _request_factory( environ['wsgi.input'], environ, new_response)) for i in range(getattr(new_request, 'retry_max_count', 3) + 1): request = new_request response = new_response setRequest(request) try: with load_app(module_info) as new_mod_info: with transaction_pubevents(request, response): response = _publish(request, new_mod_info) user = getSecurityManager().getUser() if user is not None and \ user.getUserName() != 'Anonymous User': environ['REMOTE_USER'] = user.getUserName() break except TransientError: if request.supports_retry(): request.delay_retry() # Insert a time delay new_request = request.retry() new_response = new_request.response else: raise finally: request.close() clearRequest() # Start the WSGI server response status, headers = response.finalize() start_response(status, headers) if isinstance(response.body, _FILE_TYPES) or \ IUnboundStreamIterator.providedBy(response.body): if hasattr(response.body, 'read') and \ 'wsgi.file_wrapper' in environ: result = environ['wsgi.file_wrapper'](response.body) else: result = response.body else: # If somebody used response.write, that data will be in the # response.stdout BytesIO, so we put that before the body. result = (response.stdout.getvalue(), response.body) for func in response.after_list: func() # Return the result body iterable. return result
def publish_module(environ, start_response, _publish=publish, # only for testing _response=None, _response_factory=WSGIResponse, _request=None, _request_factory=WSGIRequest, _module_name='Zope2'): module_info = get_module_info(_module_name) result = () path_info = environ.get('PATH_INFO') if path_info and PY3: # BIG Comment, see discussion at # https://github.com/zopefoundation/Zope/issues/575 # # The WSGI server automatically treats headers, including the # PATH_INFO, as latin-1 encoded bytestrings, according to PEP-3333. As # this causes headache I try to show the steps a URI takes in WebOb, # which is similar in other wsgi server implementations. # UTF-8 URL-encoded object-id 'täst': # http://localhost/t%C3%A4st # unquote('/t%C3%A4st'.decode('ascii')) results in utf-8 encoded bytes # b'/t\xc3\xa4st' # b'/t\xc3\xa4st'.decode('latin-1') latin-1 decoding due to PEP-3333 # '/täst' # We now have a latin-1 decoded text, which was actually utf-8 encoded. # To reverse this we have to encode with latin-1 first. path_info = path_info.encode('latin-1') # So we can now decode with the right (utf-8) encoding to get text. # This encode/decode two-step with different encodings works because # of the way PEP-3333 restricts the type of string allowable for # request and response metadata. The allowed characters match up in # both latin-1 and utf-8. path_info = path_info.decode('utf-8') environ['PATH_INFO'] = path_info with closing(BytesIO()) as stdout, closing(BytesIO()) as stderr: new_response = ( _response if _response is not None else _response_factory(stdout=stdout, stderr=stderr)) new_response._http_version = environ['SERVER_PROTOCOL'].split('/')[1] new_response._server_version = environ.get('SERVER_SOFTWARE') new_request = ( _request if _request is not None else _request_factory(environ['wsgi.input'], environ, new_response)) for i in range(getattr(new_request, 'retry_max_count', 3) + 1): request = new_request response = new_response setRequest(request) try: with load_app(module_info) as new_mod_info: with transaction_pubevents(request, response): response = _publish(request, new_mod_info) break except TransientError: if request.supports_retry(): new_request = request.retry() new_response = new_request.response else: raise finally: request.close() clearRequest() # Start the WSGI server response status, headers = response.finalize() start_response(status, headers) if isinstance(response.body, _FILE_TYPES) or \ IUnboundStreamIterator.providedBy(response.body): result = response.body else: # If somebody used response.write, that data will be in the # response.stdout BytesIO, so we put that before the body. result = (response.stdout.getvalue(), response.body) for func in response.after_list: func() # Return the result body iterable. return result