def test_empty_requests_dropped(self, empty_body, endpoint,
                                    endpoint_exists):
        # type: (bool, str, bool) -> None
        """Test that empty requests are dropped before routing

        Note that content_length is None if not explicitly set,
        so HEAD, GET, etc. requests are fine.
        """
        client = testing.TestClient(API(middleware=[m.EmptyRequestDropper()]))

        # We have to forge the content-length header, because if it is
        # made automatically for our empty body, we won't get to the check
        # of the body contents.
        heads = {"Content-Length": str("20")} if empty_body else {}
        body = "" if empty_body else None

        res = client.simulate_get(endpoint, body=body,
                                  headers=heads)  # type: testing.Result

        if empty_body:
            assert res.status == status_codes.HTTP_BAD_REQUEST
        else:
            if endpoint_exists:
                assert bool(
                    200 <= res.status_code < 300
                    or res.status_code == status_codes.HTTP_METHOD_NOT_ALLOWED)
            else:
                assert res.status == status_codes.HTTP_NOT_FOUND
class TestEmptyRequestDropper:
    """Tests for the empty request dropper"""

    dropper = mid.EmptyRequestDropper()

    @pytest.mark.parametrize('content_length', [None, 0])
    def test_ignore_when_no_content_length(self, content_length):
        # type: (Optional[int]) -> None
        """Test that we drop out with no content_length"""
        req = mock.Mock(content_length=content_length, )

        # noinspection PyTypeChecker
        self.dropper.process_request(req, 'foo')

        # Assert we didn't go past the first return
        req.stream.read.assert_not_called()

    @pytest.mark.parametrize('read', ['foo', ''])
    def test_raise_on_empty_body(self, read):
        # type: (str) -> None
        """Test that we raise if we get an empty body"""
        req = mock.Mock(content_length=10, context={})
        req.stream.read.return_value = read

        if not read:
            with pytest.raises(errors.HTTPBadRequest):
                # noinspection PyTypeChecker
                self.dropper.process_request(req, 'foo')
        else:
            # noinspection PyTypeChecker
            self.dropper.process_request(req, 'foo')
def hydrated_client_multiple_middleware():
    """Create a server for testing, with all included middlewares"""

    data_store = DataStore()

    class PhilosopherResource:

        schema = Philosopher()

        def on_get(self, req, resp, phil_id):
            """Get a philosopher"""
            req.context["result"] = data_store.get(phil_id)

    class PhilosopherCollection:

        schema = Philosopher()

        def on_post(self, req, resp):
            req.context["result"] = data_store.insert(req.context["json"])

    app = API(middleware=[
        m.Marshmallow(),
        m.JSONEnforcer(),
        m.EmptyRequestDropper()
    ])

    app.add_route("/philosophers", PhilosopherCollection())
    app.add_route("/philosophers/{phil_id}", PhilosopherResource())

    yield testing.TestClient(app)

    data_store.clear()
def hydrated_client_multiple_middleware():
    """A Falcon API with an endpoint for testing Marshmallow, with all
    included middlewares registered."""
    data_store = DataStore()

    class PhilosopherResource:

        schema = Philosopher()

        def on_get(self, req, resp, phil_id):
            """Get a philosopher"""
            req.context['result'] = data_store.get(phil_id)

    class PhilosopherCollection:

        schema = Philosopher()

        def on_post(self, req, resp):
            req.context['result'] = data_store.insert(req.context['json'])

    app = API(middleware=[
        m.Marshmallow(),
        m.JSONEnforcer(),
        m.EmptyRequestDropper()])

    app.add_route('/philosophers', PhilosopherCollection())
    app.add_route('/philosophers/{phil_id}', PhilosopherResource())

    yield testing.TestClient(app)

    data_store.clear()