Home | History | Annotate | Download | only in cloudstorage
      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 
     33 import httplib
     34 
     35 
     36 class 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 
     45 class TransientError(Error):
     46   """TransientError could be retried."""
     47 
     48 
     49 class TimeoutError(TransientError):
     50   """HTTP 408 timeout."""
     51 
     52 
     53 class FatalError(Error):
     54   """FatalError shouldn't be retried."""
     55 
     56 
     57 class 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 
     65 class NotFoundError(FatalError):
     66   """HTTP 404 resource not found."""
     67 
     68 
     69 class 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 
     77 class 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 
     87 class InvalidRange(FatalError):
     88   """HTTP 416 RequestRangeNotSatifiable."""
     89 
     90 
     91 class ServerError(TransientError):
     92   """HTTP >= 500 server side error."""
     93 
     94 
     95 def 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