Add support for path-based routing

This commit is contained in:
Greg Symons 2016-10-06 21:08:47 -05:00
parent 0670a13d92
commit 1e4e1948ab

View file

@ -17,6 +17,55 @@
{{ end }}
{{ end }}
{{ define "location" }}
location {{ .Path }} {
{{ if eq .Proto "uwsgi" }}
include uwsgi_params;
uwsgi_pass {{ trim .Proto }}://{{ trim .Upstream }};
{{ else }}
proxy_pass {{ trim .Proto }}://{{ trim .Upstream }}/;
{{ end }}
{{ if (exists (printf "/etc/nginx/htpasswd/%s" .Host)) }}
auth_basic "Restricted {{ .Host }}";
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" .Host) }};
{{ end }}
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" .Host)) }}
include {{ printf "/etc/nginx/vhost.d/%s_location" .Host}};
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
include /etc/nginx/vhost.d/default_location;
{{ end }}
}
{{ end }}
{{ define "upstream-definition" }}
upstream {{ .Upstream }} {
{{ range $container := .Containers }}
{{ $addrLen := len $container.Addresses }}
{{ $networks := .Networks }}
{{ range $knownNetwork := $networks }}
{{ range $containerNetwork := $container.Networks }}
{{ if eq $knownNetwork.Name $containerNetwork.Name }}
## Can be connect with "{{ $containerNetwork.Name }}" network
{{/* If only 1 port exposed, use that */}}
{{ if eq $addrLen 1 }}
{{ $address := index $container.Addresses 0 }}
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}}
{{ else }}
{{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }}
{{ $address := where $container.Addresses "Port" $port | first }}
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
}
{{ end }}
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
@ -38,6 +87,7 @@ log_format vhost '$host $remote_addr - $remote_user [$time_local] '
'"$http_referer" "$http_user_agent"';
access_log off;
error_log /dev/stderr;
{{ if (exists "/etc/nginx/proxy.conf") }}
include /etc/nginx/proxy.conf;
@ -51,6 +101,7 @@ proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Path $request_uri;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
@ -78,30 +129,20 @@ server {
{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
upstream {{ $host }} {
{{ range $container := $containers }}
{{ $addrLen := len $container.Addresses }}
{{ $paths := groupBy $containers "Env.VIRTUAL_PATH" }}
{{ $nPaths := len $paths }}
{{ range $knownNetwork := $CurrentContainer.Networks }}
{{ range $containerNetwork := $container.Networks }}
{{ if eq $knownNetwork.Name $containerNetwork.Name }}
## Can be connect with "{{ $containerNetwork.Name }}" network
{{/* If only 1 port exposed, use that */}}
{{ if eq $addrLen 1 }}
{{ $address := index $container.Addresses 0 }}
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}}
{{ else }}
{{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }}
{{ $address := where $container.Addresses "Port" $port | first }}
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
{{ end }}
{{ end }}
{{ end }}
{{ if eq $nPaths 0 }}
# {{ $host }}
{{ template "upstream-definition" (dict "Upstream" $host "Containers" $containers "Networks" (json $CurrentContainer.Networks)) }}
{{ else }}
{{ range $path, $containers := $paths }}
{{ $sum := sha1 $path }}
{{ $upstream := printf "%s-%s" $host $sum }}
# {{ $host }}{{ $path }}
{{ template "upstream-definition" (dict "Upstream" $upstream "Containers" $containers "Networks" $CurrentContainer.Networks) }}
{{ end }}
{{ end }}
}
{{ $default_host := or ($.Env.DEFAULT_HOST) "" }}
{{ $default_server := index (dict $host "" $default_host "default_server") $host }}
@ -167,24 +208,16 @@ server {
{{ else if (exists "/etc/nginx/vhost.d/default") }}
include /etc/nginx/vhost.d/default;
{{ end }}
location / {
{{ if eq $proto "uwsgi" }}
include uwsgi_params;
uwsgi_pass {{ trim $proto }}://{{ trim $host }};
{{ else }}
proxy_pass {{ trim $proto }}://{{ trim $host }};
{{ if eq $nPaths 0 }}
{{ template "location" (dict "Path" "/" "Proto" $proto "Upstream" $host "Host" $host) }}
{{ else }}
{{ range $path, $containers := $paths }}
{{ $sum := sha1 $path }}
{{ $upstream := printf "%s-%s" $host $sum }}
{{ template "location" (dict "Path" $path "Proto" $proto "Upstream" $upstream "Host" $host) }}
{{ end }}
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
auth_basic "Restricted {{ $host }}";
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }};
{{ end }}
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
include /etc/nginx/vhost.d/default_location;
{{ end }}
}
{{ end }}
}
{{ end }}
@ -202,23 +235,15 @@ server {
include /etc/nginx/vhost.d/default;
{{ end }}
location / {
{{ if eq $proto "uwsgi" }}
include uwsgi_params;
uwsgi_pass {{ trim $proto }}://{{ trim $host }};
{{ else }}
proxy_pass {{ trim $proto }}://{{ trim $host }};
{{ if eq $nPaths 0 }}
{{ template "location" (dict "Path" "/" "Proto" $proto "Upstream" $host "Host" $host) }}
{{ else }}
{{ range $path, $containers := $paths }}
{{ $sum := sha1 $path }}
{{ $upstream := printf "%s-%s" $host $sum }}
{{ template "location" (dict "Path" $path "Proto" $proto "Upstream" $upstream "Host" $host) }}
{{ end }}
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
auth_basic "Restricted {{ $host }}";
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }};
{{ end }}
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
include /etc/nginx/vhost.d/default_location;
{{ end }}
}
{{ end }}
}
{{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}