예제 #1
0
파일: api.py 프로젝트: xuxiandi/falcon
    def __call__(self, env, start_response):
        """WSGI "app" method

        Makes instances of API callable by any WSGI server. See also PEP 333.

        Args:
            env: A WSGI environment dictionary
            start_response: A WSGI helper method for setting status and headers
                on a response.

        """

        req = Request(env)
        resp = Response()

        responder, params, na_responder = self._get_responder(
            req.path, req.method)

        try:
            responder(req, resp, **params)

        except HTTPError as ex:
            resp.status = ex.status
            if ex.headers is not None:
                resp.set_headers(ex.headers)

            if req.client_accepts('application/json'):
                resp.body = ex.json()

        #
        # Set status and headers
        #
        use_body = not helpers.should_ignore_body(resp.status, req.method)
        if use_body:
            helpers.set_content_length(resp)
            body = helpers.get_body(resp)
        else:
            # Default: return an empty body
            body = []

        # Set content type if needed
        use_content_type = (body or
                            req.method == 'HEAD' or
                            resp.status == HTTP_416)

        if use_content_type:
            media_type = self._media_type
        else:
            media_type = None

        headers = resp._wsgi_headers(media_type)

        # Return the response per the WSGI spec
        start_response(resp.status, headers)
        return body
예제 #2
0
파일: api.py 프로젝트: brandhill/falcon
    def __call__(self, env, start_response):
        """WSGI "app" method

        Makes instances of API callable by any WSGI server. See also PEP 333.

        Args:
            env: A WSGI environment dictionary
            start_response: A WSGI helper method for setting status and headers
                on a response.

        """

        req = Request(env)
        resp = Response()

        responder, params, na_responder = self._get_responder(
            req.path, req.method)

        try:
            responder(req, resp, **params)

        except HTTPError as ex:
            resp.status = ex.status
            if ex.headers is not None:
                resp.set_headers(ex.headers)

            if req.client_accepts('application/json'):
                resp.body = ex.json()

        except TypeError as ex:
            # NOTE(kgriffs): Get the stack trace up here since we can just
            # use this convenience function which graps the last raised
            # exception context.
            stack_trace = traceback.format_exc()

            # See if the method doesn't support the given route's params, to
            # support assigning multiple routes to the same resource.
            try:
                argspec = responder.wrapped_argspec
            except AttributeError:
                argspec = inspect.getargspec(responder)

            # First three args should be (self, req, resp)
            if argspec.args[0] == 'self':
                offset = 3
            else:
                offset = 2

            args_needed = set(argspec.args[offset:])
            args_given = set(params.keys())

            # Reset the response
            resp = Response()

            # Does the responder require more or fewer args than given?
            if args_needed != args_given:
                req.log_error('A responder method could not be found with the '
                              'correct arguments.')
                na_responder(req, resp)
            else:
                # Error caused by something else
                req.log_error('A responder method (on_*) raised TypeError. %s'
                              % stack_trace)
                falcon.responders.internal_server_error(req, resp)

        #
        # Set status and headers
        #
        use_body = not helpers.should_ignore_body(resp.status, req.method)
        if use_body:
            helpers.set_content_length(resp)
            body = helpers.get_body(resp)
        else:
            # Default: return an empty body
            body = []

        # Set content type if needed
        use_content_type = (body or
                            req.method == 'HEAD' or
                            resp.status == HTTP_416)

        if use_content_type:
            media_type = self._media_type
        else:
            media_type = None

        headers = resp._wsgi_headers(media_type)

        # Return the response per the WSGI spec
        start_response(resp.status, headers)
        return body
예제 #3
0
파일: api.py 프로젝트: jimmynapkins/falcon
    def __call__(self, env, start_response):
        """WSGI "app" method

        Makes instances of API callable by any WSGI server. See also PEP 333.

        Args:
            env: A WSGI environment dictionary
            start_response: A WSGI helper method for setting status and
                headers on a response.

        """

        req = Request(env)
        resp = Response()

        responder, params = self._get_responder(
            req.path, req.method)

        try:
            # NOTE(kgriffs): Using an inner try..except in order to
            # address the case when err_handler raises HTTPError.
            #
            # NOTE(kgriffs): Coverage is giving false negatives,
            # so disabled on relevant lines. All paths are tested
            # afaict.
            try:
                responder(req, resp, **params)  # pragma: no cover
            except Exception as ex:
                for err_type, err_handler in self._error_handlers:
                    if isinstance(ex, err_type):
                        err_handler(ex, req, resp, params)
                        break  # pragma: no cover

                else:
                    # PERF(kgriffs): This will propagate HTTPError to
                    # the handler below. It makes handling HTTPError
                    # less efficient, but that is OK since error cases
                    # don't need to be as fast as the happy path, and
                    # indeed, should perhaps be slower to create
                    # backpressure on clients that are issuing bad
                    # requests.
                    raise

        except HTTPError as ex:
            resp.status = ex.status
            if ex.headers is not None:
                resp.set_headers(ex.headers)

            if req.client_accepts('application/json'):
                resp.body = ex.json()

        #
        # Set status and headers
        #
        use_body = not helpers.should_ignore_body(resp.status, req.method)
        if use_body:
            helpers.set_content_length(resp)
            body = helpers.get_body(resp)
        else:
            # Default: return an empty body
            body = []

        # Set content type if needed
        use_content_type = (body or
                            req.method == 'HEAD' or
                            resp.status == HTTP_416)

        if use_content_type:
            media_type = self._media_type
        else:
            media_type = None

        headers = resp._wsgi_headers(media_type)

        # Return the response per the WSGI spec
        start_response(resp.status, headers)
        return body
예제 #4
0
    def __call__(self, env, start_response):
        """WSGI "app" method

        Makes instances of API callable by any WSGI server. See also PEP 333.

        Args:
            env: A WSGI environment dictionary
            start_response: A WSGI helper method for setting status and headers
                on a response.

        """

        req = Request(env)
        resp = Response()

        responder, params, na_responder = self._get_responder(
            req.path, req.method)

        try:
            responder(req, resp, **params)

        except HTTPError as ex:
            resp.status = ex.status
            if ex.headers is not None:
                resp.set_headers(ex.headers)

            if req.client_accepts('application/json'):
                resp.body = ex.json()

        except TypeError as ex:
            # NOTE(kgriffs): Get the stack trace up here since we can just
            # use this convenience function which graps the last raised
            # exception context.
            stack_trace = traceback.format_exc()

            # See if the method doesn't support the given route's params, to
            # support assigning multiple routes to the same resource.
            try:
                argspec = responder.wrapped_argspec
            except AttributeError:
                argspec = inspect.getargspec(responder)

            # First three args should be (self, req, resp)
            if argspec.args[0] == 'self':
                offset = 3
            else:
                offset = 2

            args_needed = set(argspec.args[offset:])
            args_given = set(params.keys())

            # Reset the response
            resp = Response()

            # Does the responder require more or fewer args than given?
            if args_needed != args_given:
                req.log_error('A responder method could not be found with the '
                              'correct arguments.')
                na_responder(req, resp)
            else:
                # Error caused by something else
                req.log_error(
                    'A responder method (on_*) raised TypeError. %s' %
                    stack_trace)
                falcon.responders.internal_server_error(req, resp)

        #
        # Set status and headers
        #
        use_body = not helpers.should_ignore_body(resp.status, req.method)
        if use_body:
            helpers.set_content_length(resp)
            body = helpers.get_body(resp)
        else:
            # Default: return an empty body
            body = []

        # Set content type if needed
        use_content_type = (body or req.method == 'HEAD'
                            or resp.status == HTTP_416)

        if use_content_type:
            media_type = self._media_type
        else:
            media_type = None

        headers = resp._wsgi_headers(media_type)

        # Return the response per the WSGI spec
        start_response(resp.status, headers)
        return body
