如何使用 Django Rest Framework 处理带有压缩正文的 POST 请求

问题描述 投票:0回答:1

这是上下文:

  • 我有一个带有后端 API(使用 Django Rest Framework 编码)的 Web 应用程序,除了作为反向代理的 Nginx 和一个前端。
  • 用户可以在请求正文中使用一些 JSON 内容来 POST 数据
  • 一切正常,但我现在想压缩 JSON 内容
  • 主体在正面进行 gzip 压缩(使用 Pako),我想在 DRF 端处理这些数据

问题是 DRF 视图(我正在使用

ListCreateAPIView
)需要 JSON 数据,因此我无法调用
request.data
来应用 zlib 解压缩。由于压缩数据,我收到格式错误的请求(400 Bad request):
JSON parse error - 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte

问题是:我怎样才能实现这个功能?

据我目前发现,Django Gzip 中间件(参见。无法使用 Django Rest 框架发送压缩的 gzip 数据)仅提供压缩功能,而不提供解压缩功能。 我还了解到压缩可能会导致安全风险。 另外,Nginx 解压文档仅针对响应,而不针对请求。

我有点困惑,因为压缩数据以通过 HTTP 请求发送对我来说似乎并不愚蠢(或者是吗?),而且我没有找到太多关于如何实现这一目标的资源。 所以也许我在这里遗漏了一些重要的东西?

客户端压缩:

async postData(json_data) {
    let headers = authHeader();
    headers['Content-Encoding'] = 'gzip';
    headers['Content-Type'] = 'application/json';

    const data = json_data;
    const gz_data = pako.gzip(JSON.stringify(data));
    
    return axios
      .post(API_URL + 'create/', 
        data,
        {
          headers: headers,
        }
      )
      .then(response => {
        return response.data;
      })
  }

在 Django 视图端:

class DataList(ListCreateAPIView):
    serializer_class = DataSerializer
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        # Filter transects based on user identity (token based)
        queryset = Data.objects.filter(user=self.request.user)
        return queryset
    
    def post(self, request, format=None):
        transect_data = request.data # Returns 400 Bad request due to malformed expected JSON because it is gzipped
python http django-rest-framework gzip
1个回答
0
投票

压缩请求正文可能不是一个好主意。我个人不确定。参见:

但是如果您仍然认为值得这样做,那么在这种情况下要读取请求正文,您似乎可以使用

request.body
来获取字节字符串形式的正文。 (link) 然后,您可以将该字节字符串传递给知道如何解压缩 gzip 的函数,这可能会为您提供另一个字节字符串。然后你就可以使用
json.loads(body_bytes.decode('utf-8'))

© www.soinside.com 2019 - 2024. All rights reserved.