Path prefix


  • /
  • /blog/
  • /tasks/
  • /lists/1/
  • /lists/2/
  • /lists/ 

When a project-aware request arrives for a path that doesn’t match a known view, the system looks for a registered ProjectProxyPath matching the requested path.

The system will prefer the most specific match — GET /lists/1/archive/2013/01/ will match a ProjectProxyPath registered at /lists/1/archive/2013/01/ if present; if /lists/1/ and /lists/ are both registered, /lists/1/ will be preferred; and a ProjectProxyPath registered at / (if present) will match if nothing else does. 

The active ProjectProxyPath will include a tool_dottedname which refers to a tool instance factory:

tool_factory = resolve(active_proxy_path.tool_dottedname)
tool = tool_factory(active_proxy_path)

With a tool in hand we can now determine the active deliverance ruleset and other configuration:

return {
  "rules": tool.deliverance_ruleset,
  "proxy_base_url": tool.proxy_base_url,
  "trusted": tool.trusted,

It’s up to the tool instance’s Python code to decide how to determine those attributes.  (@@TODO: probably script_name and path_info don’t get to vary, that’s in the wrong place.)  The ProjectProxyPath object has a nullable TEXT column “configuration” which may be used in any way by the tool’s code to determine its attributes; for example it might load that column as a JSON blob and then return the attributes straight from the underlying database entry:

class GenericTool(object):
  def __init__(self, proxy):
       self.proxy = proxy
       config = json.loads(proxy.configuration)
       self.rules = config['deliverance_ruleset']
       self.proxy_base_url = config['proxy_base_url']
       self.trusted = config.get('trusted') or False

Why not just get those straight from the active ProjectProxyPath’s database entry always?

Because some tools may want to vary less.

For example, a tool class could be built that, when installed and configured, provides a proxy to a particular mailing list on  A single deliverance ruleset would be developed — once — that covers the logic of theming any librelist’s archives.  And when installing and configuring the tool, the project admin should only be able to specify the URL of the list to proxy to.

In this case, the “configuration” column might just contain the URL of the list to proxy to, and the rest would be hardcoded in Python:

class LibreListTool(object):
  def __init__(self, proxy):
    self.proxy = proxy
    self.proxy_base_url = "" % proxy.configuration
    self.trusted = False 

Hardcoding the commonalities for this tool would have several advantages — redundant data wouldn’t be stored N times in the database, and if the deliverance rules need to change in the future this could be done just in a code upgrade, without migrating content.

Filed March 31st, 2013 under thing

A project container provides:

  • A “summary” page with RSS feeds 
  • HTTP proxies
  • A navigation bar
  • Management links, and a management dashboard
  • Search links, and a search dashboard
  • A “getting started” dashboard
  • A “project contents” screen or dashboard 
  • An export screen
  • A team screen, and a “manage team” screen
  • A screen for managing RSS feeds (which feeds are present, and in what order)
  • A screen for managing the navigation bar (which links are present, and in what order)


Tools may implement providers for some of these:

  • Tools may offer zero or more RSS sources to the summary page.
    • Each RSS source contains a title, a URL, a boolean flag vary_on_user, and a boolean flag feed_is_public.
    • Each RSS source may contain an icon URL.
    • If feed_is_public, the container may display the URL of the feed.  If feed_is_public is set to False, the container must not display the feed’s URL anywhere.  (Use case: basic auth protected feeds; security-by-obscurity feeds with unguessable URLs)
    • If vary_on_user, the container must cache each feed separately per logged-in user.
    • The container may decide whether to cache each feed, and how to expire the cache.  Each feed source has no say in this.
  • Tools may offer zero or more nav entry to the navigation bar.
    • Each nav entry contains a title and a URL.
  • Tools may provide zero or more HTTP proxy configurations.
    • Each proxy has a URL prefix that it matches on.
    • Each proxy has a deliverance ruleset to be applied to its response.
    • Each proxy has a boolean flag that specifies whether the proxy connection is trusted.  A proxy connection should only be trusted if it is a local network connection OR is an HTTPS connection; AND the proxied server is trusted.
  • Tools may provide zero or more views.
    • These can be used for things like configuration screens that need to be set up in the Django application instead of in the proxied application.
Filed March 31st, 2013 under thing