OLD | NEW |
(Empty) | |
| 1 # Copyright 2012 Google Inc. All Rights Reserved. |
| 2 # |
| 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 # you may not use this file except in compliance with the License. |
| 5 # You may obtain a copy of the License at |
| 6 # |
| 7 # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 # |
| 9 # Unless required by applicable law or agreed to in writing, |
| 10 # software distributed under the License is distributed on an |
| 11 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
| 12 # either express or implied. See the License for the specific |
| 13 # language governing permissions and limitations under the License. |
| 14 |
| 15 """Google Cloud Storage specific Files API calls.""" |
| 16 |
| 17 |
| 18 |
| 19 |
| 20 |
| 21 __all__ = ['AuthorizationError', |
| 22 'check_status', |
| 23 'Error', |
| 24 'FatalError', |
| 25 'FileClosedError', |
| 26 'ForbiddenError', |
| 27 'InvalidRange', |
| 28 'NotFoundError', |
| 29 'ServerError', |
| 30 'TimeoutError', |
| 31 'TransientError', |
| 32 ] |
| 33 |
| 34 import httplib |
| 35 |
| 36 |
| 37 class Error(Exception): |
| 38 """Base error for all gcs operations. |
| 39 |
| 40 Error can happen on GAE side or GCS server side. |
| 41 For details on a particular GCS HTTP response code, see |
| 42 https://developers.google.com/storage/docs/reference-status#standardcodes |
| 43 """ |
| 44 |
| 45 |
| 46 class TransientError(Error): |
| 47 """TransientError could be retried.""" |
| 48 |
| 49 |
| 50 class TimeoutError(TransientError): |
| 51 """HTTP 408 timeout.""" |
| 52 |
| 53 |
| 54 class FatalError(Error): |
| 55 """FatalError shouldn't be retried.""" |
| 56 |
| 57 |
| 58 class FileClosedError(FatalError): |
| 59 """File is already closed. |
| 60 |
| 61 This can happen when the upload has finished but 'write' is called on |
| 62 a stale upload handle. |
| 63 """ |
| 64 |
| 65 |
| 66 class NotFoundError(FatalError): |
| 67 """HTTP 404 resource not found.""" |
| 68 |
| 69 |
| 70 class ForbiddenError(FatalError): |
| 71 """HTTP 403 Forbidden. |
| 72 |
| 73 While GCS replies with a 403 error for many reasons, the most common one |
| 74 is due to bucket permission not correctly setup for your app to access. |
| 75 """ |
| 76 |
| 77 |
| 78 class AuthorizationError(FatalError): |
| 79 """HTTP 401 authentication required. |
| 80 |
| 81 Unauthorized request has been received by GCS. |
| 82 |
| 83 This error is mostly handled by GCS client. GCS client will request |
| 84 a new access token and retry the request. |
| 85 """ |
| 86 |
| 87 |
| 88 class InvalidRange(FatalError): |
| 89 """HTTP 416 RequestRangeNotSatifiable.""" |
| 90 |
| 91 |
| 92 class ServerError(TransientError): |
| 93 """HTTP >= 500 server side error.""" |
| 94 |
| 95 |
| 96 def check_status(status, expected, path, headers=None, |
| 97 resp_headers=None, body=None, extras=None): |
| 98 """Check HTTP response status is expected. |
| 99 |
| 100 Args: |
| 101 status: HTTP response status. int. |
| 102 expected: a list of expected statuses. A list of ints. |
| 103 path: filename or a path prefix. |
| 104 headers: HTTP request headers. |
| 105 resp_headers: HTTP response headers. |
| 106 body: HTTP response body. |
| 107 extras: extra info to be logged verbatim if error occurs. |
| 108 |
| 109 Raises: |
| 110 AuthorizationError: if authorization failed. |
| 111 NotFoundError: if an object that's expected to exist doesn't. |
| 112 TimeoutError: if HTTP request timed out. |
| 113 ServerError: if server experienced some errors. |
| 114 FatalError: if any other unexpected errors occurred. |
| 115 """ |
| 116 if status in expected: |
| 117 return |
| 118 |
| 119 msg = ('Expect status %r from Google Storage. But got status %d.\n' |
| 120 'Path: %r.\n' |
| 121 'Request headers: %r.\n' |
| 122 'Response headers: %r.\n' |
| 123 'Body: %r.\n' |
| 124 'Extra info: %r.\n' % |
| 125 (expected, status, path, headers, resp_headers, body, extras)) |
| 126 |
| 127 if status == httplib.UNAUTHORIZED: |
| 128 raise AuthorizationError(msg) |
| 129 elif status == httplib.FORBIDDEN: |
| 130 raise ForbiddenError(msg) |
| 131 elif status == httplib.NOT_FOUND: |
| 132 raise NotFoundError(msg) |
| 133 elif status == httplib.REQUEST_TIMEOUT: |
| 134 raise TimeoutError(msg) |
| 135 elif status == httplib.REQUESTED_RANGE_NOT_SATISFIABLE: |
| 136 raise InvalidRange(msg) |
| 137 elif (status == httplib.OK and 308 in expected and |
| 138 httplib.OK not in expected): |
| 139 raise FileClosedError(msg) |
| 140 elif status >= 500: |
| 141 raise ServerError(msg) |
| 142 else: |
| 143 raise FatalError(msg) |
OLD | NEW |