Page "Proposals/BEP-0003" was changed by olemis
Diff URL: 
<https://issues.apache.org/bloodhound/wiki/Proposals/BEP-0003?action=diff&version=18>
Revision 18
Comment: [BEP-0003] External environment routes (using Routes framework)
Changes:
-------8<------8<------8<------8<------8<------8<------8<------8<--------
Index: Proposals/BEP-0003
=========================================================================
--- Proposals/BEP-0003 (version: 17)
+++ Proposals/BEP-0003 (version: 18)
@@ -94,6 +94,58 @@
 
 [=#product-env-idem] The following methods and options will behave exactly the 
same as the corresponding `parent_env`'s methods: ''get_system_info'' , 
''components_section'' , '''TODO''' .
 
+=== Product routes #routes
+
+[http://routes.groovie.org/ Routes] framework will be used to match URLs based 
on predefined patterns and use this information to dispatch requests addressed 
to product environments. This will introduce an explicit installation 
dependency with that framework. 
+
+In first place there will be an instance of `routes.mapper.Mapper`. It will 
contain the definitions of the routes used to access product environments and 
their resources. Some variables in routes definitions will have special meaning 
though.
+
+||= Variable =||= Purpose =||= Observations =||
+|| `controller` || ''Ignored'' ||  ||
+|| `action` || ''Ignored'' ||  ||
+|| `envname` || Target environment name || Only used in multiple environment 
mode to determine target environment folder. Ignored otherwise. ||
+|| `product` || Target product prefix || Represents  ||
+|| `path_info` || Path to product resource or view  || Since paths under 
product base URL will be used to access anything that could be considered as 
belonging to the product, route definitions often will include 
[http://routes.readthedocs.org/en/latest/setting_up.html#magic-path-info 
path_info] to shift `SCRIPT_NAME` and `PATH_INFO` ''WSGI'' variables as 
expected ||
+
+Considering the previous discussion ''Bloodhound'' will provide a modified 
copy of the main entry point for the web interface (i.e. the 
[http://www.python.org/dev/peps/pep-0333/ WSGI] function 
`trac.web.main.dispatch_request`) to make it aware of external routing 
information. It will be wrapped by a `routes.middleware.RoutesMiddleware` 
object responsible for route matching and ''WSGI'' environment updates. This 
fact is important to understand subsequent discussion taking place in this 
section.
+
+Aforementioned data will be considered to dispatch requests in addition to the 
existing ''WSGI'' environment variables (i.e. `trac.env_path`, 
`trac.env_parent_dir`, `trac.env_index_template`, `trac.template_vars`, 
`trac.base_url`, `trac.env_paths`) or the equivalent global variables (i.e. 
`TRAC_ENV`, `TRAC_ENV_PARENT_DIR`, `TRAC_ENV_INDEX_TEMPLATE`, 
`TRAC_TEMPLATE_VARS`, `TRAC_BASE_URL`). The updated copy of 
`trac.web.main.dispatch_request` will read routing information like shown below
+
+{{{
+#!py
+
+route = environ.get('routes.route')
+match = environ.get('wsgiorg.routing_args', (None, {}) )[1]
+
+}}}
+
+As a result the following rules will be used to determine the environment 
performing subsequent request dispatching :
+
+  - If `match == {}` (equivalent to `route is None`)
+    then no route was matched, hence respond with a 
+    404 (''Not Found'') HTTP status code.
+  - ... else if `match['envname']` is empty then no 
+    specific environment was requested. 
+    * For multi-environment deployments 
+      (i.e. `TRAC_ENV_PARENT_DIR`) just render an 
+      environment index page.
+    * For single-environment deployments always 
+      instantiate configured environment.
+  - ... for multi-environment deployments, if 
+    `match['envname']` is not empty then 
+    instantiate the environment at the corresponding 
+    child folder of the parent directory.
+  - ... if `match['product']` is empty then the 
+    global environment found up to this point will dispatch the 
+    request
+  - ... else if `match['product']` is set then 
+    [#product-env-api instantiate the product environment]
+    for the corresponding product prefix. There will
+    an instance of `trac.web.main.RequestDispatcher`
+    responsible for dispatching the request.
+
+Sub-paths will be handled from there as usual.
+
 === Database schema changes #database-schema-changes
 
 Products shall become a first-class citizen in ''Bloodhound''. To make this 
possible, some changes will be required at the database schema level, 
especially as multiple product environments are meant to be hosted in the same 
database instance.
@@ -110,6 +162,13 @@
 This could be accomplished using the same approach as used in relation to 
tickets - by extending the database tables with the 'product' field that would 
reference the product that the specified entities belong to.
 
 Another change required is the change of the fore mentioned table keys. As it 
currently stands, the key used in these tables is limited to the 'name' field. 
As this (in the modified schema) prevents users from creating 
versions/milestones/... with the same name for different products, key should 
be extended with the 'product' field.
+
+=== Administration commands #admin-cmd
+
+The following new [TracAdmin administration commands] will be implemented
+
+||= Command =||= Parameters =||= Description =||
+|| `deploy-multiproduct` || '''TODO''' || In a way similar to built-in 
''deploy'' command it will extract environment assets and create scripts for 
[#url-mapping default deployment] via CGI, FastCGI or mod_wsgi. ||
 
 == Rationale #rationale
 
@@ -248,7 +307,6 @@
 }}}
 
 '''TODO'''
-
 }}}
 
   - [=#deploy-sibling-paths] '''Product path namespace''' : Each product is 
@@ -267,7 +325,50 @@
 
 This case is very similar to the [./MultienvParentDir reference 
multi-environment setup] .
 
-'''TODO'''
+Considering the [#routes enhanced routing mechanism] the following routes 
definition will be suitable for single-environment installations
+
+{{{
+#!py
+
+>>> from wsgiref.util import setup_testing_defaults as wsgi_environ
+>>> from routes import Mapper
+>>> m = Mapper()
+>>> m.connect(None, '/path/to/bloodhound/{product}/{path_info:.*}')
+>>> m.match('/path/to/bloodhound/product1/ticket/1')
+{'action': u'index', 'product': u'product1', 'controller': u'content', 
'path_info': 'ticket/1'}
+
+}}}
+
+If the global environment will be treated as yet another sibling product 
environment
+
+{{{
+#!py
+
+>>> from wsgiref.util import setup_testing_defaults as wsgi_environ
+>>> from routes import Mapper
+>>> m = Mapper()
+>>> m.connect(None, '/path/to/bloodhound/global/{path_info:.*}', product='')
+>>> m.connect(None, '/path/to/bloodhound/{product}/{path_info:.*}')
+>>> m.match('/path/to/bloodhound/global/ticket/1')
+{'action': u'index', 'product': u'', 'controller': u'content', 'path_info': 
'ticket/1'}
+>>> m.match('/path/to/bloodhound/product1/ticket/1')
+{'action': u'index', 'product': u'product1', 'controller': u'content', 
'path_info': 'ticket/1'}
+
+}}}
+
+For multi-environment installations
+
+{{{
+#!py
+
+>>> from wsgiref.util import setup_testing_defaults as wsgi_environ
+>>> from routes import Mapper
+>>> m = Mapper()
+>>> m.connect(None, '/path/to/bloodhound/{envname}/{product}/{path_info:.*}')
+>>> m.match('/path/to/bloodhound/enterprise/product1/ticket/1')
+{'action': u'index', 'product': u'product1', 'envname': u'enterprise', 
'controller': u'content', 'path_info': 'ticket/1'}
+
+}}}
 
 }}}
 
