使用 nginx 在同一域上提供反应前端和 php 后端

使用 nginx 在同一域上提供反应前端和 php 后端

问题描述:

我有一个 React 前端和一个 Symfony 后端,我正试图在同一个域上提供服务.React 前端需要提供资产(如果存在),否则回退以提供 index.html.

I have a React frontend and a Symfony backend I'm trying to serve on the same domain. The React frontend needs to serve assets if they exist otherwise fallback to serve index.html.

/api 在请求 uri 中时,我想为 php Symfony 应用程序提供服务.与 React 应用程序类似,我需要所有请求都转到 index.php 文件.

I'd like to serve the php Symfony app when /api is in the request uri. Similar to the React app, I need all requests to go to the index.php file.

前端服务正确,但 api 服务不正确.当我在浏览器中点击 /api 时,我从 nginx 得到 404.

The frontend is being served correctly but not the api. I get a 404 from nginx when i hit /api in the browser.

我觉得我很接近但是由于某种原因nginx没有正确的$document_root.我正在添加一个标题(X-script)来测试变量是什么,我得到以下内容:

I feel like i'm close but for some reason nginx doesn't have the correct $document_root. I'm adding a header(X-script) to test what the variables are and I'm getting the following:

X-script: /usr/share/nginx/html/index.php

这是我的 nginx 配置.

Here's my nginx config.

server {
    listen 80 default_server;
    index index.html index.htm;

    access_log /var/log/nginx/my-site.com.log;
    error_log /var/log/nginx/my-site.com-error.log error;

    charset utf-8;

    location /api {
        root /var/www/my-site.com/backend;
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location / {
        root /var/www/my-site.com/frontend;
        try_files $uri /index.html;
    }
    location ~* \.php$ {
        add_header X-script "$document_root$fastcgi_script_name" always;
        try_files $fastcgi_script_name =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS off;
    }
}

任何帮助将不胜感激.

在以下 vhost 中,我所做的最重要的更改是:

In the following vhost, the most important changes I made are :

  • 在 server 块中注释掉 index 指令:它直接在 location 块中处理
  • location/api/ 之后添加了一个斜杠,并在同一个 api location 块中删除了不必要的 $uri/
  • 将 php_fpm 逻辑移动到 index.php 位置块:您希望所有请求都传递到 Symfony 应用程序中的前端控制器
  • 出于同样的原因,将 404 逻辑移至通用 php 块,该块将处理任何其他 php 文件请求
  • commented out index directive in server block : it is handled directly in locations blocks
  • added a slash after location /api/ and remove unnecessary $uri/ in the same api location block
  • moved the php_fpm logic to index.php location block : you want all requests to be passed to front controller in Symfony app
  • For the same reason, moved the 404 logic to a general php block, which will handle any other php file request
server {
    listen 80 default_server;

    access_log /var/log/nginx/my-site.com.log;
    error_log /var/log/nginx/my-site.com-error.log error;

    charset utf-8;

    location /api/ {
        root /var/www/my-site.com/backend;
        try_files $uri  /index.php$is_args$args;
    }

    location / {
        root /var/www/my-site.com/frontend;
        try_files $uri /index.html;
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_param HTTPS off;

        internal;
    }

    # return 404 for all other php files not matching the front controller
    # this prevents access to other php files you don't want to be accessible.
    location ~ \.php$ {
        return 404;
    }
}

最后,我敢打赌你必须将 symfony 公共文件夹添加到 api location block 根指令中.

Last, I bet you'll have to add symfony public folder into api location block root directive.

这个虚拟主机在我的本地主机上通过以下树进行了良好的测试.

This vhost was tested fine on my localhost with following tree.

api_test
  - backend
    - index.php
  - frontend
    - index.html

我可以成功访问

  • backend/index.php 来自 api_test.dv/api
  • frontend/index.html 来自 api_test.dv/
  • backend/index.php from api_test.dv/api
  • frontend/index.html from api_test.dv/