forked from developmentseed/titiler
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
move middlewares to titiler.core (developmentseed#365)
- Loading branch information
1 parent
652b20d
commit 131f500
Showing
6 changed files
with
132 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
115 changes: 6 additions & 109 deletions
115
src/titiler/application/titiler/application/middleware.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,111 +1,8 @@ | ||
"""Titiler middlewares.""" | ||
|
||
import logging | ||
import re | ||
import time | ||
from typing import Optional, Set | ||
|
||
from fastapi.logger import logger | ||
|
||
from starlette.middleware.base import BaseHTTPMiddleware | ||
from starlette.requests import Request | ||
from starlette.types import ASGIApp | ||
|
||
|
||
class CacheControlMiddleware(BaseHTTPMiddleware): | ||
"""MiddleWare to add CacheControl in response headers.""" | ||
|
||
def __init__( | ||
self, | ||
app: ASGIApp, | ||
cachecontrol: Optional[str] = None, | ||
exclude_path: Optional[Set[str]] = None, | ||
) -> None: | ||
"""Init Middleware. | ||
Args: | ||
app (ASGIApp): starlette/FastAPI application. | ||
cachecontrol (str): Cache-Control string to add to the response. | ||
exclude_path (set): Set of regex expression to use to filter the path. | ||
""" | ||
super().__init__(app) | ||
self.cachecontrol = cachecontrol | ||
self.exclude_path = exclude_path or set() | ||
|
||
async def dispatch(self, request: Request, call_next): | ||
"""Add cache-control.""" | ||
response = await call_next(request) | ||
if self.cachecontrol and not response.headers.get("Cache-Control"): | ||
for path in self.exclude_path: | ||
if re.match(path, request.url.path): | ||
return response | ||
|
||
if request.method in ["HEAD", "GET"] and response.status_code < 500: | ||
response.headers["Cache-Control"] = self.cachecontrol | ||
|
||
return response | ||
|
||
|
||
class TotalTimeMiddleware(BaseHTTPMiddleware): | ||
"""MiddleWare to add Total process time in response headers.""" | ||
|
||
async def dispatch(self, request: Request, call_next): | ||
"""Add X-Process-Time.""" | ||
start_time = time.time() | ||
response = await call_next(request) | ||
process_time = time.time() - start_time | ||
timings = response.headers.get("Server-Timing") | ||
app_time = "total;dur={}".format(round(process_time * 1000, 2)) | ||
response.headers["Server-Timing"] = ( | ||
f"{timings}, {app_time}" if timings else app_time | ||
) | ||
return response | ||
|
||
|
||
class LoggerMiddleware(BaseHTTPMiddleware): | ||
"""MiddleWare to add logging.""" | ||
|
||
def __init__( | ||
self, app: ASGIApp, querystrings: bool = False, headers: bool = False, | ||
) -> None: | ||
"""Init Middleware.""" | ||
super().__init__(app) | ||
self.logger = logger | ||
logger.setLevel(logging.DEBUG) | ||
|
||
self.querystrings = querystrings | ||
self.headers = headers | ||
|
||
async def dispatch(self, request: Request, call_next): | ||
"""Add logs.""" | ||
self.logger.debug(str(request.url)) | ||
qs = dict(request.query_params) | ||
if qs and self.querystrings: | ||
self.logger.debug(qs) | ||
if self.headers: | ||
self.logger.debug(dict(request.headers)) | ||
|
||
response = await call_next(request) | ||
return response | ||
|
||
|
||
class LowerCaseQueryStringMiddleware(BaseHTTPMiddleware): | ||
"""Middleware to make URL parameters case-insensitive. | ||
taken from: https://github.com/tiangolo/fastapi/issues/826 | ||
""" | ||
|
||
async def dispatch(self, request: Request, call_next): | ||
"""dispatch request.""" | ||
|
||
self.DECODE_FORMAT = "latin-1" | ||
|
||
query_string = "" | ||
for k in request.query_params: | ||
query_string += k.lower() + "=" + request.query_params[k] + "&" | ||
|
||
query_string = query_string[:-1] | ||
request.scope["query_string"] = query_string.encode(self.DECODE_FORMAT) | ||
|
||
response = await call_next(request) | ||
return response | ||
from titiler.core.middleware import ( # noqa | ||
CacheControlMiddleware, | ||
LoggerMiddleware, | ||
LowerCaseQueryStringMiddleware, | ||
TotalTimeMiddleware, | ||
) |
4 changes: 2 additions & 2 deletions
4
...pplication/tests/test_cache_middleware.py → ...tiler/core/tests/test_cache_middleware.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...application/tests/test_case_middleware.py → ...itiler/core/tests/test_case_middleware.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
"""Titiler middlewares.""" | ||
|
||
import logging | ||
import re | ||
import time | ||
from typing import Optional, Set | ||
|
||
from fastapi.logger import logger | ||
|
||
from starlette.middleware.base import BaseHTTPMiddleware | ||
from starlette.requests import Request | ||
from starlette.types import ASGIApp | ||
|
||
|
||
class CacheControlMiddleware(BaseHTTPMiddleware): | ||
"""MiddleWare to add CacheControl in response headers.""" | ||
|
||
def __init__( | ||
self, | ||
app: ASGIApp, | ||
cachecontrol: Optional[str] = None, | ||
exclude_path: Optional[Set[str]] = None, | ||
) -> None: | ||
"""Init Middleware. | ||
Args: | ||
app (ASGIApp): starlette/FastAPI application. | ||
cachecontrol (str): Cache-Control string to add to the response. | ||
exclude_path (set): Set of regex expression to use to filter the path. | ||
""" | ||
super().__init__(app) | ||
self.cachecontrol = cachecontrol | ||
self.exclude_path = exclude_path or set() | ||
|
||
async def dispatch(self, request: Request, call_next): | ||
"""Add cache-control.""" | ||
response = await call_next(request) | ||
if self.cachecontrol and not response.headers.get("Cache-Control"): | ||
for path in self.exclude_path: | ||
if re.match(path, request.url.path): | ||
return response | ||
|
||
if request.method in ["HEAD", "GET"] and response.status_code < 500: | ||
response.headers["Cache-Control"] = self.cachecontrol | ||
|
||
return response | ||
|
||
|
||
class TotalTimeMiddleware(BaseHTTPMiddleware): | ||
"""MiddleWare to add Total process time in response headers.""" | ||
|
||
async def dispatch(self, request: Request, call_next): | ||
"""Add X-Process-Time.""" | ||
start_time = time.time() | ||
response = await call_next(request) | ||
process_time = time.time() - start_time | ||
timings = response.headers.get("Server-Timing") | ||
app_time = "total;dur={}".format(round(process_time * 1000, 2)) | ||
response.headers["Server-Timing"] = ( | ||
f"{timings}, {app_time}" if timings else app_time | ||
) | ||
return response | ||
|
||
|
||
class LoggerMiddleware(BaseHTTPMiddleware): | ||
"""MiddleWare to add logging.""" | ||
|
||
def __init__( | ||
self, app: ASGIApp, querystrings: bool = False, headers: bool = False, | ||
) -> None: | ||
"""Init Middleware.""" | ||
super().__init__(app) | ||
self.logger = logger | ||
logger.setLevel(logging.DEBUG) | ||
|
||
self.querystrings = querystrings | ||
self.headers = headers | ||
|
||
async def dispatch(self, request: Request, call_next): | ||
"""Add logs.""" | ||
self.logger.debug(str(request.url)) | ||
qs = dict(request.query_params) | ||
if qs and self.querystrings: | ||
self.logger.debug(qs) | ||
if self.headers: | ||
self.logger.debug(dict(request.headers)) | ||
|
||
response = await call_next(request) | ||
return response | ||
|
||
|
||
class LowerCaseQueryStringMiddleware(BaseHTTPMiddleware): | ||
"""Middleware to make URL parameters case-insensitive. | ||
taken from: https://github.com/tiangolo/fastapi/issues/826 | ||
""" | ||
|
||
async def dispatch(self, request: Request, call_next): | ||
"""dispatch request.""" | ||
|
||
self.DECODE_FORMAT = "latin-1" | ||
|
||
query_string = "" | ||
for k in request.query_params: | ||
query_string += k.lower() + "=" + request.query_params[k] + "&" | ||
|
||
query_string = query_string[:-1] | ||
request.scope["query_string"] = query_string.encode(self.DECODE_FORMAT) | ||
|
||
response = await call_next(request) | ||
return response |