【问题标题】:How can I find an application's base url behind a proxy?如何在代理后面找到应用程序的基本 URL?
【发布时间】:2020-02-09 20:32:36
【问题描述】:

我们基于 PHP 的应用程序(定制,无框架)有时需要使用其基本完整 URL(例如,将 URL 存储在发送给客户端的文件中)。例如基于this question,我们的应用程序会猜测这一点(这是基于比较__FILE__$SERVER 中的各种变量,如SCRIPT_NAMESERVER_NAME)。

现在我们需要在我们的应用程序前面设置一个 (nginx) 反向代理。假设我们将https://example.com/some/dir/onproxy/ 映射到http://backend/another/dir/onbackend/

有没有办法从backend 上的代码中猜出公共 URL (https://example.com/some/dir/onproxy/)?

AFAIU(根据我的阅读和实验),这是不可能的(HTTP_HOST 可能会给example.com,但我没有发现任何表明some/dir/onproxy)但也许我遗漏了一些东西(一些变量或 nginx 配置选项)。

有什么想法吗?

如果不可能,唯一的解决方案就是在配置中存储https://example.com/some/dir/onproxy/,对吧?

编辑 1

按照@Progman 的建议,我在this question 上尝试了解决方案。我已经尝试了接受的答案和第二个最受好评的答案,但两者都返回(一些变体)后端的 URL (http://backend/another/dir/onbackend/)。

编辑 2

我忘了提到我想避免依赖代理中的 URL 重写。

【问题讨论】:

  • 你检查过stackoverflow.com/questions/6768793/get-the-full-url-in-php吗?请edit您的问题包括您尝试链接问题中的解决方案时获得的结果。
  • 澄清。您正在通过 Nginx 上传文件。 Nginx 更改 URL 中的路径并将新路径上的请求发送到 PHP。您正在寻求一种解决方案,以便 PHP 代码可以知道原始路径在被 Nginx 更改之前是什么?
  • @SteveE。它不是(仅)上传,它适用于每个请求,但是是的,我想要原始路径。例如,当客户端请求https://example.com/some/dir/onproxy/subdir/feature.php(由代理转换为http://backend/another/dir/onbackend/subdir/feature.php)时,脚本feature.php 必须知道基本URL 是https://example.com/some/dir/onproxy/
  • @Progman 我会尽快更新问题。

标签: php reverse-proxy nginx-reverse-proxy


【解决方案1】:

由于 Nginx 会在请求到达 PHP 后端之前对其进行更改,因此解决方案是以某种方式将原始请求数据添加到代理请求中。

对此的常用约定是将原始数据添加为额外的 HTTP 标头。请参阅 X_Forwarded_For 作为示例。

要将原始请求路径添加为新标头,请将proxy_set_header 指令添加到 Nginx。

location /some/dir/onproxy/ {
    rewrite ^/some/dir/onproxy/(.*)$  /another/dir/onbackend/$1 break;

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Request-URI $request; #** This adds the original path as a header **
    proxy_set_header Host $http_host; # **Optional, will retain the original host name**
    proxy_pass http://backend;
}

与您的配置类似的东西会将原始请求代理到后端的 PHP Web 服务器。它确实假设后端是 HTTP 服务器而不是 PHP-FPM。

在 PHP 中,获取单个 HTTP 标头值的最快方法是通过 $_SERVER。原始请求路径将在$_SERVER['HTTP_X_REQUEST_URI']

这只是一个示例,您可能需要测试和调试您的应用程序以优化解决方案。 php_info();对 PHP 环境来说是一个有用的调试工具,但它对恶意行为者也很有用,因此请尽快从您的代码中删除或采取其他措施以确保它不被暴露。

【讨论】:

  • 谢谢@SteveE。 !我期待着这样的事情。在接受答案之前,我有 2 个问题。首先,是否需要 rewrite 规则?其次,请原谅我的无知,但PHP-FPM 有什么不同?
  • @Mathieu Dubios 重写规则将请求的路径更改为后端需要的任何路径。我假设你已经有了,但如果它不需要作为解决方案的一部分,那么就把它排除在外。PHP-FPM 使用它自己的网络侦听器运行 PHP,而不是通过 HTTP 服务器。然而 PHP-FPM 本身不兼容 HTTP,所以你需要一个像 Nginx 这样理解的代理。
  • 感谢您澄清这一点:我们的应用程序主要使用相对链接,并且当我们在需要时构建完整的 URL 时(因此问题:) 所以我们希望避免 URL 重写。 backend 可以使用 PHP-FPM 但在 Apache 后面应该没有问题。
  • 不应该proxy_pass http://backend;proxy_pass http://backend/another/dir/onbackend/; 吗?
  • @Mathieu Dubois,read the manual 可能更容易。 TLDR 路径对于proxy_pass 是可选的,如果指定,行为会发生变化。根据用例,任何一种方式都有效。
猜你喜欢
  • 1970-01-01
  • 2010-09-15
  • 2011-05-09
  • 2016-07-09
  • 2019-05-14
  • 1970-01-01
  • 2017-02-04
  • 2011-08-21
  • 1970-01-01
相关资源
最近更新 更多