Apache2配合Gunicorn部署Flask时路由末尾斜杠异常问题求解
我正在应用中搭建多个端点和子端点,一部分是出于学习目的,另一部分是因为我持有两个域名,下文简称为domain1和domain2。
Flask分别对应两个域名监听/api1和/api2端点,Gunicorn绑定在Unix套接字sock/domain1.sock和sock/domain2.sock上,到这一步所有功能都能正常运行。
我的Apache2代理配置如下,将请求转发到对应套接字:domain1的配置:
<Location /api> ProxyPass unix:/var/www/socks/domain1.sock|http://127.0.0.1/api1 ProxyPassReverse unix:/var/www/socks/domain1.sock|http://127.0.0.1/api1 </Location>
domain2的配置:
<Location /api> ProxyPass unix:/var/www/socks/domain2.sock|http://127.0.0.1/api2 ProxyPassReverse unix:/var/www/socks/domain2.sock|http://127.0.0.1/api2 </Location>
我知道不需要设置两个套接字,这么做仅用于测试。
现在访问domain1.com/api和domain2.com/api都运行正常,但如果访问带末尾斜杠的domain1.com/api/或者domain2.com/api/,就会返回站点未找到错误。这一点我可以理解,因为Flask监听的端点没有带末尾斜杠,于是我将Flask的监听端点修改为带末尾斜杠的/api1/和/api2/,之后就出现了异常行为。
修改后访问domain.com/api/可以正常工作,但访问不带斜杠的domain.com/api时,会跳转到domain.comapi或者127.0.01/api,两种跳转结果都是错误的。我尝试在Apache配置中添加末尾斜杠,也试过多种Flask端的解决方案,都还是出现相同的异常,我个人不介意使用不带斜杠的端点,但是想要搞清楚出现该问题的原因。我搜索了很多资料都没有找到和我这个问题相关的内容。
可复现行为
第二个域名是我公司的受保护IP,无法对外公开,因此我搭建了多个端点方便点击模拟行为:
- https://thethiny.xyz/api1 -> sock|http://127.0.0.1/api1 -> 内部路由/api1
- https://thethiny.xyz/api2 -> sock|http://127.0.0.1/api2 -> 内部路由/api2/
- https://thethiny.xyz/api3 -> sock|http://127.0.0.1/api1/ -> 内部路由/api1
- https://thethiny.xyz/api4 -> sock|http://127.0.0.1/api2/ -> 内部路由/api2
正常运行的端点
- https://thethiny.xyz/api1
- https://thethiny.xyz/api2/
- https://thethiny.xyz/api4
未找到的端点
- https://thethiny.xyz/api1/
- https://thethiny.xyz/api3
- https://thethiny.xyz/api3/
出现异常跳转的端点
- https://thethiny.xyz/api2
- https://thethiny.xyz/api4/
补充说明
我已经理解了问题成因,并且在下方答案中给出了一些解决方案。我对这些解决方案不算满意,但可以确定这是将端点映射到不同底层端点的局限性。更多信息可以查阅反向代理传递与重定向(Reverse Proxy Pass and Redirects)和HTTPd中Location头部重写(Rewriting Location Header in HTTPd)相关文档。
内容的提问来源于stack exchange,提问作者thethiny

