예제 #1
0
def _dispatch_request(req, env, env_error):
    resp = []

    # fixup env.abs_href if `[trac] base_url` was not specified
    if env and not env.abs_href.base:
        env.abs_href = req.abs_href

    try:
        if not env and env_error:
            raise HTTPInternalError(env_error)
        try:
            dispatcher = RequestDispatcher(env)
            dispatcher.dispatch(req)
        except RequestDone, req_done:
            resp = req_done.iterable
        resp = resp or req._response or []
예제 #2
0
def _dispatch_request(req, env, env_error):
    resp = []

    # fixup env.abs_href if `[trac] base_url` was not specified
    if env and not env.abs_href.base:
        env.abs_href = req.abs_href

    try:
        if not env and env_error:
            raise HTTPInternalError(env_error)
        try:
            dispatcher = RequestDispatcher(env)
            dispatcher.dispatch(req)
        except RequestDone as req_done:
            resp = req_done.iterable
        resp = resp or req._response or []
    except HTTPException as e:
        _send_user_error(req, env, e)
    except Exception:
        send_internal_error(env, req, sys.exc_info())
    return resp
예제 #3
0
    def dispatch(self, req):
        """Find a registered handler that matches the request and let
        it process it.

        In addition, this method initializes the data dictionary
        passed to the the template and adds the web site chrome.
        """
        self.log.debug('Dispatching %r', req)
        chrome = Chrome(self.env)

        # Setup request callbacks for lazily-evaluated properties
        req.callbacks.update({
            'authname': self.authenticate,
            'chrome': chrome.prepare_request,
            'perm': self._get_perm,
            'session': self._get_session,
            'locale': self._get_locale,
            'lc_time': self._get_lc_time,
            'tz': self._get_timezone,
            'form_token': self._get_form_token,
            'use_xsendfile': self._get_use_xsendfile,
            'xsendfile_header': self._get_xsendfile_header,
        })

        try:
            try:
                # Select the component that should handle the request
                chosen_handler = None
                try:
                    for handler in self._request_handlers.values():
                        if handler.match_request(req):
                            chosen_handler = handler
                            break
                    if not chosen_handler and \
                            (not req.path_info or req.path_info == '/'):
                        chosen_handler = self._get_valid_default_handler(req)
                    # pre-process any incoming request, whether a handler
                    # was found or not
                    self.log.debug("Chosen handler is %s", chosen_handler)
                    chosen_handler = \
                        self._pre_process_request(req, chosen_handler)
                except TracError as e:
                    raise HTTPInternalError(e)
                if not chosen_handler:
                    if req.path_info.endswith('/'):
                        # Strip trailing / and redirect
                        target = unicode_quote(req.path_info.rstrip('/'))
                        if req.query_string:
                            target += '?' + req.query_string
                        req.redirect(req.href + target, permanent=True)
                    raise HTTPNotFound('No handler matched request to %s',
                                       req.path_info)

                req.callbacks['chrome'] = partial(chrome.prepare_request,
                                                  handler=chosen_handler)

                # Protect against CSRF attacks: we validate the form token
                # for all POST requests with a content-type corresponding
                # to form submissions
                if req.method == 'POST':
                    ctype = req.get_header('Content-Type')
                    if ctype:
                        ctype, options = cgi.parse_header(ctype)
                    if ctype in ('application/x-www-form-urlencoded',
                                 'multipart/form-data') and \
                            req.args.get('__FORM_TOKEN') != req.form_token:
                        if self.env.secure_cookies and req.scheme == 'http':
                            msg = _('Secure cookies are enabled, you must '
                                    'use https to submit forms.')
                        else:
                            msg = _('Do you have cookies enabled?')
                        raise HTTPBadRequest(
                            _('Missing or invalid form token.'
                              ' %(msg)s',
                              msg=msg))

                # Process the request and render the template
                resp = chosen_handler.process_request(req)
                if resp:
                    if len(resp) == 2:  # old Clearsilver template and HDF data
                        self.log.error(
                            "Clearsilver template are no longer "
                            "supported (%s)", resp[0])
                        raise TracError(
                            _("Clearsilver templates are no longer supported, "
                              "please contact your Trac administrator."))
                    # Genshi
                    template, data, content_type, method = \
                        self._post_process_request(req, *resp)
                    if 'hdfdump' in req.args:
                        req.perm.require('TRAC_ADMIN')
                        # debugging helper - no need to render first
                        out = io.BytesIO()
                        pprint(data, out)
                        req.send(out.getvalue(), 'text/plain')
                    self.log.debug("Rendering response from handler")
                    output = chrome.render_template(
                        req,
                        template,
                        data,
                        content_type,
                        method=method,
                        iterable=chrome.use_chunked_encoding)
                    req.send(output, content_type or 'text/html')
                else:
                    self.log.debug("Empty or no response from handler. "
                                   "Entering post_process_request.")
                    self._post_process_request(req)
            except RequestDone:
                raise
            except:
                # post-process the request in case of errors
                err = sys.exc_info()
                try:
                    self._post_process_request(req)
                except RequestDone:
                    raise
                except Exception as e:
                    self.log.error(
                        "Exception caught while post-processing"
                        " request: %s", exception_to_unicode(e,
                                                             traceback=True))
                raise err[0], err[1], err[2]
        except PermissionError as e:
            raise HTTPForbidden(e)
        except ResourceNotFound as e:
            raise HTTPNotFound(e)
        except TracError as e:
            raise HTTPInternalError(e)
예제 #4
0
 def test_exception_with_fragment_as_argument(self):
     e1 = Exception(tag(tag.b('the message')))
     e2 = HTTPInternalError(e1)
     self.assertEqual('500 Internal Server Error (<b>the message</b>)',
                      unicode(e2))
예제 #5
0
 def test_exception_with_string_as_argument(self):
     e1 = Exception('the message')
     e2 = HTTPInternalError(e1)
     self.assertEqual('500 Internal Server Error (the message)',
                      unicode(e2))
예제 #6
0
 def test_tracerror_with_fragment_as_argument(self):
     e1 = TracError(tag(tag.b('the message')))
     e2 = HTTPInternalError(e1)
     self.assertEqual('500 Trac Error (<b>the message</b>)', unicode(e2))
예제 #7
0
 def test_tracerror_with_string_as_argument(self):
     e1 = TracError('the message')
     e2 = HTTPInternalError(e1)
     self.assertEqual('500 Trac Error (the message)', unicode(e2))
예제 #8
0
                except Exception, e:
                    self.log.error(
                        "Exception caught while post-processing"
                        " request: %s", exception_to_unicode(e,
                                                             traceback=True))
                raise err[0], err[1], err[2]
        except PermissionError, e:
            raise HTTPForbidden(e)
        except ResourceNotFound, e:
            raise HTTPNotFound(e)
        except NotImplementedError, e:
            tb = traceback.extract_tb(err[2])[-1]
            self.log.warning("%s caught from %s:%d in %s: %s",
                             e.__class__.__name__, tb[0], tb[1], tb[2],
                             to_unicode(e) or "(no message)")
            raise HTTPInternalError(TracNotImplementedError(e))
        except TracError, e:
            raise HTTPInternalError(e)

    # Internal methods

    def _get_perm(self, req):
        if isinstance(req.session, FakeSession):
            return FakePerm()
        else:
            return PermissionCache(self.env, req.authname)

    def _get_session(self, req):
        try:
            return Session(self.env, req)
        except TracError, e: