building an open social app with google app engine - open social
TRANSCRIPT
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
1/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
1/18wiki.opensocial.myspace.com/index.php?title=Building_an_
Home
Invite
Profile
Get Started
Foundation
Community
Docs
Building an OpenSocial App ith Google App
Engine
From OpenSocial
Jump to: navigation, search
Lane LiaBraaten, Google Deeloper Programs\ September 2008
While you can write OpenSocial apps that run solely in JavaScript and use the Persistence API to store data
on the container, many OpenSocial apps communicate with a third-party server for data storage or application
logic. Integrating with your own third-party server allows you to add new dimensions to your app, like
providing a data API, hosting static content, or allowing configuration through an admin console.
In this article, we'll build an app that is similar to the gift-giving application built in the OpenSocial tutorial.
When a user views the app, they see a drop-down menu of gifts (such as a peanut, or a red pistachio nut) and
another drop-down menu containing a list of their friends. The user can give any of these gifts to a friend and
the gift transaction will be displayed. The app will also display any gifts that the user has received. You can
find all the source code used to run this application in the opensocial-gifts project on Google Code ProjectHosting. You can also install this app on the orkut sandbox.
The original gift-giving app is built using 100% client-side OpenSocial code and is therefore subject to a
number of limitations imposed by the container rendering the app, such as the amount of data the container
will let you store, and the access controls related to when you can read and write data. With Google App
Engine, you can manage all this data on an external server, freeing your app from any constraints imposed by
the container. Viva la revolucin!
Contents[hide]
1 Audience
2 Architecture
2.1 Google App Engine app (app.yaml and gifts.py)
2.2 Database model (db_model.py)
2.3 Admin interface (admin.py)
2.4 JSON data API (api.py)
2.5 OpenSocial application spec (gifts.xml)
3 Setting up a Google App Engine app4 Using Google App Engine to store data
4.1 Defining the data model
4.2 Populating the datastore
4.3 Accessing the datastore
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
2/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
2/18wiki.opensocial.myspace.com/index.php?title=Building_an_
5 A G A E
5.1 C
5.2 F
5.3 I
5.4 I A
6 C API G A E
6.1 R G
6.2 R GT
6.3 R GT6.4 API R
7 S G A E
8 C OS G A E
8.1 P
8.2 R
8.3 R
8.4 R
8.5 R
8.6 S
9 N S
10 R10.1 D F
10.2 R
Audience
T G A E, OS. W'
, ' G A E G
S G O T.
OS JS HTML, '
. Y' P '
G A E . T , ' , '
, .
Note: Y' G A E SDK .
Architecture
B , ' OS ' .A , ' , , , (
). A ,
,
. T - ( ):
1. G A E
2. D
3. A
4. JSON API
5. OS
T : 0.
Google App Engine app (app.aml and gifts.p)
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
3/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
3/18wiki.opensocial.myspace.com/index.php?title=Building_an_
G A E app.aml
. I , ' gifts.p '
WSGIApplication .
Database model (db_model.p)
T G A E . W'
. W ' , ,
. W ID OS API .
Admin interface (admin.p)
W' G A E
. W' G A E'
. O
,
.
Note: G A E A C ,
, , ' .
JSON data API (api.p)
W' API ( G A E). T API
HTTP GET JSON . T API
HTTP POST .
OpenSocial application spec (gifts.ml)
O OS , XML . T
HTML JS OS , JS
- ' . T OS API G
A E gadgets.io.makeRequest .
Setting up a Google App Engine app
F applicaion idenifier . T G A E , , --sername
sername (.. --). I G A E ,
G A E . S A E
, (
' ). B , ,
sername-.
T : app.aml gifts.p. T app.aml
, P
. H' app.aml :
application: opensocial-gifts-username
version:1
runtime: pthon
api_version:1
handlers:
- url:/.*
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
4/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
4/18wiki.opensocial.myspace.com/index.php?title=Building_an_
ci: gif.
Noe: T aicai G E
sername (.. --).
I a.a , gif. /.*.
L' WSGIAicai gif. ReeHade
. H' gif.:
# Sadad ibaieimport gief.hade
# AEgie i
f gge.aegie.eimport eba
class SaiChec(eba.ReeHade):
def ge(ef):
ef.ee..rite("Y'e ca!")
# Ma URL ee hade classaicai = eba.WSGIAicai([('/', SaiChec)],
debg=True)
# Fie i !
gief.hade.CGIHade().(aicai)
N ' , ' . I ' ,
SDK . F gge_aegie , './de_aee.
;'. V ( URL
h://cah:8080/).
Uing Google App Engine o oe daa
T - OS P API . S VIEWER,
. F , ,
. A P API
. W' G A E .
Defining he daa model
W . F ,
. F , , ,
. W OS ID ,
db.Ke() .
T G A E , db_de.
P :
f gge.aegie.eimport db
class Gif(db.Mde):
ae= db.SigPe()
class GifTaaci(db.Mde):
ede_id = db.SigPe()
eceie_id = db.SigPe()gif = db.RefeecePe(Gif)
T Mde ,
.
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
5/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
5/18wiki.opensocial.myspace.com/index.php?title=Building_an_
Populating the datastore
Now that we have a data model, we need some way to populate it. Create a file called adi. and define an
Adi class to handle administrative operations like this. Let's start with two methods for initializing the gifts
and gift transactions in the datastore:
f db_de impo Gif, GifTaaci
cla Adi:
"""Iiiaie he i f gif i he daae."""
def iiGif(ef):
"""Deee a eiig gif ad add he defa gif."""
fo gif in Gif.a():
gif.delee()
GIFT_NAMES =['a cahe ',
'a ea',
'a hae',
'a ed iachi ']
foaein GIFT_NAMES:
gif = Gif()
gif.ae=ae
gif.()
def iiGifTaaci(ef):
"""Deee a eiig gif aaci."""
fo in GifTaaci.a():
.delee()
Accessing the datastore
Now let's add a couple methods to the Adi class for accessing the gifts and gift transactions in the
datastore.
def geGifNae(ef):
ae =[]
fo gif in Gif.a():
ae.aed(gif.ae)
en ae
def geGifTaaci(ef):
gifTaaci =[]
fo in GifTaaci.a():
gifTaaci.aed("ede: %, eciee: %, gif: %"%
(.ede_id, .eceie_id, .gif.e()))
en gifTaaci
Great, now we can read and write data in the datastorebut how do we invoke this Python code? That's
where the admin webapp comes into play.
A simple Google App Engine eb interface
Now we'll extend our Google App Engine application to include an admin web application so we can initialize
or view the data in the data store from a browser. We'll create a request handler so that we can invoke the
Adi class by sending a GET request to a certain URL, like http://opensocial-
gifts-sername.appspot.com/admin?action=init.
Creating a request handlerThe AdiSee class will be a subclass of the ReeHade class provided by the
gge.aegie.e.ebapackage. We can implement a ge method that will be invoked any time
the application forwards a request to this class. Add the following import statement and class definition to
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
6/18
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
7/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
7/18wiki.opensocial.myspace.com/index.php?title=Building_an_
rowse o e a m n conso e aga n an ou see a og n n . ou og n as a user a s no an
administrator of the Google App Engine app, ou'll see a message stating that "You must be an admin to view
this page."
Iig he Adi ca
Now we can add some code to invoke the Admin class b implementing the _handleRequest method from
the previous code snippet. The following method searches the request URL for a parameter called 'action'
and, based on this value, either initialies the datastore or lists the gifts and gift transactions.
def _handleRequest(self):
"""Invokes methods from the Admin class based on the 'action' parameter"""
admin = Admin()
action = self.request.get('action')
if action =='init':
admin.initGifts()
admin.initGiftTransactions()
msg ="Gifts have been initialized, gift transactions have been cleared."
self.response.out.rite(msg)
elif action =='list':
self.response.out.rite("Gifts = %s"% admin.getGiftNames())
self.response.out.rite("
")self.response.out.rite("Gift Transactions = %s"% admin.getGiftTransactions())
else:
html =[]
html.append('Initialize datastore
')html.append('List all data in datastore')
self.response.out.rite(''.join(html))
Note that if no 'action' parameter is given (or if the value is not 'init' or 'list') the handler will displa links to
initialie the datastore or list the gift data.
Ceaig a ie daa API ih Gge A Egie
Reeig Gif
Let's start b creating a request handler that will return the list of gifts in a JSON format. If a request comes in
to http://opensocial-gifts-sername.appspot.com/gifts, we should return:
["a cashew nut","a peanut","a hazelnut","a red pistachio nut"]
Create a file called api.py to contain the API request handler. Implement the get method to return the list of
gifts as a JSON string.
# App Engine importsfrom google.appengine.extimport webapp
# Third party imports
import json
# OpenSocial Gifts imports
from db_model import Gift, GiftTransaction
class ApiServer(webapp.RequestHandler):
"""Handles requests to /gifts URLs and reponds with JSON strings."""
def get(self):
"""Respond with a JSON string representation of the lists of gifts."""
gifts =[] for gift in Gift.all():
item={'key': str(gift.key()),
'name': gift.name
gifts.append(item)
self.response.out.rite(json.rite(gifts))
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
8/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
8/18wiki.opensocial.myspace.com/index.php?title=Building_an_
o e: ApiServer - . json.py
. T, P D!
N gifts.py '/' API
.
import admin
import api
# Map URLs to request handler classapplication = webapp.WSGIApplication([('/admin', admin.AdminServer),
'''('/gifts', api.ApiServer)'''],
debug=True)
Reeing GifTanacion
W GT , '
WGSIApplication gifts.py:
# Map URLs to request handler classapplication = webapp.WSGIApplication([('/admin', admin.AdminServer),
('/gifts', api.ApiServer), '''('/giftTransactions', api.ApiServer)'''],
debug=True)
N GET ApiServer
URL :
def get(self):
"""Call the appropriate handler based on the path of the HTTP request."""
if self.request.path.beginsWith('gifts'):
self._handleGifts()
elif self.request.path.beginsWith('giftTransactions'):
self._handleGiftTransactions()
def _handleGifts(self):
gifts =[]
for gift in Gift.all():
item={'key': str(gift.key()),
'name': gift.name
gifts.append(item)
self.response.out.rite(json.rite(gifts))
def _handleGiftTransactions(self):
#TODO(you)return a list of GiftTransactions as JSON
I , _handleGifts . N
_handleGiftTransactions.
W GiftTransactions :
. L' API ID URL
GiftTransactions .
def _returnGiftTransactions(self):
"""Return the list of transactions specified by the URL query parameters."""
sender_id = self.request.get("sender_id")
receiver_id = self.request.get("receiver_id")
giftTransactions = self._getGiftTransactions(sender_id, receiver_id)
results =[]
for giftTransaction in giftTransactions:
item={'sender_id': giftTransaction.sender_id,
'receiver_id': giftTransaction.receiver_id,
'gift_name': giftTransaction.gift.name
results.append(item)
self.response.out.rite(json.rite(results))
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
9/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
9/18wiki.opensocial.myspace.com/index.php?title=Building_an_
def _getGiftTransactions(self, sender_id, receiver_id):
results =[]
if sender_id:
results = GiftTransaction.gql('WHERE sender_id=:sender_id',
sender_id=sender_id)
elif receiver_id:
results = GiftTransaction.gql('WHERE receiver_id=:receiver_id',
receiver_id=receiver_id)
ele:
results = GiftTransaction.all()
en results;
Recording GiftTransactions
The last feature we need to add to the data API is the ability to record a new GiftTransaction. These
requests will come in as HTTP POST requests to the /giftTransactions path with the sender ID, receiver ID,
and gift key included as POST data. To handle this request, we simply need to implement a post method in
the ApiServer class.
def post(self):
"""Store a new gift transaction in the datastore based on the POST data."""giftTransaction = GiftTransaction()
giftTransaction.sender_id= self.request.get('sender_id')
giftTransaction.receiver_id= self.request.get('receiver_id')
giftTransaction.gift= Gift.get(self.request.get('gift_ke')).ke()
giftTransaction.put()
API Reference
Here's a summary of the API we just built:
HTTP
Method URL Description Eample Response
GET /giftsReturns the names and keys of all gifts in the datastore
as a JSON array.
[{"name" : "a peanut",
"key" : "ABC",
{"name" : "a
cashew",
"key" : "XYZ"]
GET/giftTransactions?
receiver_id=xxxx
Returns an array of gift transactions where the receiver
is specified by the URL parameter receiver_id.
[{"sender_id":"yyyy",
"receiver_id":"xxxx",
"gift_key":"XYZ",
{"sender_id":"zzzz",
"receiver_id":"xxxx","gift_key":"ABC"]
GET/giftTransactions?
sender_id=xxxx
Returns an array of gift transactions where the sender
is specified by the URL parameter sender_id.
[{"sender_id":"xxxx",
receiver_id:"yyyy",
gift_key:"XYZ",
{"sender_id":"xxxx",
receiver_id:"zzzz",
gift_key:"XYZ"]
HTTP
MethodURL Description Eample POST data
POST /giftTransactions
Creates a new gift transactionin the datastore based on the
sender, receiver, and gift key
specified in the POST data.
sender_id=xxxx&receiver_id=yyyy&gift_key=XYZ
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
10/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
10/18wiki.opensocial.myspace.com/index.php?title=Building_an_
erv ng s a c es w oog e pp ng ne
Y app.aml . J URL
. H'
app.aml :
application: opensocial-gifts-'''''username'''''
version:1
runtime: pthon
api_version:1
handlers:
'''- url: /static
static_dir: static'''
- url:/.*
script: gifts.p
Note: G A E 10 ,
app.aml . Y' C A .
I , static. T '
OS . C gifts.ml :
;
;
;
;
Hello, Google App Engine!
]]>;
;
;
B http://localhost:8080/static/gifts.ml OS
.
Communication between OpenSocial and Google App Engine
N API , OS
G A E . W'
- . T ' API
. F, ' POST API.
Publishing our app
U , ' () , OS
MS , . F
google_appengine , &;./appcfg.p update ;&;
. A ,
OS XML ://--sername//.
.
Requesting friends
T OS
- .
=" " =" - "
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
11/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
11/18wiki.opensocial.myspace.com/index.php?title=Building_an_
.
;
;
''''''
;
;
;
'''gadgets.util.registerOnLoadHandler(init);
function init() {
loadFriends();
function loadFriends() {
var req = opensocial.newDataRequest();
var viewerFriendsIdSpec = opensocial.newIdSpec({ "userId" : "VIEWER", "groupId" : "FRIENDS" );
var opt_params = {;
opt_params[opensocial.DataRequest.PeopleRequestFields.MAX] = 100;
req.add(req.newFetchPeopleRequest(viewerFriendsIdSpec, opt_params), 'viewerFriends');
req.send(onLoadFriends);
function onLoadFriends(data) {
var viewerFriends = data.get('viewerFriends').getData();
html = new Array();
html.push(';');
viewerFriends.each(function(person) {
html.push(';' + person.getDisplayName() + ";");
);
html.push(';');
document.getElementById('friends').innerHTML = html.join('');
;
;'''
]]>;
;
;
T loadFriends DataRequest OS
onLoadFriends . T onLoadFriends DataResponse
opensocial.Collection opensocial.Person
' . T - . T
- , ; , '' .
Reqeing gif
N, ' - . W' , -, HTML '' . F, '' :
;
;
;
;
;
;
;
;
'''Give ;; to ;;.''' ]]>;
;
;
N, loadGifts .
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
12/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
12/18wiki.opensocial.myspace.com/index.php?title=Building_an_
loadFriends();
'''loadGifts();'''
'''function loadGifts() {
var params = {;
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
var url = 'http://openocial-gif-'''''ename'''''.apppo.com/gif';
gadgets.io.makeRequest(url, onLoadGifts, params);
'''
T loadGifts gadgets.io.MakeRequest JSON
API . O , , onLoadGifts,
- .
fncion onLoadGifts(response){
ar gifts = response.data;
ar html =ne Array();
html.push(';');
for(ar i =0; i < gifts.length; i++){
html.push(';'+ gifts[i].name+';');
html.push(';');document.getElementById('gifts').innerHTML= html.join('');
Reeing gif anacion
N . S API ID,
' ID (
ID). W - ' ,
loadGiftTransactions '
API G A E . T , onLoadFriends
:
fncion onLoadFriends(data){
ar viewer = data.get('viewer').getData();
ar viewerFriends = data.get('viewerFriends').getData();
'''var friends = new Array();'''
html =ne Array();
html.push(';');
viewerFriends.each(fncion(person){
html.push(';'+ person.getDisplayName()+";");
'''friends[person.getId()] = person.getDisplayName();'''
);
html.push(';');document.getElementById('friends').innerHTML= html.join('');
'''loadGiftTransactions(viewer, friends);'''
I loadGiftTransactions, ' URL
API makeRequest . E makeRequest
, friends
onLoadFriends . H
loadGiftTransactions :
fncion loadGiftTransactions(viewer, friends){ // Ge he gif anacion hee he VIEWER i he ende
ar url ='http://opensocial-gifts-'''''username'''''/giftTransactions?sender_id='+ viewer.getId();
gadgets.io.makeRequest(url, onLoadGiftsGivenClosure(friends));
// Ge he gif anacion hee he VIEWER i he eceie
ar url ='htt : o ensocial- ifts-'''''username''''' iftTransactions?receiver id='+ viewer. etId
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
13/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
13/18wiki.opensocial.myspace.com/index.php?title=Building_an_
_
gadgets.io.makeRequest(url, onLoadGiftsReceivedClosure(friends));
fncion onLoadGiftsGivenClosure(friends){
rernfncion(response){
ar giftTransactions = gadgets.json.parse(response.data);
ar html =ne Array();
html.push('You have given:');
html.push('');
for(ar i=0; i
Give to .
'''
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
14/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
14/18wiki.opensocial.myspace.com/index.php?title=Building_an_
Give to .
'''Give!'''
Note: W JS , href="javascript:void(0);" . U
href="#" .
T giftGive VIEWER
. I , POST ( makeRequest)
API ID .
fncion giveGift(){
ar gift_key = document.getElementById('nut').value;
ar receiver_id = document.getElementById('person').value;
ar req = opensocial.newDataRequest();
req.add(req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER),'viewer');
req.send(postGiftTransactionClosure(receiver_id, gift_key));
fncion postGiftTransactionClosure(receiver_id, gift_key){
rernfncion(response){
ar sender_id = response.get('viewer').getData().getId();
ar params ={;params[gadgets.io.RequestParameters.METHOD]= gadgets.io.MethodType.POST;
post_data = gadgets.io.encodeValues({
'sender_id': sender_id,
'receiver_id': receiver_id,
'gift_key': gift_key );
params[gadgets.io.RequestParameters.POST_DATA]= post_data;
ar url = http://openocial-gif-'''''ename'''''/gifTanacion';
gadgets.io.makeRequest(url, loadFriends, params);
N makeRequest loadFriends. T .
Sending and verifing signed requests
Y ' API. OS
, , G A
E.
T OS , makeRequest
:
fncion postGiftTransactionClosure(receiver_id, gift_key){
rernfncion(response){
ar sender_id = response.get('viewer').getData().getId();
ar params ={;
'''params[gadgets.io.RequestParameters.AUTHORIZATION = gadgets.io.AuthorizationType.SIGNED;'''
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
15/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
15/18wiki.opensocial.myspace.com/index.php?title=Building_an_
params[gadgets.io.RequestParameters.METHOD]= gadgets.io.MethodType.POST;
post_data = gadgets.io.encodeValues({
'sender_id': sender_id,
'receiver_id': receiver_id,
'gift_key': gift_key );
params[gadgets.io.RequestParameters.POST_DATA]= post_data;
ar url ='http://opensocial-gifts-'''''username'''''/giftTransactions';
gadgets.io.makeRequest(url, loadFriends, params);
Using signed requests is most important when you're executing actions on the user's behalf since you don't
want a malicious user performing actions for a legitimate user. For example, a malicious user could send
POST requests to the /giftTransactions URL of our data API and include any sender ID, receiver ID, or
gift key. By signing your requests, you can protect your data from unauthorized accessif a request is
forged, you can reply with an error message or nothing at all.
You will need to add code to the api.py class to verify the signature received from the container. We can
implement an _isValidSignature()method and call it before processing GET or POST requests:
'''def _isValidSignature(self):
return False'''
def get(self):
"""Respond with a JSON string representation of the lists of gifts."""
'''if not self._isValidSignature():
self.response.out.write(json.write({))
return'''
if self.request.path.startswith('/gifts'):
self._returnGifts()
elif self.request.path.startswith('/giftTransactions'):
self._returnGiftTransactions()
def post(self): """Store a new gift transaction in the datastore based on the POST data."""
'''if not self._isValidSignature():
return'''
giftTransaction = GiftTransaction()
giftTransaction.sender_id= self.request.get('sender_id')
giftTransaction.receiver_id= self.request.get('receiver_id')
giftTransaction.gift= Gift.get(self.request.get('gift_key')).key()
giftTransaction.put()
OpenSocial uses OAuth's method for signing requests and containers may use the HMAC-SHA1 or RSA-
SHA1 algorithms. The following sample code demonstrates the RSA-SHA1 algorithm and assumes the
container is orkut. Orkut's public key is available in an x509 certificate, which has been parsed, converted tohex value, and hard-coded in the public_key_str variable.
import hashlib
import urllib
import oauth
from Crypto.PublicKeyimport RSA
from Crypto.Utilimport number
def _isValidSignature(self):
# Construct a RSA.pubkey object
exponent =65537public_key_str ="""0x\
00b1e057678343866db89d7dec2518\99261bf2f5e0d95f5d868f81d600c9\a101c9e6da20606290228308551ed3\acf9921421dcd01ef1de35dd3275cd\
4983c7be0be325ce8dfc3af6860f7a\
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
16/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
16/18wiki.opensocial.myspace.com/index.php?title=Building_an_
b0bf32742cd9fb2fcd1cd1756bbc40\
0b743f73acefb45d26694caf4f26b9\
765b9f65665245524de957e8c547c3\
58781fdfb68ec056d1"""
public_ke_long = long(public_ke_str,16)
public_ke = RSA.construct((public_ke_long, eponent))
# Rebuild the message hash locall
oauth_request = oauth.OAuthRequest(http_method=self.request.method,
http_url=self.request.url,
parameters=self.request.params.mied())message ='&'.join((oauth.escape(oauth_request.get_normalied_http_method()),
oauth.escape(oauth_request.get_normalied_http_url()),
oauth.escape(oauth_request.get_normalied_parameters()),))
local_hash = hashlib.sha1(message).digest()
# Appl the pblic ke to the signature from the remote host
sig = urllib.unquote(self.request.params.mied()["oauth_signature"]).decode('base64')
remote_hash = public_ke.encrpt(sig,'')[0][-20:]
# Verif that the locall-built value matches the value from the remote server.
rern local_hash==remote_hash
T _isValidSignature . OA' P
L C RSA . S !
I ' , - G
C OS , JSON
API, .
Net Steps
T G A E OS. T
:
D (H: static ).
E (..
).
U .
I .
A .
L .
C OS .
H !
Resources
Developer Forums
I ,
:
G A E D F
OS A D F
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
17/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
17/18wiki.opensocial.myspace.com/index.php?title=Building_an_
Google App Engine
Geing Saed Gide
Daaoe Refeence
Webapp Refeence
OpenSocial
OpenSocial Toial
JaaScip API Refeence
Deelope' Gide
Reieed fom "hp://iki.openocial.mpace.com/inde.php?
ile=Bilding_an_OpenSocial_App_ih_Google_App_Engine"
Vies
Page
Dicion
Vie oce
Hio
Personal tools
Log in / ceae accon
Naigation
Main Page
Conaine
JS API Refeence
Aicle & Toial
Conibing
Recen change
Random page
Help
Search
Go Seach
Toolbo
Wha link hee
Relaed change
Special page
Pinable eion
Pemanen link
Thi a e a la modified 23:57 26 Noembe 2010.
-
8/3/2019 Building an Open Social App With Google App Engine - Open Social
18/18
01.11.2011 Building an OpenSocial App with Google App Engine - Ope
This page has been accessed 42,903 times.
Privac polic
About OpenSocial
Disclaimers