如何配置Sinatra使其在反向代理的虚拟子目录中运行?
解决方案:Sinatra反向代理虚拟目录适配
完全可行,需要同时调整反向代理配置和Sinatra应用设置来解决路由匹配错误的问题,具体步骤如下:
1. 修正反向代理的请求转发逻辑
你的Nginx测试配置问题在于proxy_pass末尾没有加斜杠,导致请求路径被错误传递:
- 访问
/news时,Nginx会把请求转发到http://localhost:4567/news,Sinatra收到的PATH_INFO是/news,自然匹配到get '/:name'路由(name参数被设为news)。
Nginx正确配置
location /news { # 末尾加斜杠,将/news前缀替换为后端的根路径/ proxy_pass http://localhost:4567/; # 传递必要的请求头,帮助Sinatra识别真实请求信息 proxy_set_header Host $host; 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 $scheme; }
Apache生产环境配置
对应你的实际部署环境,Apache配置需要类似这样:
# 将/news前缀的请求转发到Sinatra后端,并替换路径为/ ProxyPass /news http://localhost:4567/ ProxyPassReverse /news http://localhost:4567/ # 可选:传递虚拟路径前缀,用于Sinatra生成正确的URL RequestHeader set X-Forwarded-Path "/news"
2. Sinatra应用适配配置
如果只修正反向代理,Sinatra已经能正确匹配/和/:name路由,但如果你的应用需要生成带虚拟目录前缀的URL(比如用url('/')生成/news而不是/),需要添加以下配置:
静态设置URL前缀
require 'sinatra' # 设置虚拟目录前缀 set :url_prefix, '/news' get '/' do 'Root page' end get '/:name' do "Hello #{params[:name]}" end
动态读取反向代理头(更灵活)
如果需要根据反向代理传递的头动态适配,可添加前置钩子:
before do # 读取Apache传递的X-Forwarded-Path头 if forwarded_path = request.env['HTTP_X_FORWARDED_PATH'] request.env['SCRIPT_NAME'] = forwarded_path end end
这样配置后:
- 访问
http://some.thing/news会匹配Sinatra的get '/'路由 - 访问
http://some.thing/news/old会匹配get '/:name'路由,params[:name]为old
内容的提问来源于stack exchange,提问作者N.K
相关产品推荐
相关产品推荐

