php - 如何将简单的 index.php 重定向从 apache 转换为 nginx 格式?
问题描述
从一个旧项目中,我得到了这个 .htaccess 文件,它当前处理 apache 重写规则:
<IfModule mod_rewrite.c>
RewriteEngine On
# Folders / files to exclude from rewrite divided by Pipe goes here:
RewriteRule (^|/)install(/|$) - [L,NC]
RewriteRule (^|/)web(/|$) - [L,NC]
# turn empty requests into requests for "index.php",
# keeping the query string intact
RewriteRule ^$ index.php [QSA]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !favicon.ico$
RewriteRule ^(.+)$ index.php [QSA,L]
RewriteRule ^(.+)$ index.php [QSA,L]
</IfModule>
上面的代码片段基本上做了什么,它通过保持查询部分字符串完整并在第一次匹配后停止来重写对 index.php 的所有请求,除非文件或文件夹存在。
因此,总而言之,通过查阅 Nginx 文档并添加一些额外的安全性(允许访问合理的文件夹和文件)和与性能相关的东西(在可能的情况下启用 gzip 或 brotli 输出压缩[取决于客户端,它是哪一个)能够处理]),我得到了这个:
server {
listen 80;
listen [::]:80;
server_name subdomain.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name tdc.wunner-software.de;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Add headers to serve security-related headers
# Before enabling Strict-Transport-Security headers please read into this
# topic first.
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
#
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;
# Path to the root of your installation
root /srv/www/vhosts/example.com/subdomain.example.com;
index index.php index.html;
charset utf-8;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# set max upload size
client_max_body_size 512M;
fastcgi_buffers 64 4K;
# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
brotli on;
brotli_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
# Adding the cache control header for js, css and map files
# Make sure it is BELOW the PHP block
location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
# Add headers to serve security related headers (It is intended to
# have those duplicated to the ones above)
# Before enabling Strict-Transport-Security headers please read into
# this topic first.
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
# Optional: Don't log access to assets
access_log off;
}
location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ {
try_files $uri /index.php$request_uri;
# Optional: Don't log access to other assets
access_log off;
}
location ~ ^/vendor/.*$ {
deny all;
}
location ~ ^\.htaccess$ {
deny all;
}
#rewrite ^(.*)/$ index.php$is_args$args break;
location ~ /(.*)$ {
index index.php;
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi.conf;
fastcgi_param HTTP_PROXY "";
fastcgi_param HTTPS $https;
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
fastcgi_read_timeout 300s;
client_body_buffer_size 128k;
fastcgi_pass php-handler;
http2_push_preload on;
}
access_log /var/log/nginx/subdomain_example_com_ccess.log;
error_log /var/log/nginx/subdomain_example_com_error.log;
}
上面的新 Nginx 配置下载 PHP 文件,而不是将其绕过到 FPM 处理程序。我发现了这个和这个SO 问题,但它似乎对我没有用。此外,正如 Nginx 文档中所述,if
它是邪恶的,除非我们 100% 确定发生了什么,否则我们应该避免使用它。因此,对于我的配置,我避免使用它。主要是因为 regex 语法也适用于这种情况,location
并且在这种情况下比if
. 我的意思是,据我所知。请纠正我,如果我错了。
主nginx.conf
文件现在非常简单:
user nginx;
worker_processes 1;
# load_module lib64/nginx/modules/ngx_http_fancyindex_module.so;
# load_module lib64/nginx/modules/ngx_http_geoip_module.so;
# load_module lib64/nginx/modules/ngx_http_headers_more_filter_module.so;
# load_module lib64/nginx/modules/ngx_http_image_filter_module.so;
# load_module lib64/nginx/modules/ngx_http_perl_module.so;
# load_module lib64/nginx/modules/ngx_http_xslt_filter_module.so;
# load_module lib64/nginx/modules/ngx_mail_module.so;
# load_module lib64/nginx/modules/ngx_rtmp_module.so;
# load_module lib64/nginx/modules/ngx_stream_geoip_module.so;
# load_module lib64/nginx/modules/ngx_stream_module.so;
error_log /var/log/nginx/error.log;
#error_log /var/log/nginx/error.log notice;
error_log /var/log/nginx/error.log info;
#pid /run/nginx.pid;
events {
worker_connections 1024;
use epoll;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
gzip on;
include conf.d/*.conf;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /srv/www/htdocs/;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /srv/www/htdocs/;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
root /srv/www/htdocs/;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files if Apache's document root
# concurs with Nginx's one
#
location ~ /\.ht {
deny all;
}
}
# another virtual host using a mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root /srv/www/htdocs/;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# Allow TLS version 1.2 only, which is a recommended default these days
# by international information security standards.
# ssl_protocols TLSv1.2;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root /srv/www/htdocs/;
# index index.html index.htm;
# }
#}
include vhosts.d/*.conf;
}
上面的文件主要是 openSUSE 发行商自带的文件,有一些改动。
这是我的base.conf
文件,它定义了 nginx 的 FPM 代理处理程序(为了不重复自己;无论如何它都是必需的):
upstream php-handler {
server 127.0.0.1:9000;
#server unix:/var/run/php/php7.2-fpm.sock;
}
我将不胜感激有关该问题的任何帮助。
解决方案
上面的代码片段基本上做了什么
您可能需要一些时间来考虑这些规则所做的不太明显的事情。
上面的新 Nginx 配置下载 PHP 文件而不是绕过它到 FPM 处理程序
因为您对 php 脚本的所有引用都被拦截,location ~ \.(?:css|js|woff2?|svg|gif|map)$
因此不会将工作移交给 PHP FPM。了解 nginx 考虑 location{} 块的优先级对于实现成功的配置至关重要。
您的 try_files 指令似乎适用于整个服务器,但您已将其放在位置块中。它应该在服务器块中,以便在nginx 尝试匹配位置块之前应用它。
使用虚拟(或“命名”)位置块提供了一种处理默认选项具有处理程序(如 PHP)的情况的方法。请参阅try_files 文档中的Drupal/Fastcgi 示例。
你的配置应该看起来像
server {
...
try_files $uri @phpfpm;
location ~ \.(css|js|woff2?|svg|gif|map)$ {
add_header Cache-Control "public, max-age=15778463";
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
access_log off;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi.conf;
fastcgi_param HTTP_PROXY "";
fastcgi_param HTTPS $https;
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
fastcgi_read_timeout 300s;
client_body_buffer_size 128k;
fastcgi_pass php-handler;
http2_push_preload on;
}
location @phpfpm {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi.conf;
fastcgi_param HTTP_PROXY "";
fastcgi_param HTTPS $https;
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
fastcgi_read_timeout 300s;
client_body_buffer_size 128k;
fastcgi_pass php-handler;
http2_push_preload on;
}
虽然你真的应该将所有 PHP 配置打包在一个单独的文件中。此外,您似乎有点担心获得良好的性能,但使用的是与本地主机的 TCP 套接字连接而不是文件系统套接字——这会影响性能和容量。
推荐阅读
- swift - Swift中的多个自变量/多元线性回归
- c# - 如何将多个参数传递给 sqlite IN 子句并防止 SQL 注入?
- python - 会话和并行性在 TF2.0 中如何工作?
- javascript - 我正在尝试使用两个按钮计算按钮点击的总数并将其显示在文本区域中
- javascript - 将对象的值数字转换为字符串无法正常工作
- python - 填充缺失值的数据框(熊猫)
- postgresql - 让 LIKE 搜索使用 citext 表达式的索引
- excel - 删除 A 列或 B 列中的单元格为空的行
- go - 使用给定数据创建一个 JSON 数据作为 map[string] 接口
- azure - 如何基于孤盘创建快照