Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/hgweb/request.py @ 36860:290fc4c3d1e0
hgweb: use a capped reader for WSGI input stream
Per PEP 3333, the input stream from WSGI should respect EOF and
prevent reads past the end of the request body. However, not all
WSGI servers guarantee this. Notably, our BaseHTTPServer based
built-in HTTP server doesn't. Instead, it exposes the raw socket
and you can read() from it all you want, getting the connection in
a bad state by doing so.
We have a "cappedreader" utility class that proxies a file object
and prevents reading past a limit.
This commit converts the WSGI input stream into a capped reader when
the input length is advertised via Content-Length headers.
"cappedreader" only exposes a read() method. PEP 3333 states that
the input stream MUST also support readline(), readlines(hint), and
__iter__(). However, since our WSGI application code only calls
read() and since we're not manipulating the stream exposed by the
WSGI server, we're not violating the spec here.
Differential Revision: https://phab.mercurial-scm.org/D2768
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 10 Mar 2018 10:48:34 -0800 |
parents | e3f809e0fe8e |
children | 2cdf47e14c30 |
comparison
equal
deleted
inserted
replaced
36859:7066617187c1 | 36860:290fc4c3d1e0 |
---|---|
232 version = wsgienv[r'wsgi.version'] | 232 version = wsgienv[r'wsgi.version'] |
233 if (version < (1, 0)) or (version >= (2, 0)): | 233 if (version < (1, 0)) or (version >= (2, 0)): |
234 raise RuntimeError("Unknown and unsupported WSGI version %d.%d" | 234 raise RuntimeError("Unknown and unsupported WSGI version %d.%d" |
235 % version) | 235 % version) |
236 self.inp = wsgienv[r'wsgi.input'] | 236 self.inp = wsgienv[r'wsgi.input'] |
237 | |
238 if r'HTTP_CONTENT_LENGTH' in wsgienv: | |
239 self.inp = util.cappedreader(self.inp, | |
240 int(wsgienv[r'HTTP_CONTENT_LENGTH'])) | |
241 elif r'CONTENT_LENGTH' in wsgienv: | |
242 self.inp = util.cappedreader(self.inp, | |
243 int(wsgienv[r'CONTENT_LENGTH'])) | |
244 | |
237 self.err = wsgienv[r'wsgi.errors'] | 245 self.err = wsgienv[r'wsgi.errors'] |
238 self.threaded = wsgienv[r'wsgi.multithread'] | 246 self.threaded = wsgienv[r'wsgi.multithread'] |
239 self.multiprocess = wsgienv[r'wsgi.multiprocess'] | 247 self.multiprocess = wsgienv[r'wsgi.multiprocess'] |
240 self.run_once = wsgienv[r'wsgi.run_once'] | 248 self.run_once = wsgienv[r'wsgi.run_once'] |
241 self.env = wsgienv | 249 self.env = wsgienv |