我的博客

dwebsocket 兼容django 新版本(2.15以后)

目录
  1. 影响的版本

我在 django 2.2 上使用 dwebsocket 时遇到了一个问题。环境是 Windows 10,Python 3.7,dwebsocket 0.5.10。使用 django 开发服务器。

客户端连接时总是返回 400 BadRequest,服务端又无错误输出。只输出了 400 BedRequest。

调试源码发现,问题出在 dwebsocket.backends.default.factory.WebSocketFactory 的 get_wsgi_sock 函数。(Github 链接)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class WebSocketFactory(factory.WebSocketFactory): 

def get_wsgi_sock(self):
if 'gunicorn.socket' in self.request.META:
sock = self.request.META['gunicorn.socket']
else:
wsgi_input = self.request.META['wsgi.input']
if hasattr(wsgi_input, '_sock'):
sock = wsgi_input._sock
elif hasattr(wsgi_input, 'rfile'): # gevent
if hasattr(wsgi_input.rfile, '_sock'):
sock = wsgi_input.rfile._sock
else:
sock = wsgi_input.rfile.raw._sock
elif hasattr(wsgi_input, 'raw'):
sock = wsgi_input.raw._sock
else:
raise ValueError('Socket not found in wsgi.input')
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
return sock

第 7 行的 wsgi_input 也就是 self.request.META[‘wsgi.input’]。这个对象在的类型在 django 的 b514dc14f4e1c364341f5931b354e83ef15ee12d 提交之后改变了。这次提交之前的 wsgi_input 是 _io.BufferedReader 类型。提交之后则是 django.core.handlers.wsgi.LimitedStream 类型。实际上 LimitedStream 是对 _io.BufferedReader 的封装,LimitedStream.stream 就是原来的 _io.BufferedReader 了。

可以在 16 行后插入一个新的 elif 判断 wsgi_input 是否含有 stream 属性

1
2
elif hasattr(wsgi_input, 'stream') and hasattr(wsgi_input.stream, 'raw'):
sock = wsgi_input.stream.raw

这样不会影响原来旧版本的 django,只有 wsgi_input 不满足前面所有的条件才会执行到这里。

影响的版本

上文提到的 b514dc 提交的时间是 2018 年 12 月 6 日。介于 django 的 2.1.4 和 2.1.5 之间。也就是说从 2.1.5 开始使用 django 开发服务器运行 dwebsocket 就会出现这个问题。

评论无需登录,可以匿名,欢迎评论!