处理同一 URL 中的多个版本

发布于 2024-11-29 08:51:46 字数 636 浏览 3 评论 0原文

我想做的是处理同一网络应用程序的多个版本,有点像谷歌对其某些产品所做的那样,您可以在其中获得“尝试新版本”链接。

目标是同时拥有 Web 应用程序的“稳定”版本和“测试版”版本,并让用户尝试新功能而不强迫他们(及其错误)。

现在,一种非常简单的方法是将每个版本放入其自己的子文件夹中,例如 www.mywebapp.com/v1 和 www.mywebapp.com/v2。

但是,我希望这对用户是透明的,并且 webapp URL 保持不变(例如:www.mywebapp.com/)。

必须加载哪个版本是在用户登录后由服务器端确定的(例如:给定用户的活动版本存储在数据库中),并且可以在用户单击“尝试新版本”/“转到”时更改返回旧版本”链接。

在服务器端,我必须使用 MySQL、PHP 和 Apache。

我已经成功地将每个版本放入其自己的子文件夹中,然后将版本信息存储在cookie中(由服务器在每次登录或页面刷新时更新)并使用RewriteRule“代理”来自基本/无版本的请求正确子文件夹的 URL。如果未设置 cookie,则由后备 RewriteRule 选择默认文件夹。

这种拼凑可以工作,但感觉非常脆弱,它给 Apache 守护进程带来了额外的负担,所以我在这里询问是否有人知道更好的方法来做到这一点。

谢谢!

what I'm trying to do is to handle multiple versions of the same web application, somewhat like Google does with some of their products where you get the "Try the new version" link.

The goal is to have both a "stable" and a "beta" version of the webapp and letting the users try out the new features without forcing them (and their bugs) on them.

Now, a very simple way of doing this would be to put each version in its own subfolder, like www.mywebapp.com/v1 and www.mywebapp.com/v2.

However, I would like this to be transparent to the user and the webapp URL to stay the same (e.g.: www.mywebapp.com/).

Which version must be loaded is determined server-side after the user logs in (e.g.: active version for the given user is stored in the DB) and may be later changed when the user clicks on the "try the new version"/"go back to the old version" links.

On the server side I must make do with MySQL, PHP and Apache.

I have already managed to get this working placing each version into its own subfolder, then storing version information in cookies (updated by the server at each login or page refresh) and using RewriteRule(s) to "proxy" requests from the base/versionless URL to the proper subfolder. If no cookie is set, a default folder is selected by a fallback RewriteRule.

This kludge works but feels extremely fragile and it puts additional burden on the Apache daemon so here I am asking if anybody knows a better way of doing this.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

宣告ˉ结束 2024-12-06 08:51:46

htaccess 允许根据 cookie 的内容进行重写。由于 Apache 在重定向方面非常棒,而 PHP 也足够了,所以我会这样处理。

此示例测试是否存在 vers cookie。如果有,它会将 'vers=' + vers cookie 中的任何内容添加到请求中。

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_COOKIE} vers=([^;]+) [NC]
RewriteRule ^(.*)$ /$1?vers=%1 [NC,L,QSA]

(该示例可以在此处找到)

htaccess allows for rewrites based on the contents of cookies. Since Apache is AWESOME at redirects and PHP is adequate, I would handle it that way.

This example tests to see if there is a vers cookie. If there is, it adds 'vers=' + whatever was in the vers cookie to the request.

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_COOKIE} vers=([^;]+) [NC]
RewriteRule ^(.*)$ /$1?vers=%1 [NC,L,QSA]

(that example can be found here)

执妄 2024-12-06 08:51:46

使用单个 RewriteRule 将所有请求重新路由到网站根文件夹中的单个 route.php 文件。

route.php 文件应如下所示:

$user = authenticateUser();
$version = $user->getPreferredVersion();

$filePath = $_SERVER['DOCUMENT_ROOT'].'v'.$version.$_SERVER['REQUEST_URI'];

if( !file_exists( $filePath ) ) {
    header("Status: 404 Not Found", true, 404 );
    die();
}

$pathDetails = pathinfo( $filePath );

if( $pathDetails['extension'] == 'php' ) {
    require( $filePath );
} else {
    if( $pathDetails['extension'] == 'jpg' ) {
        header( 'Content-Type: image/jpeg' );
    } elseif( $pathDetails['extension'] == 'gif' ) {
        ...
    } elseif (...) {
        ...
    } else {
        // unsupported file type
        header("Status: 404 Not Found", true, 404 );
        die();
    }
    echo file_get_contents( $filePath );
}

这是您应在 route.php 中执行的操作的概述,还有一些您应该注意的其他安全和技术问题该文件中的。

Use a single RewriteRule to reroute all requests to a single route.php file in the root folder of your website.

The route.php file should look like this:

$user = authenticateUser();
$version = $user->getPreferredVersion();

$filePath = $_SERVER['DOCUMENT_ROOT'].'v'.$version.$_SERVER['REQUEST_URI'];

if( !file_exists( $filePath ) ) {
    header("Status: 404 Not Found", true, 404 );
    die();
}

$pathDetails = pathinfo( $filePath );

if( $pathDetails['extension'] == 'php' ) {
    require( $filePath );
} else {
    if( $pathDetails['extension'] == 'jpg' ) {
        header( 'Content-Type: image/jpeg' );
    } elseif( $pathDetails['extension'] == 'gif' ) {
        ...
    } elseif (...) {
        ...
    } else {
        // unsupported file type
        header("Status: 404 Not Found", true, 404 );
        die();
    }
    echo file_get_contents( $filePath );
}

This is the outline of what you should do in route.php there are some other security and technical issues that you should take care of in that file.

月下伊人醉 2024-12-06 08:51:46

我认为 PHP 中更好的方法是简单地查询数据库,获取所需的版本,然后从子文件夹中 include() 它。这样它对用户来说是透明的。

例如,假设用户选择了新的测试版,您将他的条目保存在数据库中,

UPDATE `versions_table` SET (`version`) VALUES ('1.02b') WHERE `userid` = 5

然后当他访问该页面时,您会发生如下情况:

//PDO Connection here, skipped for example purposes
$stmt = $pdo->query('SELECT `version` from `versions_table` WHERE `userid` = 5 LIMIT 1'); 
//Of course 5 is only an example, in actual code that would be a variable
//representing the actual user ID.
$row = $stmt->fetch(); //Should be only one row.
include_once($row['version'].'/myApp'.'.php'); //Include 1.02b/myApp.php

I think a better way in PHP would be to simply query the database, get the desired version, and then include() it from a subfolder. That way it's transparent to the user.

For instance, assuming the user has opted in for the new beta, you save his entry in the database,

UPDATE `versions_table` SET (`version`) VALUES ('1.02b') WHERE `userid` = 5

And then when he accesses the page, you have something like this going on:

//PDO Connection here, skipped for example purposes
$stmt = $pdo->query('SELECT `version` from `versions_table` WHERE `userid` = 5 LIMIT 1'); 
//Of course 5 is only an example, in actual code that would be a variable
//representing the actual user ID.
$row = $stmt->fetch(); //Should be only one row.
include_once($row['version'].'/myApp'.'.php'); //Include 1.02b/myApp.php
爱*していゐ 2024-12-06 08:51:46

虽然可以使用路由机制和会话信息来制定规则,但我宁愿保留您当前的解决方案。在 PHP 中实现它所要做的就是将负载从 apache2(它已经有一个非常快的重写引擎)推送到 php 二进制文件。此外,由于数据、cookie 和其他基于会话的变量不兼容,您的应用程序也会面临版本干扰的风险。

另一方面,您可以享受共享对象(如库、域模型、数据映射器等)可重用性的好处。但在我看来,这种优势并不会加重更差的性能和干扰风险。

所以总而言之,我相信您当前的解决方案是最好的。

While it is possible to use a routing mechanism and session information to make rules, I would rather keep your current solution. All you'd do by implementing it in PHP is that you push the load from the apache2 (which already has a very fast Rewrite-Engine) to the php-binary. Also, you would put your application at risk of interfering versions due to incompatibilities of data, cookies and other session-based variables.

On the other hand, you have the benefit of reusability of shared objects like libraries, Domain Models, Data Mappers, etc. But in my opinion that advantage doesn't weight up the worse performance and interference risk.

So in one phrase, I believe your current solution is best.

以歌曲疗慰 2024-12-06 08:51:46

在 IFRAME 中加载您的版本化页面/wepages,并且 IFRAME src 可能是“webapp.com/v2”..

