1 # Copyright (C) 2008 Google Inc.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
16 __author__
= 'api.jscudder (Jeff Scudder)'
19 import wsgiref
.handlers
21 from google
.appengine
.ext
import webapp
22 from google
.appengine
.api
import users
25 import gdata
.alt
.appengine
29 class Fetcher(webapp
.RequestHandler
):
32 # Write our pages title
33 self
.response
.out
.write("""<html><head><title>
34 Google Data Feed Fetcher: read Google Data API Atom feeds</title>""")
35 self
.response
.out
.write('</head><body>')
36 next_url
= atom
.url
.Url('http', settings
.HOST_NAME
, path
='/step3')
37 # Allow the user to sign in or sign out
38 if users
.get_current_user():
39 self
.response
.out
.write('<a href="%s">Sign Out</a><br>' % (
40 users
.create_logout_url(str(next_url
))))
42 self
.response
.out
.write('<a href="%s">Sign In</a><br>' % (
43 users
.create_login_url(str(next_url
))))
45 # Initialize a client to talk to Google Data API services.
46 client
= gdata
.service
.GDataService()
47 gdata
.alt
.appengine
.run_on_appengine(client
)
49 feed_url
= self
.request
.get('feed_url')
52 # Find the AuthSub token and upgrade it to a session token.
53 auth_token
= gdata
.auth
.extract_auth_sub_token_from_url(self
.request
.uri
)
55 # Upgrade the single-use AuthSub token to a multi-use session token.
56 session_token
= client
.upgrade_to_session_token(auth_token
)
57 if session_token
and users
.get_current_user():
58 # If there is a current user, store the token in the datastore and
59 # associate it with the current user. Since we told the client to
60 # run_on_appengine, the add_token call will automatically store the
61 # session token if there is a current_user.
62 client
.token_store
.add_token(session_token
)
64 # Since there is no current user, we will put the session token
65 # in a property of the client. We will not store the token in the
66 # datastore, since we wouldn't know which user it belongs to.
67 # Since a new client object is created with each get call, we don't
68 # need to worry about the anonymous token being used by other users.
69 client
.current_token
= session_token
71 self
.response
.out
.write('<div id="main">')
72 self
.fetch_feed(client
, feed_url
)
73 self
.response
.out
.write('</div>')
74 self
.response
.out
.write(
75 '<div id="sidebar"><div id="scopes"><h4>Request a token</h4><ul>')
76 self
.response
.out
.write('<li><a href="%s">Google Documents</a></li>' % (
77 client
.GenerateAuthSubURL(
79 ('http://docs.google.com/feeds/',), secure
=False, session
=True)))
80 self
.response
.out
.write('</ul></div><br/><div id="tokens">')
82 def fetch_feed(self
, client
, feed_url
):
83 # Attempt to fetch the feed.
85 self
.response
.out
.write(
86 'No feed_url was specified for the app to fetch.<br/>')
87 example_url
= atom
.url
.Url('http', settings
.HOST_NAME
, path
='/step3',
89 'http://docs.google.com/feeds/documents/private/full'}
91 self
.response
.out
.write('Here\'s an example query which will show the'
92 ' XML for the feed listing your Google Documents <a '
93 'href="%s">%s</a>' % (example_url
, example_url
))
96 response
= client
.Get(feed_url
, converter
=str)
97 self
.response
.out
.write(cgi
.escape(response
))
98 except gdata
.service
.RequestError
, request_error
:
99 # If fetching fails, then tell the user that they need to login to
100 # authorize this app by logging in at the following URL.
101 if request_error
[0]['status'] == 401:
102 # Get the URL of the current page so that our AuthSub request will
103 # send the user back to here.
104 next
= atom
.url
.Url('http', settings
.HOST_NAME
, path
='/step3',
105 params
={'feed_url': feed_url
})
106 # If there is a current user, we can request a session token, otherwise
107 # we should ask for a single use token.
108 auth_sub_url
= client
.GenerateAuthSubURL(next
, feed_url
,
109 secure
=False, session
=True)
110 self
.response
.out
.write('<a href="%s">' % (auth_sub_url
))
111 self
.response
.out
.write(
112 'Click here to authorize this application to view the feed</a>')
114 self
.response
.out
.write(
115 'Something went wrong, here is the error object: %s ' % (
116 str(request_error
[0])))
120 application
= webapp
.WSGIApplication([('/.*', Fetcher
),], debug
=True)
121 wsgiref
.handlers
.CGIHandler().run(application
)
124 if __name__
== '__main__':