Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
 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)
Ejemplo n.º 5
0
 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)
Ejemplo n.º 6
0
 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)
Ejemplo n.º 7
0
    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()
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
    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()
Ejemplo n.º 12
0
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
Ejemplo n.º 13
0
    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()
Ejemplo n.º 14
0
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