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 
20 It takes a bucket name in the URL path and does an HTTP GET on the
21 corresponding Google Cloud Storage URL to obtain a listing of the bucket
22 contents. For example, if this app is invoked with the URI
23 http://bucket-list.appspot.com/foo, it would remove the bucket name 'foo',
24 append it to the Google Cloud Storage service URI and send a GET request to
25 the resulting URI. The bucket listing is returned in an XML document, which is
26 prepended with a reference to an XSLT style sheet for human readable
27 presentation.
28 
29 More information about using Google App Engine apps and service accounts to
30 call 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 
38 import httplib2
39 import logging
40 import os
41 import pickle
42 import re
43 
44 from google.appengine.api import memcache
45 from google.appengine.ext import webapp
46 from google.appengine.ext.webapp import template
47 from google.appengine.ext.webapp.util import run_wsgi_app
48 from oauth2client.contrib.appengine import AppAssertionCredentials
49 
50 # Constants for the XSL stylesheet and the Google Cloud Storage URI.
51 XSL = '\n<?xml-stylesheet href="/listing.xsl" type="text/xsl"?>\n';
52 URI = 'http://commondatastorage.googleapis.com'
53 
54 # Obtain service account credentials and authorize HTTP connection.
55 credentials = AppAssertionCredentials(
56     scope='https://www.googleapis.com/auth/devstorage.read_write')
57 http = credentials.authorize(httplib2.Http(memcache))
58 
59 
60 class 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 
87 def main():
88   application = webapp.WSGIApplication(
89       [
90        ('.*', MainHandler),
91       ],
92       debug=True)
93   run_wsgi_app(application)
94 
95 
96 if __name__ == '__main__':
97   main()
98