Esempio n. 1
0
    def __call__(self, environ, start_response):
        """
            This is called by each request to the server.
            This MUST return a valid HTTP response under all circumstances.
        """
        if isinstance(environ, types.DictType):
            req = WSGIRequest(environ)
        else:
            req = environ

        # main exception handler to ensure client gets valid response.
        # defer any mutation of the request object (incl. writes to the client)
        # until you're sure all exception prone activities have been performed
        # successfully (aka: "basic exception guarantee")
        code = None
        final_content = ""
        endpoint = None
        try:
            # allow '_method' query arg to overide method
            method = req.method
            if '_method' in req.arguments:
                method = req.arguments['_method'][0].upper()
                del req.arguments['_method']

            # find appropriate endpoint
            reqline = method + urllib.unquote(req.path)
            match = None
            for endpoint in self._endpoints:
                match = endpoint.match(reqline)
                if match:
                    break

            if not match:
                # TODO: Handle HTTPException in new world exceptions
                raise HTTPException(404)
                #
                # Fallback app is untested with WSGI/EVENTLET
                # FIXTHIS!!
                #
                # if self._fallbackapp:
                    # _log.debug("falling through: %s %s" % (method, req.uri))
                    # return self._fallbackapp(event_req, start_response)
                # else:
                    # raise HTTPException(404)

            # convert all values in req.arguments from lists to scalars,
            # then combine with path args.
            arguments = dict((k, v[0]) for k, v in req.arguments.iteritems()\
                if isinstance(v, list) and len(v) > 0)
            inargs = dict(match.groupdict(), **arguments)

            # compile positional arguments
            args = []
            for arg in endpoint.sequential:
                args.append(arg.argspec(req, inargs))

            # compile keyword arguments
            kwargs = {}
            for argname, arg in endpoint.named.iteritems():
                r = arg.argspec(req, inargs)
                if r != None:
                    kwargs[argname] = r

            # invoke the service endpoint
            result = endpoint(*args, **kwargs)

            # TODO make sure this works with unicode
            _log.debug(_gen_trace_str(endpoint.function, args, kwargs, result))

            if isinstance(endpoint.renderer, RequestAwareRenderer):
                r = endpoint.renderer(req, result)
            else:
                r = endpoint.renderer(result)
            content, content_type, code, extra_headers = \
                r.content, r.content_type, r.http_status, r.headers

        except (Exception), e:
            error_response = None
            logged_trace = False
            #
            # Try to use this endpoint's exception handler(s)
            # If the raised exception is not mapped in this endpoint, or
            # this endpoint raises an exception when trying to handle,
            # we will then try to the default handler, and ultimately
            # fallback to the self._options.default_error_response, which
            # is guaranteed to be valid at app initialization.
            #
            if endpoint and endpoint.exceptions:
                try:
                    error_response = handle_exception(
                        e, endpoint.exceptions,
                        default_handler=self._options.default_error_handler
                    )
                except (Exception), e:
                    # TODO this may log too loudly
                    _log.exception(
                        "Endpoint %s failed to handle exception" % endpoint.name
                    )
                    logged_trace = True
Esempio n. 2
0
    def __call__(self, environ, start_response):
        '''
            This is called by each request to the server.
            This MUST return a valid HTTP response under all circumstances.

            We expect environ to be a valid wgsi python dictionary.
        '''
        req = WSGIRequest(environ)

        #        if isinstance(environ, types.DictType):
        #            req = WSGIRequest(environ)
        #        else:
        #            req = environ

        # main exception handler to ensure client gets valid response.
        # defer any mutation of the request object (incl. writes to the client)
        # until you're sure all exception prone activities have been performed
        # successfully (aka: "basic exception guarantee")
        code = None
        final_content = ""
        endpoint = None
        try:
            # allow '_method' query arg to override method
            method = req.method
            if '_method' in req.arguments:
                method = req.arguments['_method'][0].upper()
                del req.arguments['_method']

            # find appropriate endpoint
            reqline = method + urllib.unquote(req.path)
            match = None
            for endpoint in self._endpoints:
                match = endpoint.match(reqline)
                if match:
                    break

            if not match:
                if self._fallbackapp:
                    _log.debug("Using fallback app for request: (%s) (%s)" % \
                               (method, req.uri))
                    # Since recreating a stringio from the request body can be
                    # expensive, we only want to do this if we fallback.
                    environ['wsgi.input'] = StringIO.StringIO(req.body)
                    return self._fallbackapp(environ, start_response)
                else:
                    raise HTTPException(404)

            # convert all values in req.arguments from lists to scalars,
            # then combine with path args.
            arguments = dict((k, v[0]) for k, v in req.arguments.iteritems()\
                if isinstance(v, list) and len(v) > 0)
            inargs = dict(match.groupdict(), **arguments)

            # compile positional arguments
            args = []
            for arg in endpoint.sequential:
                args.append(arg.argspec(req, inargs))

            # compile keyword arguments
            kwargs = {}
            for argname, arg in endpoint.named.iteritems():
                r = arg.argspec(req, inargs)
                if r != None:
                    kwargs[argname] = r

            # invoke the service endpoint
            result = endpoint(*args, **kwargs)

            # TODO make sure this works with unicode
            _log.debug(_gen_trace_str(endpoint.function, args, kwargs, result))

            if isinstance(endpoint.renderer, RequestAwareRenderer):
                r = endpoint.renderer(req, result)
            else:
                r = endpoint.renderer(result)
            content, content_type, code, extra_headers = \
                r.content, r.content_type, r.http_status, r.headers

        except (Exception), e:
            error_response = None
            logged_trace = False
            #
            # Try to use this endpoint's exception handler(s)
            # If the raised exception is not mapped in this endpoint, or
            # this endpoint raises an exception when trying to handle,
            # we will then try to the default handler, and ultimately
            # fallback to the self._options.default_error_response, which
            # is guaranteed to be valid at app initialization.
            #
            if endpoint and endpoint.exceptions:
                try:
                    error_response = handle_exception(
                        e,
                        endpoint.exceptions,
                        default_handler=self._options.default_error_handler)
                    if not error_response:
                        raise
                except (Exception), e:
                    _log.exception("Endpoint (%s) failed to handle exception" %
                                   endpoint.name)
                    logged_trace = True
Esempio n. 3
0
    def __call__(self, environ, start_response):
        '''
            This is called by each request to the server.
            This MUST return a valid HTTP response under all circumstances.

            We expect environ to be a valid wgsi python dictionary.
        '''
        req = WSGIRequest(environ)

#        if isinstance(environ, types.DictType):
#            req = WSGIRequest(environ)
#        else:
#            req = environ

        # main exception handler to ensure client gets valid response.
        # defer any mutation of the request object (incl. writes to the client)
        # until you're sure all exception prone activities have been performed
        # successfully (aka: "basic exception guarantee")
        code = None
        final_content = ""
        endpoint = None
        try:
            # allow '_method' query arg to override method
            method = req.method
            if '_method' in req.arguments:
                method = req.arguments['_method'][0].upper()
                del req.arguments['_method']

            # find appropriate endpoint
            reqline = method + urllib.unquote(req.path)
            match = None
            for endpoint in self._endpoints:
                match = endpoint.match(reqline)
                if match:
                    break

            if not match:
                if self._fallbackapp:
                    _log.debug("Using fallback app for request: (%s) (%s)" % \
                               (method, req.uri))
                    # Since recreating a stringio from the request body can be
                    # expensive, we only want to do this if we fallback.
                    environ['wsgi.input'] = StringIO.StringIO(req.body)
                    return self._fallbackapp(environ, start_response)
                else:
                    raise HTTPException(404)

            # convert all values in req.arguments from lists to scalars,
            # then combine with path args.
            arguments = dict((k, v[0]) for k, v in req.arguments.iteritems()\
                if isinstance(v, list) and len(v) > 0)
            inargs = dict(match.groupdict(), **arguments)

            # compile positional arguments
            args = []
            for arg in endpoint.sequential:
                args.append(arg.argspec(req, inargs))

            # compile keyword arguments
            kwargs = {}
            for argname, arg in endpoint.named.iteritems():
                r = arg.argspec(req, inargs)
                if r != None:
                    kwargs[argname] = r

            # invoke the service endpoint
            result = endpoint(*args, **kwargs)

            # TODO make sure this works with unicode
            # This is real, super annoying, lets only use if in debug mode
            if self._debug:
                _log.debug(_gen_trace_str(
                    endpoint.function, args, kwargs, result))

            if isinstance(endpoint.renderer, RequestAwareRenderer):
                r = endpoint.renderer(req, result)
            else:
                r = endpoint.renderer(result)
            content, content_type, code, extra_headers = \
                r.content, r.content_type, r.http_status, r.headers

        except (Exception), e:
            error_response = None
            logged_trace = False
            #
            # Try to use this endpoint's exception handler(s)
            # If the raised exception is not mapped in this endpoint, or
            # this endpoint raises an exception when trying to handle,
            # we will then try to the default handler, and ultimately
            # fallback to the self._options.default_error_response, which
            # is guaranteed to be valid at app initialization.
            #
            if endpoint and endpoint.exceptions:
                try:
                    error_response = handle_exception(
                        e, endpoint.exceptions,
                        default_handler=self._options.default_error_handler
                    )
                    if not error_response:
                        raise
                except (Exception), e:
                    _log.exception(
                        "Endpoint (%s) failed to handle exception" % endpoint.name
                    )
                    logged_trace = True