Hello,
Today, I downloaded web2py from GitHub to start testing a future update. I have several "upload" fields for images, and they have all started to fail.
After some investigation, I found that this issue started after Pull Request (PR) #2471 (Sanitize Headers) was merged.
Link to PR. This PR modifies the file gluon/http.py.
The following code:
@cache.action(time_expire=86400)
def download():
return response.download(request, db)
has stopped working.
If I remove the line "@cache.action(time_expire=86400)", it works, but that's not a good solution.
While investigating the root of the problem, I found the issue around line 123 of gluon/http.py. It used to be like this:
rheaders = []
for k, v in iteritems(headers):
if isinstance(v, list):
rheaders += [(k, item) for item in v]
else:
rheaders.append((k, v))
responder(status, rheaders)
Now it looks like this:
rheaders = []
for k, v in iteritems(headers):
if isinstance(v, list):
rheaders += [(k, str(item)) for item in v]
elif v is not None:
rheaders.append((k, str(v)))
responder(status, rheaders)
The variable "rheaders" contains the HTTP headers, but with these modifications, some values are int or None, but they should be str. For example:
('Content-Length', 29563)
('Pragma', None)
('Content-Length', 29563) should be ('Content-Length', '29563'), and I believe ('Pragma', None) is a deprecated header that should be removed.
A possible solution could be to revert part of the PR, but I think there might be a better solution.
The real issue seems to originate from the files gluon/streamer.py and gluon/cache.py. I have commented on the lines that have problems:
In gluon/streamer.py, line 127:
# in all the other cases (not 304, not 206, but 200 or error page)
if status != 206:
enc = request.env.http_accept_encoding
if enc and 'gzip' in enc and not 'Content-Encoding' in headers:
gzipped = static_file + '.gz'
if os.path.isfile(gzipped) and os.path.getmtime(gzipped) >= modified:
static_file = gzipped
fsize = os.path.getsize(gzipped)
headers['Content-Encoding'] = 'gzip'
headers['Vary'] = 'Accept-Encoding'
try:
stream = open(static_file, 'rb')
except IOError as e:
# this better not happen when returning an error page ;-)
if e.errno in (errno.EISDIR, errno.EACCES):
raise HTTP(403)
else:
raise HTTP(404)
headers['Content-Length'] = fsize # should be: headers['Content-Length'] = str(fsize)
In gluon/cache.py, line 676:
if send_headers:
headers = {'Pragma': None, # Deprecated: This feature is no longer recommended
'Expires': expires,
'Cache-Control': cache_control}
What is your opinion?
Best way to solve it?
Carlos.