Web APIs Mashup
in a Python Application
Johan Euphrosine @proppy
June 21, 2011
Johan Euphrosine @proppy
June 21, 2011
POST /urlshortener/v1/url HTTP/1.1
Content-Type: application/json
{
"longUrl": "http://www.verylongurl.com/"
}
HTTP/1.1 200 OK
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
"longUrl": "http://www.verylongurl.com/"
}
>>> import httplib2, json
>>> http = httplib2.Http()
>>> url = "https://www.googleapis.com/urlshortener/v1/url"
>>> response, content = http.request(url, "POST", body=json.dumps({
... "longUrl": "http://www.verylongurl.com/"
... }), headers={"content-type":"application/json"})
>>> json.loads(content)["id"]
u'http://goo.gl/bxJ6O'
POST /urlshortener/v1/url?key=xyz HTTP/1.1
Content-Type: application/json
{
"longUrl": "http://www.verylongurl.com/"
}
HTTP/1.1 200 OK
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
"longUrl": "http://www.verylongurl.com/"
}
>>> import httplib2, json
>>> http = httplib2.Http()
>>> url = "https://www.googleapis.com/urlshortener/v1/url"
>>> url += "?key=xyz"
>>> response, content = http.request(url, "POST", body=json.dumps({
... "longUrl": "http://www.verylongurl.com/"
... }), headers={"content-type":"application/json"})
>>> json.loads(content)["id"]
u'http://goo.gl/bxJ6O'
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | Authorization Grant & +---------------+
| |--(C)--- Client Credentials -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
proppy-ep2011.appspot.com
REDIRECT https://accounts.google.com/o/oauth2/auth? client_id=926365050982.apps.googleusercontent.com& redirect_uri=https://appid.appspot.com/back& scope=https://www.googleapis.com/auth/urlshortener& response_type=code
proppy-ep2011.appspot.com
if the User approved access:
https://appid.appspot.com/back?code=4/P7q8W92a-oMsCeLvIaQm6bTrgtp7
POST https://accounts.google.com/o/oauth2/token HTTP/1.1 code=4/P7q8W92a-oMsCeLvIaQm6bTrgtp7& client_id=21302922996.apps.googleusercontent.com& client_secret=XTHhXh1SlUNgvyWGwDk1EjXB& redirect_uri=https://www.example.com/back& grant_type=authorization_code
HTTP/1.1 200 OK
{
"access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
"expires_in": 3920,
"refresh_token": "1/6BMfW9j53gdGImsixUH6kU5RsR4zwI9lUVX-tqf8JXQ"
}
GET https://www.googleapis.com/urlshortener/v1/url/history Authorization: OAuth 1/fFAGRNJru1FTz70BzhT3Zg
HTTP/1.1 200 OK
{
"totalItems": 72,
"itemsPerPage": 30,
"nextPageToken": "2011-06-15T06:59:22.584+00:00",
"items": [
{
"kind": "urlshortener#url",
"id": "http://goo.gl/fbsS",
"longUrl": "http://www.verylongurl.com/",
"status": "OK",
"created": "2010-12-13T07:22:55.000+00:00",
} /* , ... */
]
}
application = webapp.WSGIApplication([
('/', MainHandler),
('/oauth2callback', OAuth2Handler)
])
def main():
util.run_wsgi_app(application)
CLIENT_ID = '926365050982.apps.googleusercontent.com'
CLIENT_SECRET = 'SnV9pONw92NBDFYMhkYhAKTJ'
SCOPE = 'https://www.googleapis.com/auth/urlshortener'
class MainHandler(webapp.RequestHandler):
def get(self):
args = {
'client_id': CLIENT_ID,
'redirect_uri': self.request.host_url+'/oauth2callback',
'scope': SCOPE,
'response_type': 'code'
}
authorize_url = ('https://accounts.google.com/o/oauth2/auth?'
+ urllib.urlencode(args))
self.redirect(authorize_url)
class OAuth2Handler(webapp.RequestHandler):
def get(self):
code = self.request.get('code')
args = {
'grant_type': 'authorization_code',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'code': code,
'redirect_uri': self.request.uri,
'scope': SCOPE
}
token_url = 'https://accounts.google.com/o/oauth2/token'
headers = {
'user-agent': 'app-id/1.0',
'content-type': 'application/x-www-form-urlencoded'
}
response, content = http.request(token_url, 'POST',
body=urllib.urlencode(args),
headers=headers)
access_token = json.loads(content)['access_token']
api_url = 'https://www.googleapis.com/urlshortener/v1/url/history'
response, content = http.request(api_url, headers={
'authorization': 'OAuth ' + access_token
})
self.response.out.write(content)
from oauth2client.appengine import OAuth2Decorator
from apiclient.discovery import build
decorator = OAuth2Decorator(
client_id='926365050982.apps.googleusercontent.com',
client_secret='SnV9pONw92NBDFYMhkYhAKTJ',
scope='https://www.googleapis.com/auth/urlshortener',
user_agent='app-id/1.0')
class MainHandler(webapp.RequestHandler):
@decorator.oauth_required
def get(self):
http = decorator.http()
service = build("urlshortener", "v1", http=http)
self.request.out.write(service.url().list().execute()['items'])
| Resource | URI | GET | PUT | POST | DELETE |
|---|---|---|---|---|---|
| Collection | /resources/ | List | Replace | Create | Delete |
| Element | /resources/id | Retrieve | Update | Create | Delete |
POST /buzz/v1/activities/@me/@self HTTP/1.1
Authorization: 1/fFAGRNJru1FTz70BzhT3Zg
Content-Type: application/json
{
"data": {
"object": {
"type": "note",
"content": "Is anybody listening ?"
}
}
}
GET /buzz/v1/people/@me/@groups/@followers HTTP/1.1
HTTP/1.1 200 OK
{
"data": {
"kind": "buzz#peopleFeed",
"entry": []
}
}
REDIRECT https://accounts.google.com/o/oauth2/auth? client_id=926365050982.apps.googleusercontent.com& redirect_uri=https://appid.appspot.com/back& scope=https://www.googleapis.com/auth/urlshortener%20\ https://www.googleapis.com/auth/buzz& response_type=code
proppy-ep2011.appspot.com
if the User approved access:
https://appid.appspot.com/back?code=4/P7q8W92a-oMsCeLvIaQm6bTrgtp7
decorator = OAuth2Decorator(
client_id='531740438494.apps.googleusercontent.com',
client_secret='GAo_rMg0oZsJrcdOY-PFbSaC',
scope=('https://www.googleapis.com/auth/urlshortener '
'https://www.googleapis.com/auth/buzz'),
user_agent='app-id/1.0')
class MainHandler(webapp.RequestHandler):
@decorator.oauth_required
def get(self):
long_url = unquote(self.request.get('url'))
http = decorator.http()
urlshortener = build('urlshortener', 'v1', http=http)
url = urlshortener.url()
short_url = url.insert(body={"longUrl": long_url}).execute()['id']
soup = BeautifulStoneSoup(urlopen(long_url),
convertEntities=BeautifulStoneSoup.ALL_ENTITIES)
title = soup.html.head.title.string
activity = {
'title': title,
'object': {
'type': 'note',
'content': '%s: %s' % (title, short_url)
}
}
buzz = build("buzz", "v1", http=http)
activities = buzz.activities()
activity = activities.insert(userId='@me', body=activity).execute()
self.redirect(activity['links']['alternate'][0]['href'])
GET /demo?url=http://ep2011.europython.eu/conference/talks/web-api...
proppy-ep2011.appspot.com
Feedback on @proppy / https://profiles.google.com/proppy
proppy-ep2011.appspot.com