V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
happyjohann
V2EX  ›  NGINX

怎样配置干净的 PHP 接口链接? How to configure Nginx to have clean PHP API URL?

  •  
  •   happyjohann · 2017-02-23 21:07:36 +08:00 · 3269 次点击
    这是一个创建于 2611 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不好意思,因为在公司写英文,所以以下问题是用英文写的。

    Configuration 1:

    server {
      index index.html index.php
    
      location / {
        try_files $uri $uri/;
      }
    
      location ~ [^/]\.php(/|$) {
        fastcgi_pass unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
      }
    }
    

    Configuration like the above (Configuration 1) will return 500 Internal Server Error when visiting ...domain.../20170223, ...domain.../20170223/ but not ...domain.../20170223/index.php.

    So I am think try_files is executed before index and then cause a internal redirect loop thus 500 Server Internal Error because if index runs first then .../20170223/ should works just fine while in fact is not.

    But

    Configuration 2:

    server {
      index index.html index.php
    
      location / {
        try_files $uri $uri/ =404;
      }
    
      location ~ [^/]\.php(/|$) {
        fastcgi_pass unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
      }
    }
    

    works for all ...domain.../20170223, ...domain.../20170223/ and ...domain.../20170223/index.php.

    Which leads me to think when try_files is encountered with folder URI like .../20170223/ it makes an internal redirect. But contradiction is if try_files runs before index, it will be a redirect loop which is not true in this practice.

    Then there is again not clue which one (try_files or index) runs first.

    To exclude the position of index directive problem, the following configuration 3 & 4 are tested with same result as Configuration 1.

    Configuration 3:

    server {
    
      location / {
        index index.html index.php
        try_files $uri $uri/;
      }
    
      location ~ [^/]\.php(/|$) {
        fastcgi_pass unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
      }
    }
    

    Configuration 4:

    server {
    
      location / {
        try_files $uri $uri/;
        index index.html index.php
      }
    
      location ~ [^/]\.php(/|$) {
        fastcgi_pass unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
      }
    }
    

    And there comes my problem.

    The Configuration 2 doesn't receive POST data from a <form> submit when action is assigned with ...domain.../20170223 but works for ...domain.../20170223/ and ...domain.../20170223/index.php.

    So why??? Does internal redirect lost POST data? Does try_files append index.php to folder uri according to index first and then make a redirect? In the different words for same meaning, does try_files make redirect but index never make redirect? Is index a dictionary for try_files whose default value is just try_files $uri =404; (this assumption still didn't explain for Configuration 1 practice)?

    No idea according to the following official documents:

    with the summary:

    • index processes requests ending with the slash character (‘/’), and note that using an index file causes an internal redirect, and the request can be processed in a different location (for instance, a “/” request may actually be processed in a second location as “/index.html ”.).
    • try_files has specified ordered file lists and uri or =code at last, if none of the files were found, then an internal redirect to the uri specified in the last parameter is made. (Notice: only the last part is internal redirect, the ones ahead are all served directly by Nginx as static files.)

    And is there any solve to have a clean post action url without tailing slash /?

    10 条回复    2017-02-26 09:17:47 +08:00
    printempw
        1
    printempw  
       2017-02-23 23:33:28 +08:00 via Android
    尝试 `try_files $uri $uri/ /index.php?$query_string;`?
    szopen
        2
    szopen  
       2017-02-24 13:45:55 +08:00
    这个还得看程序,例如我搞的框架 https://github.com/chopins/toknot , nginx 配置就十分简单, FastCGI 配置块就如下:

    location / {
    fastcgi_index index.php;
    root $your_web_public/index.php;
    fastcgi_pass php-fpm;
    include fastcgi.conf;
    }

    然后在前面把静态路径排除就行了,这种配置无需在 nginx 中维护大量的重写规则
    orderc
        3
    orderc  
       2017-02-24 19:50:18 +08:00
    @szopen 路由参数通过 url 传递吗
    happyjohann
        4
    happyjohann  
    OP
       2017-02-24 20:14:38 +08:00
    @printempw 你这个本质上和我第二个没有什么区别,考虑 try_files 的执行顺序。另外我没有采用 /index.php 处理所有找不到对应文件夹和脚本的方式。
    happyjohann
        5
    happyjohann  
    OP
       2017-02-24 20:16:17 +08:00
    @szopen 你这是是用 PHP 在根目录的 index.php 处理所有 URL 了,不是应用 Nginx 的好的实践方案哦。
    szopen
        6
    szopen  
       2017-02-24 20:35:04 +08:00
    @happyjohann 这个方案是最灵活的处理方案,这样 nginx 不需要关联任何业务逻辑上的东西,并且能做很灵活的访问权限控制
    happyjohann
        7
    happyjohann  
    OP
       2017-02-25 00:03:07 +08:00
    @szopen 问题是我在同一个域名之下用了多种语言的后台程序。这也是为什么用 Nginx 而不是 Apache 的一个重要原因。
    szopen
        8
    szopen  
       2017-02-25 12:18:16 +08:00
    @happyjohann 对于多程序的后台程序,如果后端程序有很清晰的访问规则也很好弄,如果本省后端程序访问规则就不清晰,那也就不存在所谓的最佳方法了
    Showfom
        9
    Showfom  
       2017-02-25 13:35:18 +08:00 via iPhone
    同意 看程序的
    happyjohann
        10
    happyjohann  
    OP
       2017-02-26 09:17:47 +08:00
    @szopen 结构是清晰的,你说的办法在跑题。我现在的要求挺简单的,就是用 Nginx 做一个干净的可以提交 POST 数据的 URL ,不涉及用 PHP 路由。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2813 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 00:27 · PVG 08:27 · LAX 17:27 · JFK 20:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.