【问题标题】:webdevops nginx - remove .php requirement from urlwebdevops nginx - 从 url 中删除 .php 要求
【发布时间】:2021-02-02 10:58:58
【问题描述】:

我有一个基于 webdevops/php-nginx:7.2 的 docker,我正在尝试配置 nginx 以将带有或不带有 .php 扩展名的请求路由到适当的文件。

如果abc.php 存在,我需要/abc/abc.php 路由到abc.php。其他一切都将转到index.php

当前设置如下:

Dockerfile 包含

WEB_DOCUMENT_ROOT=/app/public
COPY docker/opt/docker/etc /opt/docker/etc/

opt/docker/etc/nginx/conf.d/10-location-root.conf

server {
  index index.html index.php;
  location / {
    try_files $uri $uri/ /index.php?_url=$uri&$args;
  }
}

/app/public 包含

index.php
abc.php

目前,此配置将所有内容路由到 index.php/abc.php 除外。尝试将/abc 路由到index.php

谢谢:)

编辑:使用 Ivan 的回答 docker 记录垃圾邮件:

app_1  | -> Executing /opt/docker/bin/service.d/nginx.d//10-init.sh
app_1  | 2020-10-20 10:31:59,273 INFO success: nginxd entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
app_1  | nginx: [emerg] unknown "_uri" variable
app_1  | 2020-10-20 10:31:59,287 INFO exited: nginxd (exit status 1; not expected)

【问题讨论】:

  • 您能否将您当前的 PHP 处理程序配置(通常类似于 location ~ \.php$ { ... })添加到您的问题中?
  • 我正在使用的唯一位置处理配置是主帖中的配置 (10-location-root.conf)。如果还有其他设置,那么它可能来自 webdevops 图像:dockerfile.readthedocs.io/en/latest/content/DockerImages/… - 我是 nginx 新手,以前一直在使用 apache/htaccess,所以我不确定在哪里可以找到 php 处理程序配置的位置
  • 我对 Docker 不熟悉,但是我对 nginx 很熟悉,并且了解你需要什么 nginx 配置来实现你想要的。我查看了文档,在 GitHub 上找到了 this,在我看来,您做的事情完全错了。文档提到/opt/docker/etc/nginx/vhost.common.d/10-location-root.conf,而不是opt/docker/etc/nginx/conf.d/10-location-root.conf。我认为您的修改根本不起作用。
  • 例如,使用您的server 配置,您将根本无法执行任何PHP 脚本,如果abc.php 按预期工作,则意味着其他一些配置会处理它(我认为默认的)。在我看来,您至少需要修改两个文件 - /opt/docker/etc/nginx/vhost.common.d/10-location-root.conf/opt/docker/etc/nginx/vhost.common.d/10-php.conf,也许在 /opt/docker/etc/nginx/conf.d/ 中添加第三个自定义文件,比如说 /opt/docker/etc/nginx/conf.d/maps.conf
  • 你能检查我的第一个变种吗?删除您的/opt/docker/etc/nginx/conf.d/10-location-root.conf,将这两个文件改为并检查它是如何工作的。保持您的 /app/public 内容不变。

标签: docker nginx nginx-location nginx-config


【解决方案1】:

如果我正确理解了这个系统是如何工作的,让我们从以下两个文件开始:

  • /opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
location / {
    try_files $uri $uri/ @extensionless-php;
}
location @extensionless-php {
    rewrite ^ $uri.php last;
}
  • /opt/docker/etc/nginx/vhost.common.d/10-php.conf
location ~ \.php$ {
    try_files $uri /<DOCUMENT_INDEX>?_url=$uri&$args;
    fastcgi_pass php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $request_filename;
    fastcgi_read_timeout <PHP_TIMEOUT>;
}

上述配置有一个严重缺陷。如果请求的 URI 不是现有 PHP 文件的名称(带有或不带有 .php 扩展名),则 $uri 内部 nginx 变量值将始终以 .php 结尾,因为 rewrite 规则在@extensionless-php 命名位置。这将导致以下结果(假设文件 /app/public/some/path.php 不存在):

/some/path => /index.php?_url=/some/path.php

/some/path.php => /index.php?_url=/some/path.php

要解决这个问题,我们可以将原始的 $uri 变量值保存在 extensionless-php 命名位置中:

  • /opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
