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 'NotFoundError', 28 'ServerError', 29 'TimeoutError', 30 'TransientError', 31 ] 32 33import httplib 34 35 36class Error(Exception): 37 """Base error for all gcs operations. 38 39 Error can happen on GAE side or GCS server side. 40 For details on a particular GCS HTTP response code, see 41 https://developers.google.com/storage/docs/reference-status#standardcodes 42 """ 43 44 45class TransientError(Error): 46 """TransientError could be retried.""" 47 48 49class TimeoutError(TransientError): 50 """HTTP 408 timeout.""" 51 52 53class FatalError(Error): 54 """FatalError shouldn't be retried.""" 55 56 57class FileClosedError(FatalError): 58 """File is already closed. 59 60 This can happen when the upload has finished but 'write' is called on 61 a stale upload handle. 62 """ 63 64 65class NotFoundError(FatalError): 66 """HTTP 404 resource not found.""" 67 68 69class ForbiddenError(FatalError): 70 """HTTP 403 Forbidden. 71 72 While GCS replies with a 403 error for many reasons, the most common one 73 is due to bucket permission not correctly setup for your app to access. 74 """ 75 76 77class AuthorizationError(FatalError): 78 """HTTP 401 authentication required. 79 80 Unauthorized request has been received by GCS. 81 82 This error is mostly handled by GCS client. GCS client will request 83 a new access token and retry the request. 84 """ 85 86 87class InvalidRange(FatalError): 88 """HTTP 416 RequestRangeNotSatifiable.""" 89 90 91class ServerError(TransientError): 92 """HTTP >= 500 server side error.""" 93 94 95def check_status(status, expected, path, headers=None, 96 resp_headers=None, extras=None): 97 """Check HTTP response status is expected. 98 99 Args: 100 status: HTTP response status. int. 101 expected: a list of expected statuses. A list of ints. 102 path: filename or a path prefix. 103 headers: HTTP request headers. 104 resp_headers: HTTP response headers. 105 extras: extra info to be logged verbatim if error occurs. 106 107 Raises: 108 AuthorizationError: if authorization failed. 109 NotFoundError: if an object that's expected to exist doesn't. 110 TimeoutError: if HTTP request timed out. 111 ServerError: if server experienced some errors. 112 FatalError: if any other unexpected errors occurred. 113 """ 114 if status in expected: 115 return 116 117 msg = ('Expect status %r from Google Storage. But got status %d.\n' 118 'Path: %r.\n' 119 'Request headers: %r.\n' 120 'Response headers: %r.\n' 121 'Extra info: %r.\n' % 122 (expected, status, path, headers, resp_headers, extras)) 123 124 if status == httplib.UNAUTHORIZED: 125 raise AuthorizationError(msg) 126 elif status == httplib.FORBIDDEN: 127 raise ForbiddenError(msg) 128 elif status == httplib.NOT_FOUND: 129 raise NotFoundError(msg) 130 elif status == httplib.REQUEST_TIMEOUT: 131 raise TimeoutError(msg) 132 elif status == httplib.REQUESTED_RANGE_NOT_SATISFIABLE: 133 raise InvalidRange(msg) 134 elif (status == httplib.OK and 308 in expected and 135 httplib.OK not in expected): 136 raise FileClosedError(msg) 137 elif status >= 500: 138 raise ServerError(msg) 139 else: 140 raise FatalError(msg) 141