Example #1
0
    def __call__(self, environ, start_response):
        # Request for this state, modified by replace_start_response()
        # and used when an error is being reported.
        state = {}

        def replacement_start_response(status, headers, exc_info=None):
            """Overrides the default response to make errors parsable.
            """
            try:
                status_code = int(status.split(' ')[0])
                state['status_code'] = status_code
            except (ValueError, TypeError):  # pragma: nocover
                raise Exception((
                    'ErrorDocumentMiddleware received an invalid '
                    'status %s' % status
                ))
            else:
                if (state['status_code'] / 100) not in (2, 3):
                    # Remove some headers so we can replace them later
                    # when we have the full error message and can
                    # compute the length.
                    headers = [(h, v)
                               for (h, v) in headers
                               if h not in ('Content-Length', 'Content-Type')
                               ]
                # Save the headers in case we need to modify them.
                state['headers'] = headers
                return start_response(status, headers, exc_info)

        app_iter = self.app(environ, replacement_start_response)
        if (state['status_code'] / 100) not in (2, 3):
            req = webob.Request(environ)
            # Find the first TranslationHook in the array of hooks and use the
            # translatable_error object from it
            error = None
            for hook in self.app.hooks:
                if isinstance(hook, hooks.TranslationHook):
                    error = hook.local_error.translatable_error
                    break
            user_locale = self.best_match_language(req.accept_language)
            if (req.accept.best_match(['application/json', 'application/xml'])
               == 'application/xml'):
                try:
                    # simple check xml is valid
                    fault = etree.fromstring('\n'.join(app_iter))
                    # Add the translated error to the xml data
                    if error is not None:
                        for fault_string in fault.findall('faultstring'):
                            fault_string.text = (
                                gettextutils.translate(
                                    error, user_locale))
                    body = ['<error_message>' + etree.tostring(fault)
                            + '</error_message>']
                except etree.XMLSyntaxError as err:
                    LOG.error(_('Error parsing HTTP response: %s') % err)
                    body = ['<error_message>%s' % state['status_code']
                            + '</error_message>']
                state['headers'].append(('Content-Type', 'application/xml'))
            else:
                try:
                    fault = json.loads('\n'.join(app_iter))
                    if error is not None and 'faultstring' in fault:
                        fault['faultstring'] = (
                            gettextutils.translate(
                                error, user_locale))
                    body = [json.dumps({'error_message': fault})]
                except ValueError as err:
                    body = [json.dumps({'error_message': '\n'.join(app_iter)})]
                state['headers'].append(('Content-Type', 'application/json'))
            state['headers'].append(('Content-Length', str(len(body[0]))))
        else:
            body = app_iter
        return body
Example #2
0
    def __call__(self, environ, start_response):
        # Request for this state, modified by replace_start_response()
        # and used when an error is being reported.
        state = {}

        def replacement_start_response(status, headers, exc_info=None):
            """Overrides the default response to make errors parsable.
            """
            try:
                status_code = int(status.split(' ')[0])
                state['status_code'] = status_code
            except (ValueError, TypeError):  # pragma: nocover
                raise Exception(('ErrorDocumentMiddleware received an invalid '
                                 'status %s' % status))
            else:
                if (state['status_code'] / 100) not in (2, 3):
                    # Remove some headers so we can replace them later
                    # when we have the full error message and can
                    # compute the length.
                    headers = [(h, v) for (h, v) in headers
                               if h not in ('Content-Length', 'Content-Type')]
                # Save the headers in case we need to modify them.
                state['headers'] = headers
                return start_response(status, headers, exc_info)

        app_iter = self.app(environ, replacement_start_response)
        if (state['status_code'] / 100) not in (2, 3):
            req = webob.Request(environ)
            # Find the first TranslationHook in the array of hooks and use the
            # translatable_error object from it
            error = None
            for hook in self.app.hooks:
                if isinstance(hook, hooks.TranslationHook):
                    error = hook.local_error.translatable_error
                    break
            user_locale = self.best_match_language(req.accept_language)
            if (req.accept.best_match(['application/json', 'application/xml'
                                       ]) == 'application/xml'):
                try:
                    # simple check xml is valid
                    fault = etree.fromstring('\n'.join(app_iter))
                    # Add the translated error to the xml data
                    if error is not None:
                        for fault_string in fault.findall('faultstring'):
                            fault_string.text = (gettextutils.translate(
                                error, user_locale))
                    body = [
                        '<error_message>' + etree.tostring(fault) +
                        '</error_message>'
                    ]
                except etree.XMLSyntaxError as err:
                    LOG.error(_('Error parsing HTTP response: %s') % err)
                    body = [
                        '<error_message>%s' % state['status_code'] +
                        '</error_message>'
                    ]
                state['headers'].append(('Content-Type', 'application/xml'))
            else:
                try:
                    fault = json.loads('\n'.join(app_iter))
                    if error is not None and 'faultstring' in fault:
                        fault['faultstring'] = (gettextutils.translate(
                            error, user_locale))
                    body = [json.dumps({'error_message': fault})]
                except ValueError as err:
                    body = [json.dumps({'error_message': '\n'.join(app_iter)})]
                state['headers'].append(('Content-Type', 'application/json'))
            state['headers'].append(('Content-Length', str(len(body[0]))))
        else:
            body = app_iter
        return body