如何从请求URI中删除版本前缀并使用正确的文档根目录?

我们需要支持几个主要和次要版本的Web服务,所以我们决定在URL中使用版本,如下所示:

http://service/      # last deployed version of service
http://service/1/    # symlink that points to the last deployed major version 1.x
http://service/1.2/  # symlink that points to the last deployed minor version 1.2.x

我们将所有标签存储在文件夹中,并将符号链接转换为正确的版本:

Here the root directory for apache:
lrwxr-xr-x   1 xxxx xxxx 28 May 23 15:21 1 -> /home/site/tags/20120523084844-HEAD
lrwxr-xr-x   1 xxxx xxxx 28 Apr 27 15:21 1.1 -> /home/site/tags/20120427152123-HEAD
lrwxr-xr-x   1 xxxx xxxx 28 May 23 08:48 1.2 -> /home/site/tags/20120523084844-HEAD
lrwxr-xr-x   1 xxxx xxxx 28 May 24 16:12 2 -> /home/site/tags/20120524161232-HEAD
(source code here for last deployed version)
.....

这里有一个问题,因为我们将在PHP的REQUEST_URI中使用版本前缀,并且Symfony路由器将不会与模式匹配。我们如何剪切该版本前缀,但是仍然使用特定的目录作为文档根目录?

例如,当我们向 http://service/1.2/some/handler/pattern 发出请求时,将使用1.2目录中的代码,PHP中的REQUEST_URI将是/ some/handler /模式

3
额外
意见: 1
我不想为源代码添加版本模式,因为每个服务安装都不应该知道URI中的版本。
额外 作者 lisachenko,
路由模式/服务/:版本/某些/处理程序/模式(symfony 1)或/服务/ {版本} /某些/处理程序/模式(symfony 2)不起作用?
额外 作者 Pierre,

2 答案

尝试这个:

RewriteEngine On
RewriteBase /

RewriteCond $1 !^[0-9.]+/
RewriteRule ^(.*) /1.2/$1 [L]

唯一的想法是你一次只能测试一个版本,如果你想要一个不同的版本,必须改变htaccess。

我可以建议使用子域进行版本控制吗?

1
额外
谢谢你的回答!不幸的是,我们需要一次支持多个版本。我已经考虑过使用apache的虚拟子域和透明的反向代理。但是这对于在生产环境中使用来说太复杂了。
额外 作者 lisachenko,

这是一个有趣的问题。

我不认为这只能用htaccess完成,至少不能没有丑陋的黑客。 REQUEST_URI总是保存原始请求,并且据我所知无法编辑它(如果我们尝试通过E = REQUEST_URI =“something”将内容分配给变量REQUEST_URI,则会创建一个名为“REDIRECT_REQUEST_URI”的环境变量)。

我对Symfony并不熟悉,所以我不知道编辑处理路由的脚本是多么容易。如果很容易,你可以做类似的事情

RewriteRule ^[1-9.]/(.*)$ - [R,QSA,NC,E=HANDLER:$1]

然后在PHP中,您可以将处理程序复制到request_uri:

$_SERVER['REQUEST_URI'] = $_SERVER['REDIRECT_HANDLER'];

除了像这样改变PHP,我只能想到这一点:首先硬重定向到处理程序,将版本信息放入查询字符串中。然后捕获该请求,并软重定向到版本/处理程序。 Request_uri将被正确设置,但它很丑并且非常容易出错。

也就是说,我完全同意Gerben关于使用子域进行版本控制的问题。

1
额外
是的,似乎没有优雅的解决方案。只有代理的子域名。很遗憾,但我会在代码级别上进行破解(
额外 作者 lisachenko,