Skip to content

Instantly share code, notes, and snippets.

@DevonStrawn
Last active January 18, 2019 06:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DevonStrawn/e01e3f22bbe9753763c983f3af0a305a to your computer and use it in GitHub Desktop.
Save DevonStrawn/e01e3f22bbe9753763c983f3af0a305a to your computer and use it in GitHub Desktop.
Nginx config for a Flask endpoint that does internal redirect via X-Accel-Redirect and passes a flash message to an OpenResty / Lua endpoint
'''
Flask server that *internal*-redirects to another Nginx endpoint without generating additional HTTP traffic.
Also passes an internaly-only 'flash message' via headers.
'''
from flask import Flask, request, make_response
application = Flask(__name__)
@application.route('/from/flask')
def fromFlask():
response = make_response('This response body is ignored! Only the headers are used by downstream Nginx location(s).')
response.headers.set('X-Accel-Redirect', '/intermediate')
response.headers.set('X-Flash-Message', 'This is the flash message from Flask')
return response
if __name__ == "__main__":
application.run(host='0.0.0.0')
# This Gist lets you do 2 cool things:
# 1) internally-redirect from an upstream app-server endpoint written in one language/framework (Python/Flask) to another (Lua/OpenResty), without generating additional HTTP traffic.
# 2) send an internal-only 'flash message' from one endpoint to another without storing it in the user session.
#
# This technique depends on the `X-Accel-Redirect` header, and some Nginx helpers to pass data between locations.
# The 'intermediate location' (below) is based on @agentzh's post: https://groups.google.com/forum/#!msg/openresty-en/vPxQFntAfCc/sQBBTSVq7xYJ
#
# Example:
# $ curl http://localhost/from
# This is the flash message from Flask, in a response generated by a Lua endpoint
#
# In practice, you'll likely want to use `ngx.location.capture` instead, for simplicity's sake.
# Even so, this technique can still be useful in rare scenarios.
http {
upstream app_server_flask {
# Out of scope for this Gist: you'll need to start Gunicorn / etc. to setup this Unix-domain socket.
server unix:/run/app_server_flask.sock;
}
# Proxy the Flask app server.
location = '/from/flask' {
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_set_header Host $host;
# proxy_redirect off;
proxy_pass http://app_server_flask;
}
# Note: this is an extra, optional endpoint to illustrate how to use this technique without any (Flask) code.
location = '/from/nginx' {
more_set_headers 'X-Accel-Redirect: /intermediate';
more_set_headers 'X-Flash-Message: This is the flash message from Nginx';
}
# This helper converts headers set by the originating location into Nginx variables to be read by the destination location.
# See agentzh's post for details: https://groups.google.com/forum/#!msg/openresty-en/vPxQFntAfCc/sQBBTSVq7xYJ
location = '/intermediate' {
internal;
set $X_Flash_Message_From_Upstream $upstream_http_x_flash_message;
# set $X_Flash_Message 'oh boy'; # Debugging helper when `$upstream_http_x_flash_message` isn't provided / correctly specified.
rewrite ^/(.+) /to;
}
# The final destination, a Lua endpoint that displays the 'flash message' from the original location(s).
location = '/to' {
content_by_lua_block {
local flashMessage = ngx.var['X_Flash_Message']
ngx.say(string.format('%s, in a response generated by a Lua endpoint', flashMessage))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment