在使用DRF和Djangorevproxy时获取“异常:从请求的数据流读取后无法访问正文”

2024-09-29 23:27:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我在我的项目中使用了django-revproxy和{a2}。我公开了一个API,用户可以从中获得聊天机器人的分析结果,其工作原理如下:

  • 用户发送来自Django项目的分析请求
  • Django项目,检查用户是否经过身份验证并拥有该聊天机器人
  • if True它联系另一个外部服务。在

我的网址.py

# urls.py
urlpatterns = (
    url(r'^analytics/(?P<path>.*)$', api.AnalyticsFunctionsProxyView.as_view()),
)

在我看来:

^{pr2}$

以及我的HasChatBotPermission权限

#permissions.py
class HasChatBotPermission(permissions.BasePermission):
    def has_permission(self, request, view):
        try:
            bot_name = request.data.get('name')
            user = request.user
            self.message = 'Permission denied for {}'.format(name)
            return ChatBot.objects.filter(user=user, project_name=project_id).exists()
        except Exception:
            self.message = 'Permission denied, no project_id was defined!'
            return False

调用该视图时,会引发此异常:

Traceback (most recent call last):
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/rest_framework/request.py", line 379, in __getattribute__
    return super(Request, self).__getattribute__(attr)
AttributeError: 'Request' object has no attribute 'body'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = get_response(request)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/fcmam5/anaconda3/lib/python3.6/contextlib.py", line 52, in inner
    return func(*args, **kwds)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/rest_framework/views.py", line 477, in dispatch
    response = self.handle_exception(exc)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/rest_framework/views.py", line 437, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/rest_framework/views.py", line 474, in dispatch
    response = handler(request, *args, **kwargs)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/rest_framework/decorators.py", line 52, in handler
    return func(*args, **kwargs)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/revproxy/views.py", line 204, in dispatch
    proxy_response = self._created_proxy_response(request, path)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/revproxy/views.py", line 139, in _created_proxy_response
    request_payload = request.body
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/rest_framework/request.py", line 383, in __getattribute__
    return getattr(self._request, attr)
  File "/home/fcmam5/dela3a/env/lib/python3.6/site-packages/django/http/request.py", line 264, in body
    raise RawPostDataException("You cannot access body after reading from request's data stream")
django.http.request.RawPostDataException: You cannot access body after reading from request's data stream

这个问题是由我的permissions.py中的bot_name = request.data.get('name')这一行引起的,当我直接传递一个字符串时,它不会有任何问题。在

我的问题是:

  • 如何访问请求正文而不出现此错误?为什么我会犯这个错误?在
  • 使用Django revproxy检查用户权限是否有更好的解决方案。在

这是我在Stackoverflow上的第一个问题,如果我的问题不是clea,我的英语很差:)


Tags: djangoinpyselfenvhomeresponserequest
1条回答
网友
1楼 · 发布于 2024-09-29 23:27:44

出现此错误是因为django-revproxy试图读取原始请求正文,以便它可以创建对上游服务器的代理请求。在

然而,使用Django(以及WSGI和缓冲)语义,一旦您以原始流的形式访问了请求体,这就不可能实现了,这是在request.data.get('name')时进行的。这将根据DRF的请求协商配置将请求主体解析为JSON、httpmultipart等,并使用流。在

据我所知,有两种方法可以解决这个问题:

  • bot_name传递到正文之外的某个地方;例如,一个查询字符串参数、一个HTTP标头、URL的一部分,因此您不需要访问主体,或者
  • 使用requests而不是反向代理(这基本上是一样的,但是增加了按原样复制请求的魔力)。在

相关问题 更多 >

    热门问题