Traefik: add trailing slash
When using Traefik as your Kubernetes ingress controller you might want to add a trailing slash (/about
→ /about/
) to prevent duplicate routes. Traefik does not (yet) support adding trailing slashes through a configuration option[1][2]. You can use this snippet to create a Traefik IngressRoute and Traefik Middleware that will do just that. Add this next to your normal IngressRoute
for www.my-domain.com
.
Prerequisites
- A running instance of Traefik v2 in a Kubernetes cluster
kubectl
access to the Kubernetes cluster- External IP address of the server/VM for testing
Snippet
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: my-domain-com-add-trailing-slash # Change this
namespace: default # Change this?
spec:
entryPoints:
- websecure # Change this?
routes:
- kind: Rule
# Matches requests with a non-empty path and only ones that do not end with
# a file extension (e.g. '.jpg') or an already existing trailing slash
match: "Host(`www.my-domain.com`) && PathPrefix(`/{path:.+}`) && !Path(`/{path:(.+)(\\.\\w+|/)}`)" # Change this
# Make sure this matching rule will be checked first
priority: 200
middlewares:
- name: add-trailing-slash
namespace: traefik
services:
- kind: TraefikService
name: noop@internal
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: add-trailing-slash
namespace: traefik
spec:
redirectRegex:
permanent: true
regex: "^https?://(.*)/(.+)"
replacement: "https://${1}/${2}/"
Usage
Save the snippet above to a file called
my-domain-com-add-trailing-slash.yaml
. You can download it hereMake the necessary changes
Create the resources:
kubectl apply -f my-domain-com-add-trailing-slash.yaml
Try it out with:
curl -v https://www.my-domain.com/foo/bar --resolve www.my-domain.com:443:{your server IP} # 301 Moved Permanently # Location: https://www.my-domain.com/foo/bar/
Notes
In case you’ve enabled the providers.kubernetesCRD.ingressClass
in the static configuration, you will have to add the kubernetes.io/ingress.class
annotation to the IngressRoute
.