Show More
@@ -36,16 +36,15 b" HGERRTYPE = 'application/hg-error'" | |||
|
36 | 36 | SSHV1 = wireprototypes.SSHV1 |
|
37 | 37 | SSHV2 = wireprototypes.SSHV2 |
|
38 | 38 | |
|
39 |
def decodevaluefromheaders( |
|
|
39 | def decodevaluefromheaders(req, headerprefix): | |
|
40 | 40 | """Decode a long value from multiple HTTP request headers. |
|
41 | 41 | |
|
42 | 42 | Returns the value as a bytes, not a str. |
|
43 | 43 | """ |
|
44 | 44 | chunks = [] |
|
45 | 45 | i = 1 |
|
46 | prefix = headerprefix.upper().replace(r'-', r'_') | |
|
47 | 46 | while True: |
|
48 |
v = |
|
|
47 | v = req.headers.get(b'%s-%d' % (headerprefix, i)) | |
|
49 | 48 | if v is None: |
|
50 | 49 | break |
|
51 | 50 | chunks.append(pycompat.bytesurl(v)) |
@@ -54,8 +53,9 b' def decodevaluefromheaders(wsgireq, head' | |||
|
54 | 53 | return ''.join(chunks) |
|
55 | 54 | |
|
56 | 55 | class httpv1protocolhandler(wireprototypes.baseprotocolhandler): |
|
57 | def __init__(self, wsgireq, ui, checkperm): | |
|
56 | def __init__(self, wsgireq, req, ui, checkperm): | |
|
58 | 57 | self._wsgireq = wsgireq |
|
58 | self._req = req | |
|
59 | 59 | self._ui = ui |
|
60 | 60 | self._checkperm = checkperm |
|
61 | 61 | |
@@ -80,24 +80,24 b' class httpv1protocolhandler(wireprototyp' | |||
|
80 | 80 | |
|
81 | 81 | def _args(self): |
|
82 | 82 | args = util.rapply(pycompat.bytesurl, self._wsgireq.form.copy()) |
|
83 |
postlen = int(self._ |
|
|
83 | postlen = int(self._req.headers.get(b'X-HgArgs-Post', 0)) | |
|
84 | 84 | if postlen: |
|
85 | 85 | args.update(urlreq.parseqs( |
|
86 | 86 | self._wsgireq.read(postlen), keep_blank_values=True)) |
|
87 | 87 | return args |
|
88 | 88 | |
|
89 |
argvalue = decodevaluefromheaders(self._ |
|
|
89 | argvalue = decodevaluefromheaders(self._req, b'X-HgArg') | |
|
90 | 90 | args.update(urlreq.parseqs(argvalue, keep_blank_values=True)) |
|
91 | 91 | return args |
|
92 | 92 | |
|
93 | 93 | def forwardpayload(self, fp): |
|
94 | if r'HTTP_CONTENT_LENGTH' in self._wsgireq.env: | |
|
95 |
length = int(self._ |
|
|
94 | if b'Content-Length' in self._req.headers: | |
|
95 | length = int(self._req.headers[b'Content-Length']) | |
|
96 | 96 | else: |
|
97 | 97 | length = int(self._wsgireq.env[r'CONTENT_LENGTH']) |
|
98 | 98 | # If httppostargs is used, we need to read Content-Length |
|
99 | 99 | # minus the amount that was consumed by args. |
|
100 |
length -= int(self._ |
|
|
100 | length -= int(self._req.headers.get(b'X-HgArgs-Post', 0)) | |
|
101 | 101 | for s in util.filechunkiter(self._wsgireq, limit=length): |
|
102 | 102 | fp.write(s) |
|
103 | 103 | |
@@ -193,11 +193,11 b' def handlewsgirequest(rctx, wsgireq, req' | |||
|
193 | 193 | if req.dispatchpath: |
|
194 | 194 | res = _handlehttperror( |
|
195 | 195 | hgwebcommon.ErrorResponse(hgwebcommon.HTTP_NOT_FOUND), wsgireq, |
|
196 | cmd) | |
|
196 | req, cmd) | |
|
197 | 197 | |
|
198 | 198 | return True, res |
|
199 | 199 | |
|
200 | proto = httpv1protocolhandler(wsgireq, repo.ui, | |
|
200 | proto = httpv1protocolhandler(wsgireq, req, repo.ui, | |
|
201 | 201 | lambda perm: checkperm(rctx, wsgireq, perm)) |
|
202 | 202 | |
|
203 | 203 | # The permissions checker should be the only thing that can raise an |
@@ -205,20 +205,20 b' def handlewsgirequest(rctx, wsgireq, req' | |||
|
205 | 205 | # exception here. So consider refactoring into a exception type that |
|
206 | 206 | # is associated with the wire protocol. |
|
207 | 207 | try: |
|
208 | res = _callhttp(repo, wsgireq, proto, cmd) | |
|
208 | res = _callhttp(repo, wsgireq, req, proto, cmd) | |
|
209 | 209 | except hgwebcommon.ErrorResponse as e: |
|
210 | res = _handlehttperror(e, wsgireq, cmd) | |
|
210 | res = _handlehttperror(e, wsgireq, req, cmd) | |
|
211 | 211 | |
|
212 | 212 | return True, res |
|
213 | 213 | |
|
214 |
def _httpresponsetype(ui, |
|
|
214 | def _httpresponsetype(ui, req, prefer_uncompressed): | |
|
215 | 215 | """Determine the appropriate response type and compression settings. |
|
216 | 216 | |
|
217 | 217 | Returns a tuple of (mediatype, compengine, engineopts). |
|
218 | 218 | """ |
|
219 | 219 | # Determine the response media type and compression engine based |
|
220 | 220 | # on the request parameters. |
|
221 |
protocaps = decodevaluefromheaders( |
|
|
221 | protocaps = decodevaluefromheaders(req, 'X-HgProto').split(' ') | |
|
222 | 222 | |
|
223 | 223 | if '0.2' in protocaps: |
|
224 | 224 | # All clients are expected to support uncompressed data. |
@@ -251,7 +251,7 b' def _httpresponsetype(ui, wsgireq, prefe' | |||
|
251 | 251 | opts = {'level': ui.configint('server', 'zliblevel')} |
|
252 | 252 | return HGTYPE, util.compengines['zlib'], opts |
|
253 | 253 | |
|
254 | def _callhttp(repo, wsgireq, proto, cmd): | |
|
254 | def _callhttp(repo, wsgireq, req, proto, cmd): | |
|
255 | 255 | def genversion2(gen, engine, engineopts): |
|
256 | 256 | # application/mercurial-0.2 always sends a payload header |
|
257 | 257 | # identifying the compression engine. |
@@ -289,7 +289,7 b' def _callhttp(repo, wsgireq, proto, cmd)' | |||
|
289 | 289 | # This code for compression should not be streamres specific. It |
|
290 | 290 | # is here because we only compress streamres at the moment. |
|
291 | 291 | mediatype, engine, engineopts = _httpresponsetype( |
|
292 |
repo.ui, |
|
|
292 | repo.ui, req, rsp.prefer_uncompressed) | |
|
293 | 293 | gen = engine.compressstream(gen, engineopts) |
|
294 | 294 | |
|
295 | 295 | if mediatype == HGTYPE2: |
@@ -314,7 +314,7 b' def _callhttp(repo, wsgireq, proto, cmd)' | |||
|
314 | 314 | return [] |
|
315 | 315 | raise error.ProgrammingError('hgweb.protocol internal failure', rsp) |
|
316 | 316 | |
|
317 | def _handlehttperror(e, wsgireq, cmd): | |
|
317 | def _handlehttperror(e, wsgireq, req, cmd): | |
|
318 | 318 | """Called when an ErrorResponse is raised during HTTP request processing.""" |
|
319 | 319 | |
|
320 | 320 | # Clients using Python's httplib are stateful: the HTTP client |
@@ -327,8 +327,7 b' def _handlehttperror(e, wsgireq, cmd):' | |||
|
327 | 327 | |
|
328 | 328 | if (wsgireq.env[r'REQUEST_METHOD'] == r'POST' and |
|
329 | 329 | # But not if Expect: 100-continue is being used. |
|
330 | (wsgireq.env.get('HTTP_EXPECT', | |
|
331 | '').lower() != '100-continue')): | |
|
330 | (req.headers.get('Expect', '').lower() != '100-continue')): | |
|
332 | 331 | wsgireq.drain() |
|
333 | 332 | else: |
|
334 | 333 | wsgireq.headers.append((r'Connection', r'Close')) |
General Comments 0
You need to be logged in to leave comments.
Login now