有条件的重写,如何管理PHP脚本?

时间:2017-07-12 11:46:28

标签: nginx url-rewriting

我需要创建一个我无法测试的 API网关 ...但问题是关于管理PHP脚本。

我需要什么

  • 所有文件HTML或PHP
  • my1issn的特殊名称在2018端口重定向到localhost
  • my2my3的特殊名称重定向到ETC.php

说明

Pseudocode详情为“我需要什么”,

if ($uri exists) {
    if extension is .php use it with php7.0-fpm.sock
    else use it as static page;
} else 
   try the @proxy_rewrite_engine;

@proxy_rewrite_engine =  
  if (regex ^\(my[23])$ use 
       ETC.php;
  elseif (regex ^/(\d+)/my1$  use 
       http://127.0.0.1:2018?type=int&val=$1
  elseif ^/([0-9]+\-\d+[Xx]?)/issn$  use 
       http://127.0.0.1:2018?type=str&val=$1
  else 
       say error;

我尝试了什么

我有问题的解决方案,请展示一个真正的解决方案,将“说明”部分翻译成具体和正确的NGINX脚本代码。

...下面,我的错误 - NGINX脚本提供线索和灵感,这不是解决方案......需要使用if而不是location吗? fastcgi_param有效吗?我可以将地点分组吗?

  server {
    server_name  test.mytest.news;

    root   /var/www/test;
    index  index.php index.html index.htm;

    location  / {
        try_files $uri $uri/ @proxy;
    }

    location  ~ \.php$ {
      try_files $uri =404;
      include /etc/nginx/fastcgi.conf; # without SCRIPT_FILENAME 
      fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
      fastcgi_pass unix:/run/php/php7.0-fpm.sock;
    }

    location  @proxy {
      rewrite ^\?(my[23])$                 $document_root/ETC.php?cmd=$1 
             last;
      rewrite  ^/(\d+)/my1$                ?type=int&val=$1 
             break;
      rewrite  ^/([0-9]+\-\d+[Xx]?)/issn$  ?type=str&val=$1  
             break;
      proxy_pass http://127.0.0.1:2018;
    }

    include  snippets/ssl-test.mytest.news.conf;

  } #end server

注意@cnst评论:假设我在说“所有文件HTML或PHP” = 时需要try_files必须尝试其他文件tham index.htm,可以是文件夹,图像和其他文件。

2 个答案:

答案 0 :(得分:3)

如果希望“脚本100%可靠,通过构建(而不是通过测试)”,那么将多个独立问题放在一个问题中可能不是最好的方法。 / p>

  1. 在将请求传递给单独的后端之前必须检查文件是否存在的理由并不完全清楚,特别是如果请求与给定的正则表达式匹配,例如issn$。最好的方法是对案件的每个不同处理使用单独的location指令。

  2. 更具体地说,您的方法也存在以下错误:rewrite ^\?(my[23])$中的正则表达式不太可能匹配任何请求,因为所有外部请求都以斜杠开头。

  3. 同样,根据https://serverfault.com/a/864778/110020rewrite ^/(\d+)/my1$ ?type=int&val=$1中的替换字符串不太可能正确;事实上,当我尝试上面的代码时,根据500 Internal Server Error,我得到的是nginx/error.log

    2017/07/24 08:46:22 [error] 45776#0: *2 the rewritten URI has a zero length, client: 127.0.0.1, server: , request: "GET /44444/my1 HTTP/1.1", host: "localhost:

    这是因为您确实将URI重写为空的 - 问号?及其后的任何内容,在nginx中的请求处理中通常不是URI的一部分,因此,URI确实是空的。解决方案:至少在?前面放一个斜杠(即/?id=),或者更好的是,必须激活脚本的全名(特别是因为这只是一个内部重定向)

答案 1 :(得分:0)

Nginx适用于大型配置。糟糕的主意是优化nginx.conf。 做起来很简单,它会努力工作:) 我认为像这样的配置可以正常工作:

# Try to load existing files
location  / {
    try_files $uri $uri/ @rewriteIt;
}

# Handle all requests except two other locations below
location  @rewriteIt {
   # Send it to index.php
   rewrite ^(.*)$ /index.php?cmd=$1 last;
}

# This RegExp location will rewrite to ETC.php
# It is more priority, than "/" and @rewriteIt
location ~ ^(my2|my3) $ {
    rewrite ^(.*)$ /ETC.php?cmd=$1 last;
    include /etc/nginx/fastcgi.conf; # without SCRIPT_FILENAME 
    fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}

# This RegExp location will proxy to 2018 port
# It is more priority, than "/" and @rewriteIt
location ~ ^(my1|issn) $ {
  proxy_pass http://127.0.0.1:2018;
}

# This location handles all php files to php-fpm
location  ~ \.php$ {
  try_files $uri =404;
  include /etc/nginx/fastcgi.conf; # without SCRIPT_FILENAME 
  fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
  fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}