-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbigpipe
152 lines (137 loc) · 5.04 KB
/
bigpipe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# -*- coding: utf-8 -*-
from werkzeug.serving import WSGIRequestHandler as wsgi
import socket
from werkzeug.exceptions import InternalServerError
import time
#全局变量 用来存储一次bigpipe的socket
sock = None
#选择是否用bigpipe发送可用装饰器localselect装订来改变返回值 返回真则用bigpipe否则不用,默认也不用
localselect_function = lambda : False
#测试bigpipe发送
scriptstring = "\
<script>\
alert('bigpipe')\
</script>\
"
#装饰器 用于装饰是否用bigpipe的函数,装饰的函数返回真假
def localselect(fn):
global localselect_function
global isbigpipe
localselect_function = fn
#改变werkzeug的发送方式用来实现bigpipe
def run_wsgi(self):
app = self.server.app
environ = self.make_environ()
headers_set = []
headers_sent = []
global sock
sock = self
def write(data):
assert headers_set, 'write() before start_response'
if not headers_sent:
status, response_headers = headers_sent[:] = headers_set
code, msg = status.split(None, 1)
self.send_response(int(code), msg)
header_keys = set()
self.send_header('Transfer-Encoding', 'chunked')
for key, value in response_headers:
if key.lower() == "content-length":
if localselect_function():
continue
self.send_header(key, value)
key = key.lower()
header_keys.add(key)
if not localselect_function() :
if 'content-length' not in header_keys:
self.close_connection = True
self.send_header('Connection', 'close')
if 'server' not in header_keys:
self.send_header('Server', self.version_string())
if 'date' not in header_keys:
self.send_header('Date', self.date_time_string())
self.end_headers()
assert type(data) is str, 'applications must write bytes'
self.wfile.write(data)
self.wfile.flush()
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
if headers_sent:
raise exc_info[0], exc_info[1], exc_info[2]
finally:
exc_info = None
elif headers_set:
raise AssertionError('Headers already set')
headers_set[:] = [status, response_headers]
return write
def execute(app):
application_iter = app(environ, start_response)
try:
for data in application_iter:
write(data)
# make sure the headers are sent
if not headers_sent:
write('')
while localselect_function():
send_script()
break
except Exception,e:
print "execute",e
finally:
if hasattr(application_iter, 'close'):
application_iter.close()
application_iter = None
try:
execute(app)
except (socket.error, socket.timeout), e:
self.connection_dropped(e, environ)
except Exception:
if self.server.passthrough_errors:
raise
from werkzeug.debug.tbtools import get_current_traceback
traceback = get_current_traceback(ignore_system_exceptions=True)
try:
# if we haven't yet sent the headers but they are set
# we roll back to be able to set them again.
if not headers_sent:
del headers_set[:]
execute(InternalServerError())
except Exception:
pass
self.server.log('error', 'Error on request:\n%s',
traceback.plaintext)
wsgi.run_wsgi = run_wsgi
#发送script的函数
def send_script():
time.sleep(3)
global sock
global scriptstring
global isbigpipe
try:
sock.wfile.write(scriptstring)
sock.wfile.flush()
sock.wfile.close()
sock.rfile.close()
except Exception,e:
print "send_script",e
finally:
init_scriptstring()
#用户用来返回script
def newscript(argscript):
global scriptstring
scriptstring = argscript
#初始化scriptstring
def init_scriptstring():
global scriptstring
scriptstring = "\
<script>\
alert('bigpipe')\
</script>\
"
#初始化localselect_function
def init_localselect_function():
global localselect_function
localselect_function = lambda : False
#用来修饰Flask的app,表示使用bigpipe
def BigPipe(app):
wsgi.run_wsgi = run_wsgi