location / {
    try_files $uri $uri/ @extensionless-php;
}
location @extensionless-php {
    set $original_uri $uri;
    rewrite ^ $uri.php last;
}
  • /opt/docker/etc/nginx/vhost.common.d/10-php.conf
location ~ \.php$ {
    try_files $uri /<DOCUMENT_INDEX>?_url=$original_uri&$args;
    fastcgi_pass php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $request_filename;
    fastcgi_read_timeout <PHP_TIMEOUT>;
}

这个配置比较好,但还是有缺陷。如果请求的 URI 以 .php 结尾并且在 /app/public 目录中没有对应的 PHP 文件,则不会初始化 $original_uri 变量,并且 _url 查询参数将作为空字符串传递给后端:

/some/path => /index.php?_url=/some/path

/some/path.php => /index.php?_url=

这对于某些 Web 应用程序来说是可以的(空的 _url 查询参数总是意味着一个无效的路由),但是如果我们想要得到一个原始的 URI,我们必须做什么呢?我们可以借助 map 指令(一个非常强大的 nginx 功能)来实现它。但是所有的map 块都应该在server 块之外声明,所以我们需要一个额外的文件:

  • /opt/docker/etc/nginx/conf.d/10-map.conf
map $_uri $original_uri {
    ""          $uri;
    default     $_uri;
}
  • /opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
location / {
    try_files $uri $uri/ @extensionless-php;
}
location @extensionless-php {
    set $_uri $uri;
    rewrite ^ $uri.php last;
}
  • /opt/docker/etc/nginx/vhost.common.d/10-php.conf
location ~ \.php$ {
    try_files $uri /<DOCUMENT_INDEX>?_url=$original_uri&$args;
    fastcgi_pass php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $request_filename;
    fastcgi_read_timeout <PHP_TIMEOUT>;
}

这个map 块意味着$original_uri 变量将等于$uri,如果它没有被修改($_uri 变量没有初始化并且为空)。如果$_uri 变量不为空,则意味着原始$uri 已修改,$_uri 变量现在保持其原始值,因此$original_uri 变量的值将设置为$_uri。此配置适用于将原始 URI 保留为 _url 查询参数的任何请求。

【讨论】:

  • 嘿,Ivan,所以当我使用这些 sn-ps 时,所有路由都无法加载,并且我的 docker 日志中充满了垃圾邮件:app_1 | -&gt; Executing /opt/docker/bin/service.d/nginx.d//10-init.sh app_1 | 2020-10-20 10:31:59,273 INFO success: nginxd entered RUNNING state, process has stayed up for &gt; than 0 seconds (startsecs) app_1 | nginx: [emerg] unknown "_uri" variable app_1 | 2020-10-20 10:31:59,287 INFO exited: nginxd (exit status 1; not expected) - cmets 中的格式非常难看,所以我将更新我的主要发布
  • 我尝试用10-php.conf 替换10-php.conf 中的$_uri 变量(不确定这是否正确),我之前也有类似的行为,只有abc.php 有效,@987654375 无效@,仅使用 /abc 我的应用程序似乎因 [error] 65#65: *1 could not find named location "@extensionless-php", client: 172.22.0.1, server: _, request: "GET /favicon.ico HTTP/1.1", host: "localhost:8080", referrer: "http://localhost:8080/" 而崩溃
  • @Arthur 我的错,有两个错别字。已更正(查看答案编辑历史记录),您现在可以查看吗?
  • @Arthur 很高兴听到这个消息,现在我们知道如何在 docker 中修改 nginx 配置,但是整个配置还没有完成。这是第一次尝试检查我的方法是否有效,但它会将/some/path 之类的请求作为_url=/some/path.php 查询参数传递给index.php 脚本。我会写一个更新的答案来解决这个问题并让你知道。
  • @Arthur Phew,我完成了。请在测试时提供一些反馈。由于您是 nginx 新手,因此我尝试尽可能多地解释此配置的工作原理。这意味着它充满了各种英语错误,所以如果你是一个以英语为母语的人,你可以修复一些:)(你的代表应该允许你编辑我的答案,对吗?)
猜你喜欢
  • 2016-07-22
  • 1970-01-01
  • 2015-10-10
  • 2018-07-16
  • 1970-01-01
  • 1970-01-01
  • 2015-06-15
  • 1970-01-01
相关资源
最近更新 更多