예제 #5
0
파일: api.py 프로젝트: warsaw/falcon
    def __call__(self, env, start_response):
        """WSGI `app` method.

        Makes instances of API callable from a WSGI server. May be used to
        host an API or called directly in order to simulate requests when
        testing the API.

        See also PEP 3333.

        Args:
            env (dict): A WSGI environment dictionary
            start_response (callable): A WSGI helper function for setting
                status and headers on a response.

        """

        req = self._request_type(env)
        resp = self._response_type()

        responder, params, resource = self._get_responder(req.path, req.method)

        try:
            # NOTE(kgriffs): Using an inner try..except in order to
            # address the case when err_handler raises HTTPError.
            #
            # NOTE(kgriffs): Coverage is giving false negatives,
            # so disabled on relevant lines. All paths are tested
            # afaict.
            try:
                responder(req, resp, **params)  # pragma: no cover
            except Exception as ex:
                for err_type, err_handler in self._error_handlers:
                    if isinstance(ex, err_type):
                        err_handler(ex, req, resp, params)
                        self._call_after_hooks(req, resp, resource)
                        break  # pragma: no cover

                else:
                    # PERF(kgriffs): This will propagate HTTPError to
                    # the handler below. It makes handling HTTPError
                    # less efficient, but that is OK since error cases
                    # don't need to be as fast as the happy path, and
                    # indeed, should perhaps be slower to create
                    # backpressure on clients that are issuing bad
                    # requests.
                    raise

        except HTTPError as ex:
            helpers.compose_error_response(req, resp, ex)
            self._call_after_hooks(req, resp, resource)

        #
        # Set status and headers
        #
        use_body = not helpers.should_ignore_body(resp.status, req.method)
        if use_body:
            helpers.set_content_length(resp)
            body = helpers.get_body(resp, env.get('wsgi.file_wrapper'))
        else:
            # Default: return an empty body
            body = []

        # Set content type if needed
        use_content_type = (body or req.method == 'HEAD'
                            or resp.status == HTTP_416)

        if use_content_type:
            media_type = self._media_type
        else:
            media_type = None

        headers = resp._wsgi_headers(media_type)

        # Return the response per the WSGI spec
        start_response(resp.status, headers)
        return body
예제 #6
0
파일: api.py 프로젝트: jasimmk/falcon
    def __call__(self, env, start_response):
        """WSGI `app` method.

        Makes instances of API callable from a WSGI server. May be used to
        host an API or called directly in order to simulate requests when
        testing the API.

        See also PEP 3333.

        Args:
            env (dict): A WSGI environment dictionary
            start_response (callable): A WSGI helper function for setting
                status and headers on a response.

        """

        req = self._request_type(env)
        resp = self._response_type()
        resource = None

        try:
            # NOTE(warsaw): Moved this to inside the try except because it's
            # possible when using object-based traversal for _get_responder()
            # to fail.  An example is a case where an object does not have the
            # requested next-hop child resource.  In that case, the object
            # being asked to dispatch to its child will raise an HTTP
            # exception signalling the problem, e.g. a 404.
            responder, params, resource = self._get_responder(req)
            # NOTE(kgriffs): Using an inner try..except in order to
            # address the case when err_handler raises HTTPError.
            #
            # NOTE(kgriffs): Coverage is giving false negatives,
            # so disabled on relevant lines. All paths are tested
            # afaict.
            try:
                responder(req, resp, **params)  # pragma: no cover
            except Exception as ex:
                for err_type, err_handler in self._error_handlers:
                    if isinstance(ex, err_type):
                        err_handler(ex, req, resp, params)
                        self._call_after_hooks(req, resp, resource)
                        break  # pragma: no cover

                else:
                    # PERF(kgriffs): This will propagate HTTPError to
                    # the handler below. It makes handling HTTPError
                    # less efficient, but that is OK since error cases
                    # don't need to be as fast as the happy path, and
                    # indeed, should perhaps be slower to create
                    # backpressure on clients that are issuing bad
                    # requests.
                    raise

        except HTTPError as ex:
            helpers.compose_error_response(req, resp, ex)
            self._call_after_hooks(req, resp, resource)

        #
        # Set status and headers
        #
        use_body = not helpers.should_ignore_body(resp.status, req.method)
        if use_body:
            helpers.set_content_length(resp)
            body = helpers.get_body(resp, env.get("wsgi.file_wrapper"))
        else:
            # Default: return an empty body
            body = []

        # Set content type if needed
        use_content_type = body or req.method == "HEAD" or resp.status == HTTP_416

        if use_content_type:
            media_type = self._media_type
        else:
            media_type = None

        headers = resp._wsgi_headers(media_type)

        # Return the response per the WSGI spec
        start_response(resp.status, headers)
        return body
