3
3
Application Dispatching
4
4
=======================
5
5
6
+ Application dispatching is the process of combining multiple Flask
7
+ applications on the WSGI level. You can not only combine Flask
8
+ applications into something larger but any WSGI application. This would
9
+ even allow you to run a Django and a Flask application in the same
10
+ interpreter side by side if you want. The usefulness of this depends on
11
+ how the applications work internally.
12
+
13
+ This is fundamentally different from the :ref: `module approach
14
+ <larger-applications>` is that in this case you are running the same or
15
+ different Flask applications that are entirely isolated from each other.
16
+ They run different configurations and are dispatched on the WSGI level.
17
+
18
+ Combining Applications
19
+ ----------------------
20
+
21
+ If you have entirely separated applications and you want them to work next
22
+ to each other in the same Python interpreter process you can take
23
+ advantage of the :class: `werkzeug.wsgi.DispatcherMiddleware `. The idea
24
+ here is that each Flask application is a valid WSGI application and they
25
+ are combined by the dispatcher middleware into a larger one that
26
+ dispatched based on prefix.
27
+
28
+ For example you could have your main application run on `/ ` and your
29
+ backend interface on `/admin `::
30
+
31
+ from werkzeug.wsgi import DispatcherMiddleware
32
+ from frontend_app import application as frontend
33
+ from backend_app import application as backend
34
+
35
+ application = DispatcherMiddleware(frontend, {
36
+ '/backend': backend
37
+ })
38
+
39
+
40
+ Dispatch by Subdomain
41
+ ---------------------
42
+
6
43
Sometimes you might want to use multiple instances of the same application
7
44
with different configurations. Assuming the application is created inside
8
45
a function and you can call that function to instanciate it, that is
9
46
really easy to implement. In order to develop your application to support
10
47
creating new instances in functions have a look at the
11
48
:ref: `app-factories ` pattern.
12
49
13
-
14
- Dispatch by Subdomain
15
- ---------------------
16
-
17
50
A very common example would be creating applications per subdomain. For
18
51
instance you configure your webserver to dispatch all requests for all
19
52
subdomains to your application and you then use the subdomain information
20
- to create user-specific instances.
53
+ to create user-specific instances. Once you have your server set up to
54
+ listen on all subdomains you can use a very simple WSGI application to do
55
+ the dynamic application creation.
21
56
22
- Once you have your server set up to listen on all subdomains you can use a
23
- very simple WSGI application to do the dynamic application creation.
24
-
25
- The code for the dispatching looks roughly like this:
26
-
27
- .. sourcecode :: python
57
+ The perfect level for abstraction in that regard is the WSGI layer. You
58
+ write your own WSGI application that looks at the request that comes and
59
+ and delegates it to your Flask application. If that application does not
60
+ exist yet, it is dynamically created and remembered::
28
61
29
62
from threading import Lock
30
63
@@ -43,21 +76,16 @@ The code for the dispatching looks roughly like this:
43
76
with self.lock:
44
77
app = self.instances.get(subdomain)
45
78
if app is None:
46
- app = self.make_app (subdomain)
79
+ app = self.create_app (subdomain)
47
80
self.instances[subdomain] = app
48
81
return app
49
82
50
- def make_app(self, subdomain):
51
- return self.create_app(subdomain)
52
-
53
83
def __call__(self, environ, start_response):
54
84
app = self.get_application(environ['HTTP_HOST'])
55
85
return app(environ, start_response)
56
86
57
87
58
- If you want to use it, you can do something like this:
59
-
60
- .. sourcecode :: python
88
+ This dispatcher can then be used like this::
61
89
62
90
from myapplication import create_app, get_user_for_subdomain
63
91
from werkzeug.exceptions import NotFound
@@ -76,3 +104,51 @@ If you want to use it, you can do something like this:
76
104
return create_app(user)
77
105
78
106
application = SubdomainDispatcher('example.com', make_app)
107
+
108
+
109
+ Dispatch by Path
110
+ ----------------
111
+
112
+ Dispatching by a path on the URL is very similar. Instead of looking at
113
+ the `Host ` header to figure out the subdomain one simply looks at the
114
+ request path up to the first slash::
115
+
116
+ from threading import Lock
117
+ from werkzeug.wsgi import pop_path_info, peek_path_info
118
+
119
+ class PathDispatcher(object):
120
+
121
+ def __init__(self, default_app, create_app):
122
+ self.default_app = default_app
123
+ self.create_app = create_app
124
+ self.lock = Lock()
125
+ self.instances = {}
126
+
127
+ def get_application(self, prefix):
128
+ with self.lock:
129
+ app = self.instances.get(prefix)
130
+ if app is None:
131
+ app = self.create_app(prefix)
132
+ if app is not None:
133
+ self.instances[prefix] = app
134
+ return app
135
+
136
+ def __call__(self, environ, start_response):
137
+ app = self.get_application(peek_path_info(environ))
138
+ if app is not None:
139
+ pop_path_info(environ)
140
+ else:
141
+ app = self.default_app
142
+ return app(environ, start_response)
143
+
144
+ The big difference between this and the subdomain one is that this one
145
+ falls back to another application if the creator function returns `None `::
146
+
147
+ from myapplication import create_app, default_app, get_user_for_prefix
148
+
149
+ def make_app(prefix):
150
+ user = get_user_for_prefix(prefix)
151
+ if user is not None:
152
+ return create_app(user)
153
+
154
+ application = PathDispatcher('example.com', default_app, make_app)
0 commit comments