我试图在同一个主机名上运行两个网站,其中一个提供静态内容(AngularJS 应用程序),另一个将所有请求路由到 PHP(使用 Apigility 编写的 API),但仅针对 URL 中的特定路径(稍后会详细介绍)。
目前,我有两个 nginx vhost 在两个不同的域上监听,它们工作得很好,但是客户端应用程序最终将使用 OAuth 对 API 进行身份验证,并且我不想在客户端的 cookie、本地存储或任何其他地方存储令牌或任何其他敏感数据。本文比我自己能解释的更好地解释了其背后的原因。
考虑到这个问题,我决定使用一个“代理”服务器,它将默认(重要)提供客户端浏览器请求的任何静态内容,但是如果收到以 开头的请求,/api/
则应将其重新路由到 php-fpm。
举个例子,假设 API 有一个端点/users
。我想要做的是像平常一样运行我的 AngularJS 应用程序,例如,http://monkey.com/index.html
但同时,如果我执行 AJAX 请求,http://monkey.com/api/users
它应该将位转发/users
到 PHP,后者将安装在不同的目录中(为了回答这个问题,假设 AngularJS 应用程序安装在中/var/www/website
,API 位于中/var/www/api
。
这是我目前拥有的两个配置,它们作为独立的网站运行:
AngularJS 应用程序配置:
server {
listen 80;
server_name monkey.com;
root /var/www/website;
index index.html
location / {
try_files $uri $uri/ /index.html =404;
}
}
API 配置:
server {
listen 80;
server_name api.monkey.com;
root /var/www/api/public;
index index.php
include /etc/nginx/fcgiwrap.conf;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
}
}
为了避免混淆,我不会发布我失败的尝试,但我只能说我尝试过使用root
,但alias
无济于事。我想我最大的问题是我不确定如何只提取后面的部分/api
并将其转发到 PHP,而 PHP 位于与$document_root。
我已经看到很多文章和答案,其中提到在条目root
内部添加location
不是一个好主意,但我认为不这样做就无法解决这个问题。
我已经为这个看似简单的问题奋斗了一段时间,所以我希望有人能给出一个真正有效的配置示例。
答案1
在花费了大量时间尝试获取可行的配置后,我似乎终于成功了。
我现在可以从同一个域执行请求http://monkey.com/some/angular/path
并http://monkey.com/api/users
分别提供静态内容或 PHP 站点。
如果有人偶然发现这个问题,下面是我最终得到的配置:
server {
listen 80;
server_name monkey.com;
location / {
alias /var/www/website/;
try_files $uri $uri/ /index.html =404;
}
location /api/ {
alias /var/www/api/public;
try_files /index.php =404;
set $path $request_uri;
if ($request_uri ~ ^/api/(.*)$ ) {
set $path /$1;
}
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param REQUEST_URI $path;
}
}
上述配置删除/api/
前缀并设置REQUEST_URI
为其后的任何内容。例如,如果您请求,monkey.com/api/users/1
则最终会传递/users/1
给 php-fpm。
如果您不需要以任何方式修改原始请求 URI,而只想将整个请求 URI 传递给 PHP,则可以简化(并可能加快)配置,如下所示:
server {
listen 80;
server_name monkey.com;
location / {
alias /var/www/website/;
try_files $uri $uri/ /index.html =404;
}
location /api/ {
alias /var/www/api/public;
try_files /index.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
}
现在开始设置狂饮代理网站的项目!
答案2
首先要做的事情:如果没有“Andris”和 Google 以及其他人的努力,这个代码就不可能实现。请阅读他的代码首先,如果失败了,请阅读此内容!
Angular 或任何其他服务都可以在端口 4200 和默认路径上提供服务 / 例如:http://example.com/将运行角度。
任何 URL 请求,例如http://example.com/api/index.php将被重定向到适当的路由,并从中删除“/api”。因此http://example.com/api/index.php将被视为http://example.com/index.php
我刚刚测试了此代码,如果有任何补丁和建议,请回复!
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name localhost;
#root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://127.0.0.1:4200;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /api/ {
root /var/www/api/public;
try_files /index.php =404;
set $path $request_uri;
if ($request_uri ~ ^/api/(.*)$ ) {
set $path /$1;
}
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$path;
fastcgi_param REQUEST_URI $path;
# index index.php index.html index.htm;
}
}