【问题标题】:serve pre-compressed files with Starlette, when uncompressed is requested, but 'accept-encoding' includes 'gzip'当请求未压缩时,使用 Starlette 提供预压缩文件,但 'accept-encoding' 包括 'gzip'
【发布时间】:2021-11-09 13:31:51
【问题描述】:

假设为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 ...

显然我不能只返回 gzip 压缩的内容作为对原始 request.url 的响应,因为浏览器不会期望 gzip 压缩的内容。

【问题讨论】:

    标签: python gzip starlette


    【解决方案1】:

    这样做的正确方法可能是在响应的标题中设置'content-encoding': 'gzip'

    所以,在上面的例子中,我基本上是这样做的:

    return StreamingResponse(
        s3_result['Body'],
        headers={**s3_result['ResponseMetadata']['HTTPHeaders'], 'content-encoding': 'gzip'}
    )
    

    【讨论】:

      猜你喜欢
      • 2016-04-22
      • 2020-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-07
      • 1970-01-01
      • 2014-05-24
      • 1970-01-01
      相关资源
      最近更新 更多