因此,无论用户选择哪个版本,您的地址栏都会读取 webapp.com.. 但您的 IFRAME url 会根据版本不断变化。 .

不需要写重写规则..

Load your version-ed page/wepages in IFRAME and IFRAME src could be "webapp.com/v2"..

So whichever version user selects your address bar will read webapp.com..but your IFRAME url keeps on changing depending on version..

There is no need to write rewrite rules..

您的好友蓝忘机已上羡 2024-12-06 08:51:46

这可能会有所帮助:我现在使用一个月的是

  1. 保留数据库中的所有文件(路径,代码,版本=十进制(3,1),标志:稳定= 3/lab =2/beta=1/alpha=0)

  2. 拥有.htaccess 将所有不存在的文件重定向(不要将图像、css、js 或其他静态非版本控制文件)内部重定向到 loader.pm(为您提供 loader.ph_)不要使用与其他文件相同的扩展名以进行区分

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ loader.pm [L,QSA]
    
  3. loader 会从数据库加载最新的稳定版本,如果不存在稳定版本,则加载器会从测试版加载。

    从表中选择代码、版本、标志 WHERE 路径 = ?与标志> 0 ORDER BY flag DESC, version DESC LIMIT 1 不显示正在开发的 alpha 页面

    如果没有结果则输出404错误,并且

    当版本指定为 ?v=2.0 时,加载程序文件使用不同的查询

    从表中选择代码、版本、标志 WHERE 路径 = ?且版本 <= ? ORDER BY flag DESC LIMIT 1

假设:

  1. 用户想要稳定版或最新版;所以实际上每个路径不需要超过 2 个文件;除非您想保留旧版本进行展示。如果用户想要最新的,请使用 .. ORDER BY version DESC, flag DESC, ..
  2. 用户不关心知道它是哪个版本,因此我们不是一次为整个网站设置相同的版本,而是单独设置每个文件的版本;所以跟踪开发很容易。

问题:

  • 没有索引/主键
    • 您需要确保没有重复的条目,虽然它不会破坏您的网站,但看起来不太好;)
    • 如果相同的测试版和文件存在稳定版本,并且用户已选择最新版本(测试版);那么你可能会不小心给他提供测试版文件而不是稳定文件。
  • 查询字符串变量?v=被保留用于选择版本,但这很好;您可以选择 ?var=

This might help: what I am using for a month now is

  1. Keep all the files in database (path, code, version=Decimal(3,1), flag:stable=3/lab=2/beta=1/alpha=0)

  2. have .htaccess redirects all non existing files (don't redirect images, css, js or other static non version-ate files) internally to loader.pm (for you loader.ph_) don't use same extension as your other files for differentiation

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^   loader.pm [L,QSA]
    
  3. loader loads the latest stable version from database or beta version if no stable version exists.

    SELECT code, version, flag FROM table WHERE path = ? AND flag > 0 ORDER BY flag DESC, version DESC LIMIT 1 Don't show alpha pages that are under development

    output 404 error if no results, and

    when version is specified like ?v=2.0 loader file uses different query

    SELECT code, version, flag FROM table WHERE path = ? AND version <= ? ORDER BY flag DESC LIMIT 1

Assumptions:

  1. A user either want stable or latest; so you actually don't need more than 2 files per path; until unless you want to keep old versions for showcase. If user want latest, use .. ORDER BY version DESC, flag DESC, ..
  2. User doesn't care to know which version it is, hence instead of setting same version for whole website at once, we set version of each file individually; so tracking development is easy.

Problems:

  • No index/primary key
    • You need to make sure that you don't have duplicate entries, it will not break your website though, but it will not look good ;)
    • if same beta & stable version exists for a file, and user has opted for latest (beta); then you might accidentally deliver him beta file instead of stable file.
  • query-string variable ?v= is reserved for selecting versions, but that is fine; you may choose ?var=
盗心人 2024-12-06 08:51:46

有一个云平台可以在部署时自动执行此操作。 www.cycligent.com
只需在部署两个版本后设置 cookie 即可。比显示的其他一些答案少了很多工作。
全面披露:我为 Cycligent 工作。

There is a cloud platform that does this automatically upon deployment. www.cycligent.com
It is just a matter of setting a cookie once the two versions are deployed. A lot less work than some of the other answers shown.
Full Disclosure: I work for Cycligent.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文