OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 """Defines class Rietveld to easily access a rietveld instance. | 4 """Defines class Rietveld to easily access a rietveld instance. |
5 | 5 |
6 Security implications: | 6 Security implications: |
7 | 7 |
8 The following hypothesis are made: | 8 The following hypothesis are made: |
9 - Rietveld enforces: | 9 - Rietveld enforces: |
10 - Nobody else than issue owner can upload a patch set | 10 - Nobody else than issue owner can upload a patch set |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 def get(self, request_path, **kwargs): | 304 def get(self, request_path, **kwargs): |
305 kwargs.setdefault('payload', None) | 305 kwargs.setdefault('payload', None) |
306 return self._send(request_path, **kwargs) | 306 return self._send(request_path, **kwargs) |
307 | 307 |
308 def post(self, request_path, data, **kwargs): | 308 def post(self, request_path, data, **kwargs): |
309 ctype, body = upload.EncodeMultipartFormData(data, []) | 309 ctype, body = upload.EncodeMultipartFormData(data, []) |
310 return self._send(request_path, payload=body, content_type=ctype, **kwargs) | 310 return self._send(request_path, payload=body, content_type=ctype, **kwargs) |
311 | 311 |
312 def _send(self, request_path, **kwargs): | 312 def _send(self, request_path, **kwargs): |
313 """Sends a POST/GET to Rietveld. Returns the response body.""" | 313 """Sends a POST/GET to Rietveld. Returns the response body.""" |
314 maxtries = 5 | 314 try: |
315 for retry in xrange(maxtries): | 315 # Sadly, upload.py calls ErrorExit() which does a sys.exit(1) on HTTP |
316 try: | 316 # 500 in AbstractRpcServer.Send(). |
317 logging.debug('%s' % request_path) | 317 old_error_exit = upload.ErrorExit |
318 result = self.rpc_server.Send(request_path, **kwargs) | 318 def trap_http_500(msg): |
319 # Sometimes GAE returns a HTTP 200 but with HTTP 500 as the content. How | 319 """Converts an incorrect ErrorExit() call into a HTTPError exception.""" |
320 # nice. | 320 m = re.search(r'(50\d) Server Error', msg) |
321 return result | 321 if m: |
322 except urllib2.HTTPError, e: | 322 # Fake an HTTPError exception. Cheezy. :( |
323 if retry >= (maxtries - 1): | 323 raise urllib2.HTTPError( |
324 raise | 324 request_path, m.group(1), e.args[0], None, None) |
325 if e.code not in (500, 502, 503): | 325 old_error_exit(msg) |
326 raise | 326 upload.ErrorExit = trap_http_500 |
327 except urllib2.URLError, e: | 327 |
328 if retry >= (maxtries - 1): | 328 maxtries = 5 |
329 raise | 329 for retry in xrange(maxtries): |
330 if not 'Name or service not known' in e.reason: | 330 try: |
331 # Usually internal GAE flakiness. | 331 logging.debug('%s' % request_path) |
332 raise | 332 result = self.rpc_server.Send(request_path, **kwargs) |
333 # If reaching this line, loop again. Uses a small backoff. | 333 # Sometimes GAE returns a HTTP 200 but with HTTP 500 as the content. |
334 time.sleep(1+maxtries*2) | 334 # How nice. |
| 335 return result |
| 336 except urllib2.HTTPError, e: |
| 337 if retry >= (maxtries - 1): |
| 338 raise |
| 339 if e.code not in (500, 502, 503): |
| 340 raise |
| 341 except urllib2.URLError, e: |
| 342 if retry >= (maxtries - 1): |
| 343 raise |
| 344 if not 'Name or service not known' in e.reason: |
| 345 # Usually internal GAE flakiness. |
| 346 raise |
| 347 # If reaching this line, loop again. Uses a small backoff. |
| 348 time.sleep(1+maxtries*2) |
| 349 finally: |
| 350 upload.ErrorExit = old_error_exit |
335 | 351 |
336 # DEPRECATED. | 352 # DEPRECATED. |
337 Send = get | 353 Send = get |
OLD | NEW |