process headers only when application is processed

An application can modify the headers after
start_response have been processed.

So we have to store the references of the headers list.

And write them to the client only when the application
have been processed but before we iter the body.

wsgiref and weboob already does the same thing.
This commit is contained in:
Mehdi Abaakouk
2015-07-31 14:20:29 +02:00
parent 86c5d1aef7
commit 585f919c4b
3 changed files with 36 additions and 16 deletions

View File

@@ -85,3 +85,12 @@ def test_encoding_errors():
response, content = http.request( response, content = http.request(
'http://some_hopefully_nonexistant_domain/boom/baz', 'http://some_hopefully_nonexistant_domain/boom/baz',
headers={'Accept': u'application/\u2603'}) headers={'Accept': u'application/\u2603'})
def test_post_status_headers():
with InstalledApp(wsgi_app.post_status_headers_app, host=HOST) as app:
http = httplib2.Http()
resp, content = http.request(
'http://some_hopefully_nonexistant_domain/', 'GET')
assert app.success()
assert resp.get('content-type') == 'text/plain'

View File

@@ -23,5 +23,12 @@ def more_interesting_app(environ, start_response):
return [pformat(environ).encode('utf-8')] return [pformat(environ).encode('utf-8')]
def post_status_headers_app(environ, start_response):
headers = []
start_response('200 OK', headers)
headers.append(('Content-type', 'text/plain'))
return [b'WSGI intercept successful!\n']
def raises_app(environ, start_response): def raises_app(environ, start_response):
raise TypeError("bah") raise TypeError("bah")

View File

@@ -375,25 +375,15 @@ class wsgi_fake_socket:
# dynamically construct the start_response function for no good reason. # dynamically construct the start_response function for no good reason.
self.headers = []
def start_response(status, headers, exc_info=None): def start_response(status, headers, exc_info=None):
# construct the HTTP request. # construct the HTTP request.
self.output.write(b"HTTP/1.0 " + status.encode('utf-8') + b"\n") self.output.write(b"HTTP/1.0 " + status.encode('utf-8') + b"\n")
# Keep the reference of the headers list to write them only
for k, v in headers: # when the whole application have been processed
try: self.headers = headers
k = k.encode('utf-8') return self.write_results.append
except AttributeError:
pass
try:
v = v.encode('utf-8')
except AttributeError:
pass
self.output.write(k + b': ' + v + b"\n")
self.output.write(b'\n')
def write_fn(s):
self.write_results.append(s)
return write_fn
# construct the wsgi.input file from everything that's been # construct the wsgi.input file from everything that's been
# written to this "socket". # written to this "socket".
@@ -411,6 +401,20 @@ class wsgi_fake_socket:
raise WSGIAppError(error, sys.exc_info()) raise WSGIAppError(error, sys.exc_info())
self.result = iter(app_result) self.result = iter(app_result)
# send the headers
for k, v in self.headers:
try:
k = k.encode('utf-8')
except AttributeError:
pass
try:
v = v.encode('utf-8')
except AttributeError:
pass
self.output.write(k + b': ' + v + b"\n")
self.output.write(b'\n')
### ###
# read all of the results. the trick here is to get the *first* # read all of the results. the trick here is to get the *first*