Laravel 4 和 Nginx 中的奇怪路由问题
Weird Routing Issue in Laravel 4 and Nginx
我遇到了 Laravel 4 和 Nginx 的奇怪路由问题。我相信这很可能是 Nginx 问题,而不是 Laravel.
可以访问任何存在的路由:
/index.php/route
更奇怪的是,index.php 之前的任何内容也都有效:
/abcdefg/abcdef/abcde/abcd/abc/ab/a/index.php/route
路线有多长并不重要,只要 index.php 之后的任何路段在 routes.php.
内正确定义即可
第一个示例使用 CSS/JS 等加载正确的路线,但第二个示例没有,它仅加载 HTML.
有没有人遇到过这种情况,如果遇到过,在这两种情况下,您如何才能阻止这种情况发生?谢谢
更新:好的伙计们,下面是我的 Nginx 配置:
# Enable compression both for HTTP/1.0 and HTTP/1.1.
gzip_http_version 1.1;
# Compression level (1-9).
# 5 is a perfect compromise between size and cpu usage, offering about
# 75% reduction for most ascii files (almost identical to level 9).
gzip_comp_level 5;
# Don't compress anything that's already small and unlikely to shrink much
# if at all (the default is 20 bytes, which is bad as that usually leads to
# larger files after gzipping).
gzip_min_length 500;
# Compress data even for clients that are connecting to us via proxies,
# identified by the "Via" header (required for CloudFront).
gzip_proxied any;
# Tell proxies to cache both the gzipped and regular version of a resource
# whenever the client's Accept-Encoding capabilities header varies;
# Avoids the issue where a non-gzip capable client (which is extremely rare
# today) would display gibberish if their proxy gave them the gzipped version.
gzip_vary on;
# Compress all output labeled with one of the following MIME-types.
gzip_types application/atom+xml application/x-javascript text/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component;
server {
listen 80;
server_name www.domain.com domain.com;
return 301 https://domain.com$request_uri;
}
server {
listen 443 ssl;
server_name domain.com;
root /home/forge/default/public;
if ($host = 'www.domain.com') {
rewrite ^/(.*)$ https://domain.com/ permanent;
}
# FORGE SSL (DO NOT REMOVE!)
# ssl on;
ssl_certificate /etc/nginx/ssl/default/4980/server.crt;
ssl_certificate_key /etc/nginx/ssl/default/4980/server.key;
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
# auth_basic "Restricted Area";
# auth_basic_user_file /home/forge/default/.htpasswd;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/default-error.log error;
error_page 404 /index.php;
# error_page 404 https://domain.com/404;
location ~ \.php$ {
try_files $uri $uri/ /index.php?$query_string;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ \.html$ {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ /\.ht {
deny all;
}
# Expire rules for static content
# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
expires -1;
# access_log logs/static.log; # I don't usually include a static log
}
# Feed
location ~* \.(?:rss|atom)$ {
expires 1h;
add_header Cache-Control "public";
}
# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|woff)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
# CSS and Javascript
location ~* \.(?:css|js)$ {
expires 1y;
access_log off;
add_header Cache-Control "public";
}
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
}
尝试将您的第二个位置块更改为:
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
好的伙计们,看来我已经解决了这个问题。我最初尝试使用 Route::filter 来检测 index.php 然后执行重定向但是没有用,所以我使用 App::before 像这样:
App::before(function($request)
{
if (strpos($request->url(), 'index.php/'))
{
return Redirect::to(str_replace(['index.php/'], '', $request->url()), 301);
}
if (strpos($request->url(), 'index.php'))
{
return Redirect::to(str_replace(['index.php'], '', $request->url()), 301);
}
});
这解决了这两个问题并将请求重定向到不再包含 index.php 的 URI。希望这对可能遇到此问题的其他人有所帮助。
我遇到了 Laravel 4 和 Nginx 的奇怪路由问题。我相信这很可能是 Nginx 问题,而不是 Laravel.
可以访问任何存在的路由:
/index.php/route
更奇怪的是,index.php 之前的任何内容也都有效:
/abcdefg/abcdef/abcde/abcd/abc/ab/a/index.php/route
路线有多长并不重要,只要 index.php 之后的任何路段在 routes.php.
内正确定义即可第一个示例使用 CSS/JS 等加载正确的路线,但第二个示例没有,它仅加载 HTML.
有没有人遇到过这种情况,如果遇到过,在这两种情况下,您如何才能阻止这种情况发生?谢谢
更新:好的伙计们,下面是我的 Nginx 配置:
# Enable compression both for HTTP/1.0 and HTTP/1.1.
gzip_http_version 1.1;
# Compression level (1-9).
# 5 is a perfect compromise between size and cpu usage, offering about
# 75% reduction for most ascii files (almost identical to level 9).
gzip_comp_level 5;
# Don't compress anything that's already small and unlikely to shrink much
# if at all (the default is 20 bytes, which is bad as that usually leads to
# larger files after gzipping).
gzip_min_length 500;
# Compress data even for clients that are connecting to us via proxies,
# identified by the "Via" header (required for CloudFront).
gzip_proxied any;
# Tell proxies to cache both the gzipped and regular version of a resource
# whenever the client's Accept-Encoding capabilities header varies;
# Avoids the issue where a non-gzip capable client (which is extremely rare
# today) would display gibberish if their proxy gave them the gzipped version.
gzip_vary on;
# Compress all output labeled with one of the following MIME-types.
gzip_types application/atom+xml application/x-javascript text/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component;
server {
listen 80;
server_name www.domain.com domain.com;
return 301 https://domain.com$request_uri;
}
server {
listen 443 ssl;
server_name domain.com;
root /home/forge/default/public;
if ($host = 'www.domain.com') {
rewrite ^/(.*)$ https://domain.com/ permanent;
}
# FORGE SSL (DO NOT REMOVE!)
# ssl on;
ssl_certificate /etc/nginx/ssl/default/4980/server.crt;
ssl_certificate_key /etc/nginx/ssl/default/4980/server.key;
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
# auth_basic "Restricted Area";
# auth_basic_user_file /home/forge/default/.htpasswd;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/default-error.log error;
error_page 404 /index.php;
# error_page 404 https://domain.com/404;
location ~ \.php$ {
try_files $uri $uri/ /index.php?$query_string;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ \.html$ {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ /\.ht {
deny all;
}
# Expire rules for static content
# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
expires -1;
# access_log logs/static.log; # I don't usually include a static log
}
# Feed
location ~* \.(?:rss|atom)$ {
expires 1h;
add_header Cache-Control "public";
}
# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|woff)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
# CSS and Javascript
location ~* \.(?:css|js)$ {
expires 1y;
access_log off;
add_header Cache-Control "public";
}
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
}
尝试将您的第二个位置块更改为:
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
好的伙计们,看来我已经解决了这个问题。我最初尝试使用 Route::filter 来检测 index.php 然后执行重定向但是没有用,所以我使用 App::before 像这样:
App::before(function($request)
{
if (strpos($request->url(), 'index.php/'))
{
return Redirect::to(str_replace(['index.php/'], '', $request->url()), 301);
}
if (strpos($request->url(), 'index.php'))
{
return Redirect::to(str_replace(['index.php'], '', $request->url()), 301);
}
});
这解决了这两个问题并将请求重定向到不再包含 index.php 的 URI。希望这对可能遇到此问题的其他人有所帮助。