Google App Engine

../../_images/appengine-logo.gif

Introduction

This howto will show you how to use a PyAMF application (0.3.1 or newer) with Google App Engine.

Google App Engine (GAE) lets you run your web applications on Google’s infrastructure for free. You can serve your app using a free domain name on the appspot.com domain, or use Google Apps to serve it from your own domain.

GAE applications are implemented using Python 2.5.2. The runtime environment includes the full Python language and most of the Python standard library, including Django.

Prerequisites

Before you can start using GAE you need to download and install:

Create Project

Start a new GAE project:

  • Create a new folder for your project
  • Copy main.py, app.yaml, and index.yaml from google_appengine/new_project_template to your new folder. On a Mac you can find it under /usr/local
  • Move the pyamf folder from your unpacked PyAMF-0.x.x folder to the root folder of the new GAE project

Using a terminal the steps above would translate into something like:

cp -R /usr/local/google_appengine/new_project_template MyProject
cp -R PyAMF-0.5.1/pyamf MyProject
cd MyProject
ls -l

The folder structure of your project should look something like this:

+ MyProject
  - app.yaml
  - index.yaml
  - main.py
  - pyamf

Application

You can setup your application using the WebAppGateway or the WSGIGateway.

WebApp Gateway

The pyamf.remoting.gateway.google.WebAppGateway class allows a GAE application to handle AMF requests on the root URL and other standard HTTP requests on another URL (/helloworld in the examples below).

The main.py module tells GAE what code to launch. Modify it for PyAMF:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import logging

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

from pyamf.remoting.gateway.google import WebAppGateway


class MainPage(webapp.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write('Hello, webapp World!')


def echo(data):
    return data


def main():
    debug_enabled = True

    services = {
        'myservice.echo': echo,
    }

    gateway = WebAppGateway(services, logger=logging, debug=debug_enabled)

    application_paths = [('/', gateway), ('/helloworld', MainPage)]
    application = webapp.WSGIApplication(application_paths, debug=debug_enabled)

    run_wsgi_app(application)


if __name__ == '__main__':
  main()

WSGI Gateway

If you don’t want to use the pure google.appengine approach as described above, you can also use pyamf.remoting.gateway.wsgi.WSGIGateway by modifying your main.py like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import logging
import wsgiref.handlers

from pyamf.remoting.gateway.wsgi import WSGIGateway


def echo(data):
    return data


def main():
    services = {
        'myservice.echo': echo,
    }

    gateway = WSGIGateway(services, logger=logging, debug=True)
    wsgiref.handlers.CGIHandler().run(gateway)


if __name__ == '__main__':
    main()

Start the server

Run this command from your application folder:

/usr/local/google_appengine/dev_appserver.py --debug --address=localhost --port=8080 .

Once the server started it usually prints something like:

INFO     2010-03-10 00:06:22,840 dev_appserver_main.py:399] Running application new-project-template on port 8080: http://localhost:8080

Test the application

When you visit http://localhost:8080/helloworld in your browser it should show a simple message:

Hello, webapp World!

The AMF gateway is available on http://localhost:8080, so this should return a 405 in the browser:

405 Method Not Allowed

To access this PyAMF gateway you must use POST requests (GET received)

Python

To test the gateway you can use a Python AMF client like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import logging

from pyamf.remoting.client import RemotingService

	
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)-5.5s [%(name)s] %(message)s'
)


path = 'http://localhost:8080/'
gw = RemotingService(path, logger=logging, debug=True)
service = gw.getService('myservice')

print service.echo('Hello World!')

Flash

Create a new Adobe Flash document and place a TextField on the stage. Make it dynamic in the Properties pane, and give it the instance name output. Then, paste the following code into the Actions pane:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import flash.net.*;

var netConnection:NetConnection = new NetConnection();
netConnection.connect("http://localhost:8080/");

var responder:Responder = new Responder(onComplete, onFail);
netConnection.call("myservice.echo", responder, "Flash talked to PyAMF.  They both say hello.");

function onComplete(results)
{
        output.htmlText = results;
}

function onFail(results)
{
        for each (var thisResult in results)
        {
                output.text += thisResult;
        }
}

Run Debug > Debug movie to test PyAMF with Google App Engine! Other examples for Flex etc can be found on the Examples page.

Useful Resources

http://aralbalkan.com/1307
Aral Balkan - Building Flash applications with Google App Engine.
Django
PyAMF integration with Django.
ByteArray
ByteArray example using Django and Flex.
http://blog.pyamf.org/archives/pyamf-and-google-app-engine
Related post on PyAMF blog.
http://pyamf.appspot.com/punit
Run the PyAMF test suite on the Google App Engine.