[web.py] Multiple Application with Same Context


In web.py official site, there is a code example which shows multiple sub applications [1]. In the example, the context web.ctx are modified in the sub application. This post shows multiple applications with the same context web.ctx, and runs both on Apache with mod_wsgi and Google App Engine Python (the same as [3]).

The point is to overwrite the _delegate_sub_application in web.applcation class. a customApp is declared:

class customApp(web.application):
  def _delegate_sub_application(self, dir, app):
    return app.handle_with_processors()

The customApp will be used for the mapping of applications.

Complete Source Code

delegate requests app

delegate.py | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python
# -*- coding:utf-8 -*-

# Simulate app.yaml of Google App Engine

import web
import staticweb
import mainweb

mapping = (
  r'/robots.txt', staticweb.app,
  r'/', mainweb.app,
)

class customApp(web.application):
  def _delegate_sub_application(self, dir, app):
    return app.handle_with_processors()

if __name__ == '__main__':
  app = customApp(mapping)
  app.run()

Note

web.py is not included in the third-party libraries in GAE Python 2.7. To use web.py on GAE, please download web.py from Github. Put the web directory in web.py repo and this "Hello World" application in the same directory.

main app

mainweb.py | repository | view raw
 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
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import web

urls = (
  r"/about", "AboutPage",
  r"/", "MainPage",
)

class AboutPage:
  def GET(self):
    return "Hello About"

class MainPage:
  def GET(self):
    return "Hello World"

app = web.application(urls, globals())
try:
  from google.appengine.ext import ndb
  # runs on Google App Engine
  app = app.gaerun()
except ImportError:
  application = app.wsgifunc()

static app

staticweb.py | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import web

urls = (
  r"/robots.txt", "StaticPage",
)


class StaticPage:
  def GET(self):
    return 'User-agent: *\nDisallow: /'


app = web.application(urls, globals())
try:
  from google.appengine.ext import ndb
  # runs on Google App Engine
  app = app.gaerun()
except ImportError:
  application = app.wsgifunc()

sample GAE Python config

app.yaml | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
application: webpy-multiple-app
version: 1
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /robots.txt
  script: staticweb.app

- url: /.*
  script: mainweb.app

sample Apache config

apache.conf | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<VirtualHost *:80>
        ServerName      {{ domain_name }}
        ServerAdmin     {{ email }}
        ErrorLog        {{ SOME_DIR }}/logs/error_log
        CustomLog       {{ SOME_DIR }}/logs/access_log combined

        Alias           /favicon.ico {{ REPO_DIR }}/favicon.ico
        Alias           /robots.txt {{ REPO_DIR }}/robots.txt

        WSGIScriptAlias / {{ REPO_DIR }}/mainweb.py

        AddType         text/html .py
</VirtualHost>

sample Makefile for development

Makefile | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# path of Google App Engine Python SDK
GAE_PY_SDK=../../../../../google_appengine

all: local

devserver:
	$(GAE_PY_SDK)/dev_appserver.py .

local:
	python delegate.py

clean:
	rm *.pyc

Tested on: Ubuntu Linux 14.10, Google App Engine Python SDK 1.9.18


References:

[1]using subapplications (web.py)
[2]Django style multiple apps with web.py (web.py)
[3][web.py] Web Application on Both Google App Engine and Apache