This is a collection of some of the most “fun” uses of uWSGI features.
Even if your frontend proxy/webserver does not support X-Sendfile (or cannot access your static resources) you can emulate it using uWSGI’s internal offloading (your process/thread will delegate the actual static file serving to offload threads).
[uwsgi]
...
; load router_static plugin (compiled in by default in monolithic profiles)
plugins = router_static
; spawn 2 offload threads
offload-threads = 2
; files under /private can be safely served
static-safe = /private
; collect the X-Sendfile response header as X_SENDFILE var
collect-header = X-Sendfile X_SENDFILE
; if X_SENDFILE is not empty, pass its value to the "static" routing action (it will automatically use offloading if available)
response-route-if-not = empty:${X_SENDFILE} static:${X_SENDFILE}
This will force HTTPS for the whole site.
[uwsgi]
...
; load router_redirect plugin (compiled in by default in monolithic profiles)
plugins = router_redirect
route-if-not = equal:${HTTPS};on redirect-permanent:https://${HTTP_HOST}${REQUEST_URI}
And this only for /admin
[uwsgi]
...
; load router_redirect plugin (compiled in by default in monolithic profiles)
plugins = router_redirect
route = ^/admin goto:https
; stop the chain
route-run = last:
route-label = https
route-if-not = equal:${HTTPS};on redirect-permanent:https://${HTTP_HOST}${REQUEST_URI}
Eventually you may want to send HSTS (HTTP Strict Transport Security) header too.
[uwsgi]
...
; load router_redirect plugin (compiled in by default in monolithic profiles)
plugins = router_redirect
route-if-not = equal:${HTTPS};on redirect-permanent:https://${HTTP_HOST}${REQUEST_URI}
route-if = equal:${HTTPS};on addheader:Strict-Transport-Security: max-age=31536000
In production you can monitor file/directory changes for triggering reloads (touch-reload, fs-reload...).
During development having a monitor for all of the loaded/used python modules can be handy. But please use it only during development.
The check is done by a thread that scans the modules list with the specified frequency:
[uwsgi]
...
py-autoreload = 2
will check for python modules changes every 2 seconds and eventually restart the instance.
And again:
Warning
Use this only in development.
This example spawned from a uWSGI mainling-list thread.
We have static files in /var/www and cgis in /var/cgi. Cgi will be accessed using the /cgi-bin mountpoint. So /var/cgi/foo.lua will be run on request to /cgi-bin/foo.lua
[uwsgi]
workdir = /var
ipaddress = 0.0.0.0
; start an http router on port 8080
http = %(ipaddress):8080
; enable the stats server on port 9191
stats = 127.0.0.1:9191
; spawn 2 threads in 4 processes (concurrency level: 8)
processes = 4
threads = 2
; drop privileges
uid = nobody
gid = nogroup
; serve static files in /var/www
static-index = index.html
static-index = index.htm
check-static = %(workdir)/www
; skip serving static files ending with .lua
static-skip-ext = .lua
; route requests to the CGI plugin
http-modifier1 = 9
; map /cgi-bin requests to /var/cgi
cgi = /cgi-bin=%(workdir)/cgi
; only .lua script can be executed
cgi-allowed-ext = .lua
; .lua files are executed with the 'lua' command (it avoids the need of giving execute permission to files)
cgi-helper = .lua=lua
; search for index.lua if a directory is requested
cgi-index = index.lua
Let’s write three flask apps:
#app1.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World! i am app1"
#app2.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World! i am app2"
#app3.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World! i am app3"
each will be mounted respectively in /app1, /app2, /app3
To mount an application with a specific “key” in uWSGI, you use the –mount option:
` --mount <mountpoint>=<app> `
in our case we want to mount 3 python apps, each keyed with what will be the WSGI SCRIPT_NAME variable:
[uwsgi]
plugin = python
mount = /app1=app1.py
mount = /app2=app2.py
mount = /app3=app3.py
; generally flask apps expose the 'app' callable instead of 'application'
callable = app
; tell uWSGI to rewrite PATH_INFO and SCRIPT_NAME according to mount-points
manage-script-name = true
; bind to a socket
socket = /var/run/uwsgi.sock
now directly point your webserver.proxy to the instance socket (without doing additional configurations)
Note: by default every app is loaded in a new python interpreter (that means a pretty-well isolated namespace for each app). If you want all of the app to be loaded in the same python vm, use the –single-interpreter option.
Another note: you may find reference to an obscure “modifier1 30” trick. It is deprecated and extremely ugly. uWSGI is able to rewrite request variables in lot of advanced ways
Final note: by default, the first loaded app is mounted as the “default one”. That app will be served when no mountpoint matches.