如何使用Traefik根据请求主机重写路径?
解答你的Traefik配置问题
先直接给你结论:你提到的前两个需求是可以实现的,第三个需求需要换个思路——因为Redirect*系列中间件的核心就是返回3xx响应,如果你不想让客户端收到重定向,应该用路径修改类中间件来代替。下面逐个拆解:
1. 在中间件中使用HostRegexp匹配到的内容
addPrefix中间件确实不支持直接引用路由捕获的变量(比如你的{bucketName}),但我们可以用ReplacePathRegex来实现完全相同的效果。路由中通过HostRegexp捕获的变量会被传递给中间件,你可以在正则替换规则里直接引用。
2. 在ReplacePathRegex中读取Host或Host Header
你有两种方式获取Host信息:
- 直接用路由中
HostRegexp捕获的命名变量(比如你的{bucketName}),这是最精准的; - 用Traefik的内置变量
{http.request.host}来获取完整的Host头。
3. 不返回30*响应的“重定向”需求
Redirect*中间件的设计目的就是向客户端返回3xx重定向响应,如果你希望在代理层面修改路径(客户端完全感知不到),应该使用ReplacePath或ReplacePathRegex这类中间件,它们会在转发请求到后端服务前修改请求路径,不会给客户端返回重定向。
适配你需求的完整配置
把原来的addPrefix换成ReplacePathRegex,就能实现将https://{bucketName}.demo.localhost/resource/转发到http://my-resource.s3-website.eu-central-1.amazonaws.com/{bucketName}/resource/:
[http] [http.routers] [http.routers.demo] rule = "HostRegexp(`{bucketName:[a-z\\-]+}.demo.localhost`)" middlewares = ["addBucketPrefix"] service = "demo" [http.middlewares.addBucketPrefix.replacePathRegex] # 正则匹配原路径的开头(^表示起始),替换为/{bucketName}加上原路径内容 regex = "^(.*)" replacement = "/{bucketName}$1" [http.services] [http.services.demo.loadBalancer] passHostHeader = false [[http.services.demo.loadBalancer.servers]] url = "http://my-resource.s3-website.eu-central-1.amazonaws.com/"
这里的ReplacePathRegex规则解释:
regex = "^(.*)":匹配请求路径的全部内容(比如/resource/);replacement = "/{bucketName}$1":把路径替换为/{bucketName}加上原路径的内容(比如/my-bucket/resource/)。
这样就能完全满足你的需求,而且客户端不会收到任何重定向响应。
内容的提问来源于stack exchange,提问作者m90
相关产品推荐
相关产品推荐

