-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Override routes for patching pygeoapi responses
- Loading branch information
1 parent
02f3358
commit a5bd3d8
Showing
5 changed files
with
130 additions
and
6 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""API package for patched pygeoapi.""" |
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,6 @@ | ||
"""Processes patched module.""" | ||
|
||
|
||
def patch_response(response): | ||
"""Patch pygeoapi response.""" | ||
return response |
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,81 @@ | ||
"""Starlette application override module.""" | ||
|
||
import asyncio | ||
from typing import Callable | ||
from typing import Union | ||
|
||
from pygeoapi.starlette_app import api_ as geoapi | ||
from starlette.requests import Request | ||
from starlette.responses import HTMLResponse | ||
from starlette.responses import JSONResponse | ||
from starlette.responses import Response | ||
|
||
|
||
def call_api_threadsafe( | ||
loop: asyncio.AbstractEventLoop, api_call: Callable, *args | ||
) -> tuple: | ||
"""Call api in a safe thread. | ||
The api call needs a running loop. This method is meant to be called | ||
from a thread that has no loop running. | ||
:param loop: The loop to use. | ||
:param api_call: The API method to call. | ||
:param args: Arguments to pass to the API method. | ||
:returns: The api call result tuple. | ||
""" | ||
asyncio.set_event_loop(loop) | ||
return api_call(*args) | ||
|
||
|
||
async def get_response( | ||
api_call, | ||
*args, | ||
) -> Union[Response, JSONResponse, HTMLResponse]: | ||
"""Creates a Starlette Response object and updates matching headers. | ||
Runs the core api handler in a separate thread in order to avoid | ||
blocking the main event loop. | ||
:param result: The result of the API call. | ||
This should be a tuple of (headers, status, content). | ||
:returns: A Response instance. | ||
""" | ||
loop = asyncio.get_running_loop() | ||
result = await loop.run_in_executor( | ||
None, call_api_threadsafe, loop, api_call, *args | ||
) | ||
|
||
headers, status, content = result | ||
if headers["Content-Type"] == "text/html": | ||
response = HTMLResponse(content=content, status_code=status) | ||
else: | ||
if isinstance(content, dict): | ||
response = JSONResponse(content, status_code=status) | ||
else: | ||
response = Response(content, status_code=status) | ||
|
||
if headers is not None: | ||
response.headers.update(headers) | ||
return response | ||
|
||
|
||
async def patched_get_job_result(request: Request, job_id=None): | ||
"""OGC API - Processes job result endpoint. | ||
:param request: Starlette Request instance | ||
:param job_id: job identifier | ||
:returns: HTTP response | ||
""" | ||
if "job_id" in request.path_params: | ||
job_id = request.path_params["job_id"] | ||
|
||
response = await get_response(geoapi.get_job_result, request, job_id) | ||
|
||
from app.pygeoapi.api.processes import patch_response | ||
|
||
patched_response = patch_response(response=response) | ||
|
||
return patched_response |
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,12 @@ | ||
"""Utilities for pygeoapi module.""" | ||
|
||
from starlette.routing import Route | ||
|
||
from app.pygeoapi.starlette_app import patched_get_job_result | ||
|
||
|
||
def patch_route(route: Route) -> Route: | ||
"""Patch route behavior.""" | ||
if route.path == "/jobs/{job_id}/results": | ||
route = Route("/jobs/{job_id}/results", patched_get_job_result) | ||
return route |