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__ = '[email protected] (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