Skip to content

Commit fbde5f0

Browse files
authored
Merge pull request #345 from lsst-sqre/tickets/DM-47769
DM-47769: Add documentation of CaseInsensitiveFormMiddleware
2 parents 3c9b2a3 + a898c43 commit fbde5f0

File tree

2 files changed

+24
-15
lines changed

2 files changed

+24
-15
lines changed

docs/user-guide/ivoa.rst

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,29 @@ IVOA protocol support
55
The IVOA web protocols aren't entirely RESTful and have some unusual requirements that are not provided by modern web frameworks.
66
Safir provides some FastAPI support facilities to make implementing IVOA services easier.
77

8-
Query parameter case insensitivity
9-
==================================
8+
Parameter case insensitivity
9+
============================
1010

1111
Many IVOA protocols require the key of a query parameter to be case-insensitive.
1212
For example, the requests ``GET /api/foo?param=bar`` and ``GET /api/foo?PARAM=bar`` are supposed to produce identical results.
13-
Safir provides `safir.middleware.ivoa.CaseInsensitiveQueryMiddleware` to implement this protocol requirement.
13+
The same is true for parameters provided in form bodies to ``POST``.
1414

15-
Add this middleware to the FastAPI application:
15+
Safir provides two middlewares, `~safir.middleware.ivoa.CaseInsensitiveQueryMiddleware` and `~safir.middleware.ivoa.CaseInsensitiveFormMiddleware`, to implement this protocol requirement.
16+
17+
Add these middlewares to the FastAPI application:
1618

1719
.. code-block:: python
1820
19-
from safir.middleware.ivoa import CaseInsensitiveQueryMiddleware
21+
from safir.middleware.ivoa import (
22+
CaseInsensitiveFormMiddleware,
23+
CaseInsensitiveQueryMiddleware,
24+
)
2025
2126
app = FastAPI()
27+
app.add_middleware(CaseInsensitiveFormMiddleware)
2228
app.add_middleware(CaseInsensitiveQueryMiddleware)
2329
24-
In the route handlers, declare all query parameters in all lowercase.
30+
In the route handlers, declare all form and query parameters in all lowercase.
2531
For instance, for the above example queries:
2632

2733
.. code-block:: python

safir/src/safir/middleware/ivoa.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55

66
from starlette.types import ASGIApp, Receive, Scope, Send
77

8-
__all__ = ["CaseInsensitiveQueryMiddleware"]
8+
__all__ = [
9+
"CaseInsensitiveFormMiddleware",
10+
"CaseInsensitiveQueryMiddleware",
11+
]
912

1013

1114
class CaseInsensitiveQueryMiddleware:
@@ -74,13 +77,13 @@ async def __call__(
7477

7578
scope = copy(scope)
7679

77-
if scope["method"] == "POST" and self.is_form_data(scope):
78-
receive = self.wrapped_receive(receive)
80+
if scope["method"] == "POST" and self._is_form_data(scope):
81+
receive = self._wrapped_receive(receive)
7982

8083
await self._app(scope, receive, send)
8184

8285
@staticmethod
83-
def is_form_data(scope: Scope) -> bool:
86+
def _is_form_data(scope: Scope) -> bool:
8487
"""Check if the request contains form data.
8588
8689
Parameters
@@ -101,7 +104,7 @@ def is_form_data(scope: Scope) -> bool:
101104
return content_type.startswith("application/x-www-form-urlencoded")
102105

103106
@staticmethod
104-
async def get_body(receive: Receive) -> bytes:
107+
async def _get_body(receive: Receive) -> bytes:
105108
"""Read the entire request body.
106109
107110
Parameters
@@ -123,7 +126,7 @@ async def get_body(receive: Receive) -> bytes:
123126
return body
124127

125128
@staticmethod
126-
async def process_form_data(body: bytes) -> bytes:
129+
async def _process_form_data(body: bytes) -> bytes:
127130
"""Process the body, lowercasing keys of form data.
128131
129132
Parameters
@@ -142,7 +145,7 @@ async def process_form_data(body: bytes) -> bytes:
142145
processed = urlencode(lowercased)
143146
return processed.encode("utf-8")
144147

145-
def wrapped_receive(self, receive: Receive) -> Receive:
148+
def _wrapped_receive(self, receive: Receive) -> Receive:
146149
"""Wrap the receive function to process form data.
147150
148151
Parameters
@@ -166,8 +169,8 @@ async def inner() -> dict:
166169
"more_body": False,
167170
}
168171

169-
body = await self.get_body(receive)
170-
processed_body = await self.process_form_data(body)
172+
body = await self._get_body(receive)
173+
processed_body = await self._process_form_data(body)
171174
processed = True
172175
return {
173176
"type": "http.request",

0 commit comments

Comments
 (0)