@@ -285,7 +386,7 @@
 }}} 
 Even if this case is very similar to the [./MultienvParentDir reference 
multi-environment setup] a better match will be another setup based on 
[TracHacks:TracWsgiPlugin]. The main difference with respect to 
[#deploy-sibling-paths sibling paths] deployment is that the global environment 
plays an active role dispatching the requests addressed to an specific product 
by forwarding them to the corresponding product environment.
 
-'''TODO'''
+This particular case does not even need to make use of the [#routes enhanced 
routing mechanism]. Instead of external routes definitions , a component 
(request handler) will be enabled in the global environment. It will handle 
requests sent to sub-paths of the form `product/<product 
prefix>/path/to/resource` relative to the global environment's base URL. 
Products base URL will be `product/<product prefix>` as a result. In its 
`process_request` method it will forward request dispatching to the instance of 
`trac.web.main.RequestDispatcher` of the corresponding product environment.
 
 }}}
 
@@ -312,10 +413,10 @@
 
 }}}
 
-  - [=#deploy-domain-path] '''Arbitrary product path namespace''' : 
+  - [=#deploy-complex-path] '''Arbitrary product path namespace''' : 
     Sometimes hosting providers like forges do not 
     support product sub-domains . Hence 
-    product prefix is included in URL. 
+    product prefix is included in URL path. 
     In general, product base URLs will look like this
     `http://domain.tld/path/to/<product prefix>/path/to/bloodhound` . 
     One such hypothetical example would be 
@@ -331,7 +432,47 @@
   Implementation notes
 }}} 
 
-'''TODO'''
+Considering the [#routes enhanced routing mechanism] the following routes 
definition will be suitable for single-environment installations
+
+{{{
+#!py
+
+>>> from wsgiref.util import setup_testing_defaults as wsgi_environ
+>>> from routes import Mapper
+>>> m = Mapper()
+>>> m.connect(None, 
'/path/to/bloodhound/{product}/path/to/bloodhound/{path_info:.*}')
+>>> m.match('/path/to/bloodhound/product1/path/to/bloodhound/ticket/1')
+{'action': u'index', 'product': u'product1', 'controller': u'content', 
'path_info': 'ticket/1'}
+
+}}}
+
+The example mentioned above for ''Allura'' 
+
+{{{
+#!py
+
+>>> from wsgiref.util import setup_testing_defaults as wsgi_environ
+>>> from routes import Mapper
+>>> m = Mapper()
+>>> m.connect(None, '/p/{product}/bloodhound/{path_info:.*}')
+>>> m.match('/p/product1/bloodhound/ticket/1')
+{'action': u'index', 'product': u'product1', 'controller': u'content', 
'path_info': 'ticket/1'}
+
+}}}
+
+For multi-environment installations
+
+{{{
+#!py
+
+>>> from wsgiref.util import setup_testing_defaults as wsgi_environ
+>>> from routes import Mapper
+>>> m = Mapper()
+>>> m.connect(None, 
'/{envname}/path/to/bloodhound/{product}/path/to/bloodhound/{path_info:.*}')
+>>> m.match('/company/path/to/bloodhound/product1/path/to/bloodhound/ticket/1')
+{'action': u'index', 'product': u'product1', 'envname': u'company', 
'controller': u'content', 'path_info': 'ticket/1'}
+
+}}}
 
 }}}
 
@@ -365,7 +506,7 @@
 
 The final solution will be prepared to import data from other issue tracker 
systems and still provide a similar user experience. Important examples to 
consider are :
 
-  - Exisiting ''Trac'' and ''Bloodhound'' instances without multi-product 
support
+  - Existing ''Trac'' and ''Bloodhound'' instances without multi-product 
support
   - [http://www.atlassian.com/en/software/jira/overview JIRA]
   - [http://www.bugzilla.org/ Bugzilla]
   - [http://scarab.tigris.org/ Scarab]
-------8<------8<------8<------8<------8<------8<------8<------8<--------

--
Page URL: <https://issues.apache.org/bloodhound/wiki/Proposals/BEP-0003>
Apache Bloodhound <https://issues.apache.org/bloodhound/>
The Apache Bloodhound (incubating) issue tracker

This is an automated message. Someone added your email address to be
notified of changes on 'Proposals/BEP-0003' page.
If it was not you, please report to .

Reply via email to