pyjs' kitchensink comes with a JSON-RPC example, this posting shows how to use Appengine to serve as a JSON-RPC server for the pyjs json-rpc example.
(Rough) Steps:
1) download appengine SDK and create an appengine application (in the dashboard)
2) download pyjs
3) Replace pyjs example/jsonrpc/JSONRPCExample.py with this code
from ui import RootPanel, TextArea, Label, Button, HTML, VerticalPanel, HorizontalPanel, ListBox
from JSONService import JSONProxy
class JSONRPCExample:
def onModuleLoad(self):
self.TEXT_WAITING = "Waiting for response..."
self.TEXT_ERROR = "Server Error"
self.remote_py = UpperServicePython()
self.status=Label()
self.text_area = TextArea()
self.text_area.setText(r"Please uppercase this string")
self.text_area.setCharacterWidth(80)
self.text_area.setVisibleLines(8)
self.button_py = Button("Send to Python Service", self)
buttons = HorizontalPanel()
buttons.add(self.button_py)
buttons.setSpacing(8)
info = r'This example demonstrates the calling of appengine upper(case) method with JSON-RPC from javascript (i.e. Python code compiled with pyjs to javascript).'
panel = VerticalPanel()
panel.add(HTML(info))
panel.add(self.text_area)
panel.add(buttons)
panel.add(self.status)
RootPanel().add(panel)
def onClick(self, sender):
self.status.setText(self.TEXT_WAITING)
text = self.text_area.getText()
if self.remote_py.upper(self.text_area.getText(), self) < 0:
self.status.setText(self.TEXT_ERROR)
def onRemoteResponse(self, response, request_info):
self.status.setText(response)
def onRemoteError(self, code, message, request_info):
self.status.setText("Server Error or Invalid Response: ERROR " + code + " - " + message)
class UpperServicePython(JSONProxy):
def __init__(self):
JSONProxy.__init__(self, "/json", ["upper"])
4) Use the following code for the appengine app
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
import logging
from django.utils import simplejson
class JSONHandler(webapp.RequestHandler):
def json_upper(self,args):
return [args[0].upper()]
def post(self):
args = simplejson.loads(self.request.body)
json_func = getattr(self, 'json_%s' % args[u"method"])
json_params = args[u"params"]
json_method_id = args[u"id"]
result = json_func(json_params)
# reuse args to send result back
args.pop(u"method")
args["result"] = result[0]
args["error"] = None # IMPORTANT!!
self.response.headers['Content-Type'] = 'application/json'
self.response.set_status(200)
self.response.out.write(simplejson.dumps(args))
application = webapp.WSGIApplication(
[('/json', JSONHandler)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
5) compile pyjs code in 3) and create static dir in appengine app to store compiled code (i.e in app.yaml)
6) use dev_appserver.py to test locally or appcfg.py to deploy on appengine
7) a testable version is on https://testulf3.appspot.com/static/JSONRPCExample.html .
Facebook application
By using this recipe it was easy to create a facebook app of the example in this posting - check it out at http://apps.facebook.com/testulf/
Alternative backend - using webpy
This shows how to use webpy as backend, just put the javascript/html resulting from pyjs compile into the static/ directory. Very similar as the previous approach, with the code in blue being the main diff (i.e. webpy specific)
import web
import json
urls = (
'/json', 'jsonhandler'
)
app = web.application(urls, globals())
class jsonhandler:
def json_upper(self,args):
return [args[0].upper()]
def json_markdown(self,args):
return [args[0].lower()]
def POST(self):
args = json.loads(web.data())
json_func = getattr(self, 'json_%s' % args[u"method"])
json_params = args[u"params"]
json_method_id = args[u"id"]
result = json_func(json_params)
# reuse args to send result back
args.pop(u"method")
args["result"] = result[0]
args["error"] = None # IMPORTANT!!
web.header("Content-Type","text/html; charset=utf-8")
return json.dumps(args)
if __name__ == "__main__":
app.run()