1
1
"""stac-fastapi HTML middlewares."""
2
2
3
+ from __future__ import annotations
4
+
3
5
import json
4
6
import re
5
7
from dataclasses import dataclass , field
6
- from typing import Any , List , Optional
8
+ from typing import TYPE_CHECKING , Any , List , Optional
7
9
8
10
import jinja2
9
- from stac_pydantic .shared import MimeTypes
10
11
from starlette .datastructures import MutableHeaders
11
12
from starlette .requests import Request
12
13
from starlette .templating import Jinja2Templates
13
- from starlette .types import ASGIApp , Message , Receive , Scope , Send
14
+
15
+ if TYPE_CHECKING :
16
+ from starlette .types import ASGIApp , Message , Receive , Scope , Send
14
17
15
18
jinja2_env = jinja2 .Environment (
16
19
loader = jinja2 .ChoiceLoader (
@@ -46,6 +49,9 @@ def preferred_encoding(accept: str) -> Optional[List[str]]:
46
49
"""
47
50
accept_values = {}
48
51
for m in accept .replace (" " , "" ).split ("," ):
52
+ if not m :
53
+ continue
54
+
49
55
values = m .split (";" )
50
56
if len (values ) == 1 :
51
57
name = values [0 ]
@@ -78,6 +84,7 @@ class HTMLRenderMiddleware:
78
84
79
85
app : ASGIApp
80
86
templates : Jinja2Templates = field (default_factory = lambda : DEFAULT_TEMPLATES )
87
+ endpoints_names : dict [str , str ] = field (default_factory = lambda : ENDPOINT_TEMPLATES )
81
88
82
89
def create_html_response (
83
90
self ,
@@ -89,7 +96,7 @@ def create_html_response(
89
96
** kwargs : Any ,
90
97
) -> bytes :
91
98
"""Create Template response."""
92
- router_prefix = request .app .state . router_prefix
99
+ router_prefix = getattr ( request .app .state , " router_prefix" , None )
93
100
94
101
urlpath = request .url .path
95
102
if root_path := request .app .root_path :
@@ -167,23 +174,25 @@ async def send_as_html(message: Message):
167
174
request = Request (scope , receive = receive )
168
175
pref_encoding = preferred_encoding (request .headers .get ("accept" , "" )) or []
169
176
170
- output_type : Optional [ MimeTypes ] = None
177
+ encode_to_html = False
171
178
if request .query_params .get ("f" , "" ) == "html" :
172
- output_type = MimeTypes .html
173
- elif "text/html" in pref_encoding and not request .query_params .get ("f" , "" ):
174
- output_type = MimeTypes .html
175
-
176
- if start_message ["status" ] == 200 and output_type :
177
- headers = MutableHeaders (scope = start_message )
178
- if tpl := ENDPOINT_TEMPLATES .get (scope ["route" ].name ):
179
- headers ["content-type" ] = "text/html"
179
+ encode_to_html = True
180
+ elif (
181
+ "text/html" in pref_encoding or "*" in pref_encoding
182
+ ) and not request .query_params .get ("f" , "" ):
183
+ encode_to_html = True
184
+
185
+ if start_message ["status" ] == 200 and encode_to_html :
186
+ # NOTE: `scope["route"]` seems to be specific to FastAPI application
187
+ if tpl := self .endpoints_names .get (scope ["route" ].name ):
180
188
body = self .create_html_response (
181
189
request ,
182
190
json .loads (body .decode ()),
183
191
template_name = tpl ,
184
192
title = scope ["route" ].name ,
185
193
)
186
- headers ["Content-Encoding" ] = "text/html"
194
+ headers = MutableHeaders (scope = start_message )
195
+ headers ["Content-Type" ] = "text/html"
187
196
headers ["Content-Length" ] = str (len (body ))
188
197
189
198
# Send http.response.start
0 commit comments