-
-
Save bodewig/048f72aca7f18752cf9a87b83e5a2e51 to your computer and use it in GitHub Desktop.
SSI with nginx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# http://editorconfig.org | |
root = true | |
[*] | |
charset = utf-8 | |
end_of_line = lf | |
insert_final_newline = true | |
trim_trailing_whitespace = true | |
max_line_length = 80 | |
indent_style = tab | |
indent_size = 4 | |
[*.{md,py}] | |
indent_style = space | |
[COMMIT_EDITMSG] | |
trim_trailing_whitespace = false | |
max_line_length = 72 | |
indent_style = space |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import sys | |
HOST = "localhost" | |
PORT = int(sys.argv[1]) | |
ROOT_URI = "/" | |
AUTH_URI = "/auth" | |
NAV_URI = "/nav" | |
FRAGMENT_PREFIX = "/_fragment" | |
JWT = ("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9" + | |
".eyJmb28iOiJiYXIifQ" + | |
".VAoRL1IU0nOguxURF2ZcKR0SGKE1gCbqwyh8u2MLAyY") | |
FRAGMENT_TYPE = "text/html; fragment=true" | |
DOCUMENT = """<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>%(title)s</title> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<style> | |
nav { | |
margin-left: 1em; | |
border: 1px solid #DCA; | |
padding: 0.5em; | |
background-color: #FEFFCD; | |
} | |
nav p, | |
nav ul { | |
margin: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>%(title)s</h1> | |
<p>welcome, %(username)s</p> | |
<pre>%(request_details)s</pre> | |
<a href="%(auth_uri)s">toggle authentication</a> | |
<!--# include virtual="%(embed_uri)s" --> | |
<p>EOF</p> | |
</body> | |
</html> | |
""" | |
FRAGMENT = """ | |
<nav> | |
<p>browsing as %(username)s</p> | |
<pre>%(request_details)s</pre> | |
<ul> | |
<li>foo</li> | |
<li>bar</li> | |
<li>baz</li> | |
</ul> | |
</nav> | |
""" | |
def handler(environ, start_response): | |
method = environ["REQUEST_METHOD"] | |
uri = environ.get("PATH_INFO", "") | |
accept = environ.get("HTTP_ACCEPT") | |
cookie = environ.get("HTTP_COOKIE") | |
user = environ.get("HTTP_X_USER") | |
if uri == AUTH_URI: | |
origin = environ.get("HTTP_REFERER", ROOT_URI) | |
value = ("token=void; expires=Thu, 01 Jan 1970 00:00:00 GMT" if cookie | |
else "token=%s" % JWT) | |
start_response("302 Found", | |
[("Set-Cookie", value), ("Location", origin)]) | |
return "" | |
start_response("200 OK", [("Content-Type", "text/html"), | |
("Cache-Control", "no-cache, must-revalidate, max-age=0")]) | |
embed_uri = FRAGMENT_PREFIX + NAV_URI | |
data = { | |
"request_details": "\n".join([ | |
"🔗 %s" % uri, | |
"⛓️ %s" % embed_uri, | |
"📄 %s" % accept, | |
"🍪 %s" % (cookie or "N/A"), | |
"👤 %s" % (user or "N/A") | |
]), | |
"username": "admin" if cookie else "anonymous" | |
} | |
html = FRAGMENT % data if accept == FRAGMENT_TYPE else DOCUMENT % { | |
**data, | |
"title": "Hello World", | |
"auth_uri": AUTH_URI, | |
"embed_uri": embed_uri | |
} | |
return uft8(html) | |
def uft8(*args): | |
return (txt.encode("utf-8") for txt in args) | |
if __name__ == "__main__": | |
from wsgiref.simple_server import make_server | |
srv = make_server(HOST, PORT, handler) | |
print("→ http://%s:%s" % (HOST, PORT)) | |
srv.serve_forever() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local authr = {} | |
local jwt = require "resty.jwt" | |
local ck = require "cookie" | |
local cjson = require "cjson" | |
local ngx = ngx | |
local auth_uri = "/auth" | |
local cookie_field = "token" | |
local jwt_key = "lua-resty-jwt" | |
function authr.access_handler() | |
if ngx.var.uri == auth_uri then -- FIXME: hacky workaround | |
return | |
end | |
-- retrieve JWT from cookie, otherwise abort | |
local cookie, err = ck:new() | |
if not cookie then | |
return ngx.redirect(auth_uri) | |
end | |
local cookie_value, err = cookie:get(cookie_field) | |
if not cookie_value then | |
return ngx.redirect(auth_uri) | |
end | |
-- retrieve payload from JWT, otherwise abort | |
local token = jwt:verify(jwt_key, cookie_value) | |
if not token.valid or not token.verified then | |
return ngx.redirect(auth_uri) | |
end | |
ngx.req.set_header("X-USER", cjson.encode(token.payload)) | |
-- do not expose cookies to upstream applications | |
-- FIXME: must be selective; only applies to JWT cookie | |
ngx.req.clear_header("Cookie") | |
end | |
return authr |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM openresty/openresty:stretch-fat | |
RUN opm get cdbattags/lua-resty-jwt && \ | |
cd /usr/local/openresty/lualib && \ | |
curl -O https://raw.githubusercontent.com/cloudflare/lua-resty-cookie/8f414390cc72da90e9a450a2127acaea247e3dda/lib/resty/cookie.lua | |
COPY ./nginx.conf /usr/local/openresty/nginx/conf/nginx.conf | |
COPY ./nginx.default.conf /etc/nginx/conf.d/default.conf | |
COPY ./authr.lua /usr/local/openresty/lualib/authr.lua |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
worker_processes 1; | |
events { | |
worker_connections 1024; | |
} | |
http { | |
init_by_lua_block { | |
authr = require "authr" | |
} | |
server { | |
location /_fragment/ { | |
rewrite ^/_fragment/(.*)$ /$1 break; | |
proxy_pass http://host.docker.internal:9999; | |
proxy_set_header Host $host; | |
proxy_set_header Accept "text/html; fragment=true"; | |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
proxy_set_header X-Forwarded-Proto $scheme; | |
} | |
location / { | |
ssi on; | |
access_by_lua_block { | |
authr.access_handler() | |
} | |
proxy_pass http://host.docker.internal:9999; | |
proxy_set_header Host $host; | |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
proxy_set_header X-Forwarded-Proto $scheme; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
server { | |
listen 80; | |
server_name localhost; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
host_port="8080" | |
vm_port="80" # cf. nginx.conf | |
app_port="9999" # cf. nginx.conf | |
echo "----" | |
echo "starting application and reverse proxy → http://localhost:$host_port" | |
echo "----" | |
./app "$app_port" & | |
app_pid="$!" | |
docker build -t nginxy ./ | |
docker run -p "$host_port:$vm_port" nginxy | |
kill $app_pid # it appears Python ignores SIGINT ¯\_(ツ)_/¯ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment