Files
connexion/tests/test_middleware.py
Robbe Sneyders 14e02fa97f Add interface to add WSGI middleware (#1814)
As discussed in #1807.

Allowing the injection of WSGI middleware can enable easier migration
from Connexion 2 to Connexion 3. The use cases are limited though, as
this will only work for middleware that can work at the end of the
middleware stack.
2023-11-19 23:46:21 +01:00

112 lines
3.4 KiB
Python

import typing as t
from unittest.mock import Mock
import pytest
from connexion import FlaskApp
from connexion.middleware import ConnexionMiddleware, MiddlewarePosition
from connexion.middleware.swagger_ui import SwaggerUIMiddleware
from connexion.types import Environ, ResponseStream, StartResponse, WSGIApp
from starlette.datastructures import MutableHeaders
from conftest import build_app_from_fixture
class TestMiddleware:
"""Middleware to check if operation is accessible on scope."""
__test__ = False
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
operation_id = scope["extensions"]["connexion_routing"]["operation_id"]
async def patched_send(message):
if message["type"] != "http.response.start":
await send(message)
return
message.setdefault("headers", [])
headers = MutableHeaders(scope=message)
headers["operation_id"] = operation_id
await send(message)
await self.app(scope, receive, patched_send)
@pytest.fixture(scope="session")
def middleware_app(spec, app_class):
middlewares = ConnexionMiddleware.default_middlewares + [TestMiddleware]
return build_app_from_fixture(
"simple", app_class=app_class, spec_file=spec, middlewares=middlewares
)
def test_routing_middleware(middleware_app):
app_client = middleware_app.test_client()
response = app_client.post("/v1.0/greeting/robbe")
assert (
response.headers.get("operation_id") == "fakeapi.hello.post_greeting"
), response.status_code
def test_add_middleware(spec, app_class):
"""Test adding middleware via the `add_middleware` method."""
app = build_app_from_fixture("simple", app_class=app_class, spec_file=spec)
app.add_middleware(TestMiddleware)
app_client = app.test_client()
response = app_client.post("/v1.0/greeting/robbe")
assert (
response.headers.get("operation_id") == "fakeapi.hello.post_greeting"
), response.status_code
def test_position(spec, app_class):
"""Test adding middleware via the `add_middleware` method."""
middlewares = [
middleware
for middleware in ConnexionMiddleware.default_middlewares
if middleware != SwaggerUIMiddleware
]
app = build_app_from_fixture(
"simple", app_class=app_class, spec_file=spec, middlewares=middlewares
)
with pytest.raises(ValueError) as exc_info:
app.add_middleware(TestMiddleware, position=MiddlewarePosition.BEFORE_SWAGGER)
assert (
exc_info.value.args[0]
== f"Could not insert middleware at position BEFORE_SWAGGER. "
f"Please make sure you have a {SwaggerUIMiddleware} in your stack."
)
def test_add_wsgi_middleware(spec):
app: FlaskApp = build_app_from_fixture("simple", app_class=FlaskApp, spec_file=spec)
class WSGIMiddleware:
def __init__(self, app_: WSGIApp, mock_counter):
self.next_app = app_
self.mock_counter = mock_counter
def __call__(
self, environ: Environ, start_response: StartResponse
) -> ResponseStream:
self.mock_counter()
return self.next_app(environ, start_response)
mock = Mock()
app.add_wsgi_middleware(WSGIMiddleware, mock_counter=mock)
app_client = app.test_client()
app_client.post("/v1.0/greeting/robbe")
mock.assert_called_once()