| OLD | NEW |
| 1 # Copyright 2012 The Swarming Authors. All rights reserved. | 1 # Copyright 2012 The Swarming Authors. All rights reserved. |
| 2 # Use of this source code is governed by the Apache v2.0 license that can be | 2 # Use of this source code is governed by the Apache v2.0 license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """This module defines Isolate Server frontend url handlers.""" | 5 """This module defines Isolate Server frontend url handlers.""" |
| 6 | 6 |
| 7 import binascii | 7 import binascii |
| 8 import collections | 8 import collections |
| 9 import datetime | 9 import datetime |
| 10 import hashlib | 10 import hashlib |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 "server_app_version": "138-193f1f3", | 158 "server_app_version": "138-193f1f3", |
| 159 } | 159 } |
| 160 """ | 160 """ |
| 161 | 161 |
| 162 # This handler is called to get XSRF token, there's nothing to enforce yet. | 162 # This handler is called to get XSRF token, there's nothing to enforce yet. |
| 163 xsrf_token_enforce_on = () | 163 xsrf_token_enforce_on = () |
| 164 | 164 |
| 165 @auth.require(acl.isolate_readable) | 165 @auth.require(acl.isolate_readable) |
| 166 def post(self): | 166 def post(self): |
| 167 """Responds with access token and server version.""" | 167 """Responds with access token and server version.""" |
| 168 logging.error('Unexpected old client') |
| 168 try: | 169 try: |
| 169 request = json.loads(self.request.body) | 170 request = json.loads(self.request.body) |
| 170 client_protocol = str(request['protocol_version']) | 171 client_protocol = str(request['protocol_version']) |
| 171 client_app_version = str(request['client_app_version']) | 172 client_app_version = str(request['client_app_version']) |
| 172 pusher = request.get('pusher', True) | 173 pusher = request.get('pusher', True) |
| 173 fetcher = request.get('fetcher', True) | 174 fetcher = request.get('fetcher', True) |
| 174 except (ValueError, KeyError) as exc: | 175 except (ValueError, KeyError) as exc: |
| 175 return self.send_error( | 176 return self.send_error( |
| 176 'Invalid body of /handshake call.\nError: %s.' % exc) | 177 'Invalid body of /handshake call.\nError: %s.' % exc) |
| 177 | 178 |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 entry_info, namespace, | 368 entry_info, namespace, |
| 368 http_verb='PUT', | 369 http_verb='PUT', |
| 369 uploaded_to_gs=False, | 370 uploaded_to_gs=False, |
| 370 expiration=self.DEFAULT_LINK_EXPIRATION) | 371 expiration=self.DEFAULT_LINK_EXPIRATION) |
| 371 finalize_url = None | 372 finalize_url = None |
| 372 return upload_url, finalize_url | 373 return upload_url, finalize_url |
| 373 | 374 |
| 374 @auth.require(acl.isolate_writable) | 375 @auth.require(acl.isolate_writable) |
| 375 def post(self, namespace): | 376 def post(self, namespace): |
| 376 """Reads body with items to upload and replies with URLs to upload to.""" | 377 """Reads body with items to upload and replies with URLs to upload to.""" |
| 378 logging.error('Unexpected old client') |
| 377 if not re.match(r'^%s$' % model.NAMESPACE_RE, namespace): | 379 if not re.match(r'^%s$' % model.NAMESPACE_RE, namespace): |
| 378 self.send_error( | 380 self.send_error( |
| 379 'Invalid namespace; allowed keys must pass regexp "%s"' % | 381 'Invalid namespace; allowed keys must pass regexp "%s"' % |
| 380 model.NAMESPACE_RE) | 382 model.NAMESPACE_RE) |
| 381 | 383 |
| 382 # Parse a body into list of EntryInfo objects. | 384 # Parse a body into list of EntryInfo objects. |
| 383 try: | 385 try: |
| 384 entries = self.parse_request(self.request.body) | 386 entries = self.parse_request(self.request.body) |
| 385 except ValueError as err: | 387 except ValueError as err: |
| 386 return self.send_error( | 388 return self.send_error( |
| (...skipping 29 matching lines...) Expand all Loading... |
| 416 Can produce 5 types of responses: | 418 Can produce 5 types of responses: |
| 417 * HTTP 200: the content is in response body as octet-stream. | 419 * HTTP 200: the content is in response body as octet-stream. |
| 418 * HTTP 206: partial content is in response body. | 420 * HTTP 206: partial content is in response body. |
| 419 * HTTP 302: http redirect to a file with the content. | 421 * HTTP 302: http redirect to a file with the content. |
| 420 * HTTP 404: content is not available, response body is a error message. | 422 * HTTP 404: content is not available, response body is a error message. |
| 421 * HTTP 416: requested byte range can not be satisfied. | 423 * HTTP 416: requested byte range can not be satisfied. |
| 422 """ | 424 """ |
| 423 | 425 |
| 424 @auth.require(acl.isolate_readable) | 426 @auth.require(acl.isolate_readable) |
| 425 def get(self, namespace, hash_key): #pylint: disable=W0221 | 427 def get(self, namespace, hash_key): #pylint: disable=W0221 |
| 428 logging.error('Unexpected old client') |
| 426 # Parse 'Range' header if it's present to extract initial offset. | 429 # Parse 'Range' header if it's present to extract initial offset. |
| 427 # Only support single continuous range from some |offset| to the end. | 430 # Only support single continuous range from some |offset| to the end. |
| 428 offset = 0 | 431 offset = 0 |
| 429 range_header = self.request.headers.get('range') | 432 range_header = self.request.headers.get('range') |
| 430 if range_header: | 433 if range_header: |
| 431 match = re.match(r'bytes=(\d+)-', range_header) | 434 match = re.match(r'bytes=(\d+)-', range_header) |
| 432 if not match: | 435 if not match: |
| 433 return self.send_error( | 436 return self.send_error( |
| 434 'Unsupported byte range.\n\'%s\'.' % range_header, http_code=416) | 437 'Unsupported byte range.\n\'%s\'.' % range_header, http_code=416) |
| 435 offset = int(match.group(1)) | 438 offset = int(match.group(1)) |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 is_isolated, | 520 is_isolated, |
| 518 uploaded_to_gs, | 521 uploaded_to_gs, |
| 519 ]) | 522 ]) |
| 520 mac = hmac.new(secret_key, digestmod=hashlib.sha1) | 523 mac = hmac.new(secret_key, digestmod=hashlib.sha1) |
| 521 mac.update(data_to_sign) | 524 mac.update(data_to_sign) |
| 522 return mac.hexdigest() | 525 return mac.hexdigest() |
| 523 | 526 |
| 524 @auth.require(acl.isolate_writable) | 527 @auth.require(acl.isolate_writable) |
| 525 def post(self, namespace, hash_key): | 528 def post(self, namespace, hash_key): |
| 526 """POST is used when finalizing upload to GS.""" | 529 """POST is used when finalizing upload to GS.""" |
| 530 logging.error('Unexpected old client') |
| 527 return self.handle(namespace, hash_key) | 531 return self.handle(namespace, hash_key) |
| 528 | 532 |
| 529 @auth.require(acl.isolate_writable) | 533 @auth.require(acl.isolate_writable) |
| 530 def put(self, namespace, hash_key): | 534 def put(self, namespace, hash_key): |
| 531 """PUT is used when uploading directly to datastore via this handler.""" | 535 """PUT is used when uploading directly to datastore via this handler.""" |
| 532 return self.handle(namespace, hash_key) | 536 return self.handle(namespace, hash_key) |
| 533 | 537 |
| 534 def handle(self, namespace, hash_key): | 538 def handle(self, namespace, hash_key): |
| 535 """Handles this request.""" | 539 """Handles this request.""" |
| 536 # Extract relevant request parameters. | 540 # Extract relevant request parameters. |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 RetrieveContentHandler), | 711 RetrieveContentHandler), |
| 708 webapp2.Route( | 712 webapp2.Route( |
| 709 r'/content-gs/store%s' % namespace_key, | 713 r'/content-gs/store%s' % namespace_key, |
| 710 StoreContentHandler, | 714 StoreContentHandler, |
| 711 name='store-gs'), | 715 name='store-gs'), |
| 712 ] | 716 ] |
| 713 # Routes added to WSGIApplication only a dev mode. | 717 # Routes added to WSGIApplication only a dev mode. |
| 714 if utils.is_local_dev_server(): | 718 if utils.is_local_dev_server(): |
| 715 routes.extend(gcs.URLSigner.switch_to_dev_mode()) | 719 routes.extend(gcs.URLSigner.switch_to_dev_mode()) |
| 716 return routes | 720 return routes |
| OLD | NEW |