当请求未压缩时,使用 Starlette 提供预压缩文件,但 'accept-encoding' 包括 'gzip'
serve pre-compressed files with Starlette, when uncompressed is requested, but 'accept-encoding' includes 'gzip'
假设为request.url
GET /fomantic-ui/default/semantic.min.css
对于某些文件扩展名,例如.css
,我需要提供预压缩的 .gz
版本。
我从 node-express 知道一种方法,当应用于 Starlette 时,只需操作 request.url.path
并向其附加 '.gz'
。然而,这会导致 AttributeError: Can't set attribute
.
Starlette 世界的方法是什么?
我唯一发现的是应该处理 GZIP 请求的中间件。但我认为它在这里不可用,因为我需要自己的逻辑来决定从 AWS S3 存储桶或 diskcache
.
请求什么文件
这是路由处理程序的示例:
async def theme(request):
try:
file_path = request.path_params.get('file_path')
is_asset = file_path.split('.')[-1] in ['ico', 'png']
if is_asset:
full_path = f'assets/{file_path}'
else:
if 'gzip' in request.headers['accept-encoding']:
full_path = f'theme_build/{file_path}.gz'
request.url.path = request.url.path + '.gz' # results in AttributeError("can't set attribute")
else:
full_path = f'theme_build/{file_path}'
print(full_path, flush=True)
s3_result = get_file(full_path)
return StreamingResponse(s3_result['Body'], headers=s3_result['ResponseMetadata']['HTTPHeaders'])
except ...
显然我不能只return gzip 内容作为对原始 request.url
的响应,因为浏览器不会期望 gzip 内容。
可能完全正确的方法是在响应的 header 中设置 'content-encoding': 'gzip'
。
所以,在上面的例子中我基本上是这样做的:
return StreamingResponse(
s3_result['Body'],
headers={**s3_result['ResponseMetadata']['HTTPHeaders'], 'content-encoding': 'gzip'}
)
假设为request.url
GET /fomantic-ui/default/semantic.min.css
对于某些文件扩展名,例如.css
,我需要提供预压缩的 .gz
版本。
我从 node-express 知道一种方法,当应用于 Starlette 时,只需操作 request.url.path
并向其附加 '.gz'
。然而,这会导致 AttributeError: Can't set attribute
.
Starlette 世界的方法是什么?
我唯一发现的是应该处理 GZIP 请求的中间件。但我认为它在这里不可用,因为我需要自己的逻辑来决定从 AWS S3 存储桶或 diskcache
.
这是路由处理程序的示例:
async def theme(request):
try:
file_path = request.path_params.get('file_path')
is_asset = file_path.split('.')[-1] in ['ico', 'png']
if is_asset:
full_path = f'assets/{file_path}'
else:
if 'gzip' in request.headers['accept-encoding']:
full_path = f'theme_build/{file_path}.gz'
request.url.path = request.url.path + '.gz' # results in AttributeError("can't set attribute")
else:
full_path = f'theme_build/{file_path}'
print(full_path, flush=True)
s3_result = get_file(full_path)
return StreamingResponse(s3_result['Body'], headers=s3_result['ResponseMetadata']['HTTPHeaders'])
except ...
显然我不能只return gzip 内容作为对原始 request.url
的响应,因为浏览器不会期望 gzip 内容。
可能完全正确的方法是在响应的 header 中设置 'content-encoding': 'gzip'
。
所以,在上面的例子中我基本上是这样做的:
return StreamingResponse(
s3_result['Body'],
headers={**s3_result['ResponseMetadata']['HTTPHeaders'], 'content-encoding': 'gzip'}
)