1#!/usr/bin/env python 2# 3# Copyright 2014 Google Inc. All Rights Reserved. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17"""This application produces formatted listings for Google Cloud 18 Storage buckets. 19 20It takes a bucket name in the URL path and does an HTTP GET on the 21corresponding Google Cloud Storage URL to obtain a listing of the bucket 22contents. For example, if this app is invoked with the URI 23http://bucket-list.appspot.com/foo, it would remove the bucket name 'foo', 24append it to the Google Cloud Storage service URI and send a GET request to 25the resulting URI. The bucket listing is returned in an XML document, which is 26prepended with a reference to an XSLT style sheet for human readable 27presentation. 28 29More information about using Google App Engine apps and service accounts to 30call Google APIs can be found here: 31 32<https://developers.google.com/accounts/docs/OAuth2ServiceAccount> 33<http://code.google.com/appengine/docs/python/appidentity/overview.html> 34""" 35 36__author__ = 'marccohen@google.com (Marc Cohen)' 37 38import httplib2 39import logging 40import os 41import pickle 42import re 43 44from google.appengine.api import memcache 45from google.appengine.ext import webapp 46from google.appengine.ext.webapp import template 47from google.appengine.ext.webapp.util import run_wsgi_app 48from oauth2client.contrib.appengine import AppAssertionCredentials 49 50# Constants for the XSL stylesheet and the Google Cloud Storage URI. 51XSL = '\n<?xml-stylesheet href="/listing.xsl" type="text/xsl"?>\n'; 52URI = 'http://commondatastorage.googleapis.com' 53 54# Obtain service account credentials and authorize HTTP connection. 55credentials = AppAssertionCredentials( 56 scope='https://www.googleapis.com/auth/devstorage.read_write') 57http = credentials.authorize(httplib2.Http(memcache)) 58 59 60class MainHandler(webapp.RequestHandler): 61 62 def get(self): 63 try: 64 # Derive desired bucket name from path after domain name. 65 bucket = self.request.path 66 if bucket[-1] == '/': 67 # Trim final slash, if necessary. 68 bucket = bucket[:-1] 69 # Send HTTP request to Google Cloud Storage to obtain bucket listing. 70 resp, content = http.request(URI + bucket, "GET") 71 if resp.status != 200: 72 # If error getting bucket listing, raise exception. 73 err = 'Error: ' + str(resp.status) + ', bucket: ' + bucket + \ 74 ', response: ' + str(content) 75 raise Exception(err) 76 # Edit returned bucket listing XML to insert a reference to our style 77 # sheet for nice formatting and send results to client. 78 content = re.sub('(<ListBucketResult)', XSL + '\\1', content) 79 self.response.headers['Content-Type'] = 'text/xml' 80 self.response.out.write(content) 81 except Exception as e: 82 self.response.headers['Content-Type'] = 'text/plain' 83 self.response.set_status(404) 84 self.response.out.write(str(e)) 85 86 87def main(): 88 application = webapp.WSGIApplication( 89 [ 90 ('.*', MainHandler), 91 ], 92 debug=True) 93 run_wsgi_app(application) 94 95 96if __name__ == '__main__': 97 main() 98