예제 #7
0
파일: api.py 프로젝트: JinsongBian/falcon
    def __call__(self, env, start_response):
        """WSGI `app` method.

        Makes instances of API callable from a WSGI server. May be used to
        host an API or called directly in order to simulate requests when
        testing the API.

        See also PEP 3333.

        Args:
            env (dict): A WSGI environment dictionary
            start_response (callable): A WSGI helper function for setting
                status and headers on a response.

        """

        req = self._request_type(env)
        resp = self._response_type()

        responder, params = self._get_responder(
            req.path, req.method)

        try:
            # NOTE(kgriffs): Using an inner try..except in order to
            # address the case when err_handler raises HTTPError.
            #
            # NOTE(kgriffs): Coverage is giving false negatives,
            # so disabled on relevant lines. All paths are tested
            # afaict.
            try:
                responder(req, resp, **params)  # pragma: no cover
            except Exception as ex:
                for err_type, err_handler in self._error_handlers:
                    if isinstance(ex, err_type):
                        err_handler(ex, req, resp, params)
                        break  # pragma: no cover

                else:
                    # PERF(kgriffs): This will propagate HTTPError to
                    # the handler below. It makes handling HTTPError
                    # less efficient, but that is OK since error cases
                    # don't need to be as fast as the happy path, and
                    # indeed, should perhaps be slower to create
                    # backpressure on clients that are issuing bad
                    # requests.
                    raise

        except HTTPError as ex:
            helpers.compose_error_response(req, resp, ex)

        #
        # Set status and headers
        #
        use_body = not helpers.should_ignore_body(resp.status, req.method)
        if use_body:
            helpers.set_content_length(resp)
            body = helpers.get_body(resp, env.get('wsgi.file_wrapper'))
        else:
            # Default: return an empty body
            body = []

        # Set content type if needed
        use_content_type = (body or
                            req.method == 'HEAD' or
                            resp.status == HTTP_416)

        if use_content_type:
            media_type = self._media_type
        else:
            media_type = None

        headers = resp._wsgi_headers(media_type)

        # Return the response per the WSGI spec
        start_response(resp.status, headers)
        return body
예제 #8
0
파일: api.py 프로젝트: jaypipes/falcon
    def __call__(self, env, start_response):
        """WSGI "app" method

        Makes instances of API callable by any WSGI server. See also PEP 333.

        Args:
            env: A WSGI environment dictionary
            start_response: A WSGI helper method for setting status and
                headers on a response.

        """

        req = Request(env)
        resp = Response()

        responder, params = self._get_responder(
            req.path, req.method)

        try:
            # NOTE(kgriffs): Using an inner try..except in order to
            # address the case when err_handler raises HTTPError.
            #
            # NOTE(kgriffs): Coverage is giving false negatives,
            # so disabled on relevant lines. All paths are tested
            # afaict.
            try:
                responder(req, resp, **params)  # pragma: no cover
            except Exception as ex:
                for err_type, err_handler in self._error_handlers:
                    if isinstance(ex, err_type):
                        err_handler(ex, req, resp, params)
                        break  # pragma: no cover

                else:
                    # PERF(kgriffs): This will propagate HTTPError to
                    # the handler below. It makes handling HTTPError
                    # less efficient, but that is OK since error cases
                    # don't need to be as fast as the happy path, and
                    # indeed, should perhaps be slower to create
                    # backpressure on clients that are issuing bad
                    # requests.
                    raise

        except HTTPError as ex:
            resp.status = ex.status
            if ex.headers is not None:
                resp.set_headers(ex.headers)

            if req.client_accepts('application/json'):
                resp.body = ex.json()

        #
        # Set status and headers
        #
        use_body = not helpers.should_ignore_body(resp.status, req.method)
        if use_body:
            helpers.set_content_length(resp)
            body = helpers.get_body(resp)
        else:
            # Default: return an empty body
            body = []

        # Set content type if needed
        use_content_type = (body or
                            req.method == 'HEAD' or
                            resp.status == HTTP_416)

        if use_content_type:
            media_type = self._media_type
        else:
            media_type = None

        headers = resp._wsgi_headers(media_type)

        # Return the response per the WSGI spec
        start_response(resp.status, headers)
        return body