Day 3: Responding to Requests in App Engine


When a request comes into a web server, that request has to be either processed or rejected. The request may be for static or dynamic content. So long as the web server can find something to respond to the request, the server will try. Otherwise, it will inform the caller that the resource cannot be found. Google App Engine supports both static and dynamic content. Our app.yaml file tells the server how to respond to different request types.

Handling Static Content in App Engine

When creating a web site, the site typically contains a fair number of static resources. These resources include cascading style sheets (CSS), JavaScript files (JS), images, static HTML, and so on. Most developers will structure their projects so that the folders are structured something like this

/Project

    /pages

    /scripts

    /theme

    /images

where pages contains static (or templatized) HTML, scripts contains JavaScript, theme contains elements for displaying the site (CSS and images), and images contains any stock content that is not specific to the theme. Additionally, a site will frequently want to customize the icon shown in the browser address bar by setting favicon.ico. To inform App Engine how to find this content, we write the following in our app.yaml:

handlers:

– url: /theme

  static_dir: theme

– url: /scripts

  static_dir: scripts

– url: /pages

  static_dir: /pages

– url: /favicon.ico

  static_files: favicon.ico

  upload: favicon.ico

  mime_type: application/octet-stream

The first set of entries contain a static_dir directive. This directive says that when someone requests data from the theme, scripts, or pages directory, go look in that directory and return any matching file. When we upload the application, the App Engine SDK will push up all the contents in these directories.

The work for favicon.ico is a bit different. This icon file sits in the root of the application and is requested by the browser. Because it is a single file, we map the url to the actual file, tell the toolkit which file to upload, and finally set the MIME type to use when sending the file as a response. octet-stream works for favicon.ico on all major browsers (Internet Explorer, Firefox, Opera, Chrome, and Safari).

Handling Dynamic Content in App Engine

Like with static content, we need to tell the web server what to do when a request for dynamic content comes in. Static content was handled by returning a file. Dynamic content is handled by passing the request off to a Python file. We tell App Engine how to do this through the following settings in app.yaml:

– url: /

  script: HelloWorld.py

With this, the request gets Python supports something called the Web Server Gateway Interface, aka WSGI. Through WSGI, one can map an incoming request to a specific class within the file.

application = webapp.WSGIApplication(

                                     [(‘/’, MainPage)],

                                      debug=True)

 

def main():

  run_wsgi_app(application)

 

if __name__ == "__main__":

  main()

The preceding code instantiates a variable, application, that maps the path / to a class named MainPage. This also turns on debugging for all paths so that any exceptions or other errors generated during request processing will be displayed in the response. To make it easier to respond to messages, the MainPage class inherits from google.appengine.ext.webapp.RequestHandler. This is a handy base class. As a developer, you decide which HTTP methods you need to handle and RequestHandler does the rest. To handle requests for data, one simply implements a method named get and the rest works out. To handle the standard HTTP methods, you would implement some combination of the following:

  • get
  • delete
  • put
  • post
  • head

This model allows one to respond directly to requests by writing all of the response information in code:

class MainPage(webapp.RequestHandler):

    def get(self):

        self.response.out.write("<html><body>Hello, World!</body></html>")

You can generate whatever content you like and put everything out using code. A more pleasant alternative is to use a web templating framework where you fill in values and then code the HTML creation based on those values. App Engine supports several web frameworks, including the popular Django. I did a minor dive into Django’s template language. To return a template, one simply loads up a set of values and then asks Django to process a template using those values. I was able to design the home page in an HTML editor. To set a few values and then load the template from a file relative to the current Python script, one writes:

template_values = {

    ‘username’: username,

    }

 

path = os.path.join(os.path.dirname(__file__), ‘pages/index.html’)

self.response.out.write(template.render(path, template_values))

The values are consumed in the html via markup like this:

Hello, {{ username }}!

%d bloggers like this: