-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Currently the SmartApp and other nginx apps like WaalKade are proxied on path prefixes like https://pdok.smartemission.nl/smartapp. As to still allow local resources (javascript, css, media) to be served, the prefix-path /smartapp is rewritten in Kubernetes Ingress to /smartapp/ (trailing slash). This does not work nicely in all deployment contexts, in particular Traefik. Also it is a different method as used with (Flask) Python Apps. There the HTTP Header X_SCRIPT_NAME is set in the related Ingress and handled internally within the Flask app.
It appears to be possible to use the same X_SCRIPT_NAME mechanism to work for nginx backend apps. Thus the rewrite is not required anymore.
This can be effected by a simple addition to the nginx config, using the sub_filter feature on HTML (by default) and JavaScript (sub_filter_types application/javascript) content:
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
location / {
# rewrite ^([^.]*[^/])$ $uri/ permanent;
root /usr/share/nginx/html/smartapp;
# substitute /SCRIPT_NAME so if proxied the proper URLs are set
sub_filter_once off;
sub_filter_types application/javascript;
sub_filter "/X_SCRIPT_NAME" $http_x_script_name;
index index.html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
The HTML and JavaScript content will need to have /X_SCRIPT_NAME in the content e.g.
<!DOCTYPE html>
<html>
<head>
<title>SmartApp</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css"
integrity="sha512-M2wvCLH6DSRazYeZRIm1JnYyh22purTM+FDB5CsyxtQJYeKq83arPe5wgbNmcFXGqiSH2XR8dT/fJISVA1r/zQ=="
crossorigin=""/>
<link rel="stylesheet" href="/X_SCRIPT_NAME/lib/markercluster/1.1.0/MarkerCluster.css" />
<link rel="stylesheet" href="/X_SCRIPT_NAME/lib/markercluster/1.1.0/MarkerCluster.Default.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"/>
This replaces href="/X_SCRIPT_NAME/... with e.g. href="/smartapp/... when the X_SCRIPT_NAME header is set. If not set, e.g. when accessed directly this substitutes to href="/... and resolves as well. A very basic form of templating.
The SmartApp Ingress needs to be adapted to:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: smartapp
namespace: smartemission
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/add-base-url: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header X-Script-Name /smartapp;
spec:
rules:
- host: pdok.smartemission.nl
http:
paths:
- path: /smartapp
backend:
serviceName: smartapp-service
servicePort: 80
The nice thing is that we have a single method within the Ingress-es (proxy_set_header X-Script-Name) and getting rid of the sometimes problematic rewrite.
In docker-compose this becomes
version: "3"
services:
smartapp:
image: smartemission/se-smartapp:latest
container_name: smartapp
restart: unless-stopped
labels:
- "traefik.backend=smartapp"
- "traefik.enable=true"
- "traefik.frontend.priority=500"
- "traefik.frontend.rule=HostRegexp:{subdomain:[a-z]+}.smartemission.nl;PathPrefixStrip:/smartapp"
- "traefik.frontend.headers.customRequestHeaders=X-Script-Name:/smartapp"
- "traefik.docker.network=se_back"
networks:
- se_back
# ports:
# - 80:80
networks:
se_back:
external: true