larave/nginx постоянно возвращает 301 Moved Permanently
Разрабатываю приложение на laravel и vue. Локально всё работает прекрасно. Но когда загрузил приложение на сервер обнаружил что не работает ссылка из письма при подтверждении почты, а именно при переходе по ссылке из письма вечно происходит редирект и браузер выдаёт "Сайт выполнил переадресацию слишком много раз."
Ссылка из письма выглядит следующим образом -> http://mysite/email/verify/4/09VVTt2BKtjyUoXQoLamqOaZuauXSSvf?signature=5741aad143a4580fa785c6647c11923f1121e899d20cc770fb66a4e74e3933c4
Приложение делает переадресацию на http://mysite/auth/register/verify?next=http://mysite/email/verify/4/09VVTt2BKtjyUoXQoLamqOaZuauXSSvf?signature=5741aad143a4580fa785c6647c11923f1121e899d20cc770fb66a4e74e3933c4
nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/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 65;
gzip on;
gzip_proxied any;
gzip_types
text/css
text/javascript
text/xml
text/plain
application/javascript
application/x-javascript
application/json;
client_max_body_size 32m;
server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/public;
location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires max;
log_not_found off;
}
# Remove index.php$
if ($request_uri ~* "^(.*/)index\.php$") {
return 301 $1;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
# Remove from everywhere index.php
if ($request_uri ~* "^(.*/)index\.php(/?)(.*)") {
return 301 $1$3;
}
}
# Remove trailing slash.
if (!-d $request_filename) {
rewrite ^/(.+)/$ /$1 permanent;
}
# Clean Double Slashes
if ($request_uri ~* "\/\/") {
rewrite ^/(.*) /$1 permanent;
}
# enforce NO www
if ($host ~* ^www\.(.*))
{
set $host_without_www $1;
rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
}
location ~* \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
}
роут отвечающий за переадресацию
Route::get('/email/verify/{id}/{hash}', function (\Illuminate\Http\Request $request, $id) {
if(Auth::guest())
{
return redirect('/auth/register/verify?next='.Request::fullUrl());
}
else
{
return redirect('/app/dashboard');
}
})->name('email-verify')->middleware(['signed']);
В первую очередь пробовал чистить кэш браузера и приложения... не помогло. С nginx я мало знаком...
Понимаю как это выглядит... прошу помощи не до конца разобравшись с nginx. Но я даже не знаю с чего начать... где именно я ошибся или почему происходит зацикливание редиректа. Помогите понять почему это происходит... само приложение и nginx работают в docker контейнерах.
Ответы (1 шт):
Проблему решил. Всё дело в самой ссылке. Нужно было просто экранировать все специальные символы в URL. ссылка на PDF в котором рассказывается как надо экранировать специальные символы -> https://честныйзнак.рф/upload/iblock/d53/Рекомендуемый_алгоритм_экранирования_специальных_символов_в_коде_идентификации_ки.pdf
Однако что конкретно вызвало такое поведения мне не удалось. Вероятно дело в Laravel. Сопоставление адреса с маршрутом отрабатывало некорректно. т.е. laravel при сопоставлении маршрута находил второе вхождение http://mysite/ и работал с ним (брал первый попавшийся роут который совпадал по маршруту, а именно он брал 'email-verify' и снова редиректил на длинный путь с двумя вхождениями http://mysite/ ). Таким образом получался бесконечный цикл.
В пользу этого говорит следующее: В ответе от сервера
General
Request URL: http://mysite/auth/register/verify?next=http://mysite/email/verify/4/4PWWX681MW1sdNe8x3oLRJATQGlWaWDx?signature=fa1a41940dffe9ffc5e6be08ff1d5949d6fe8d04efd2e8aef1bc6b5f6cde58a7
Request Method: GET
Status Code: 301 Moved Permanently
Remote Address: 20.52.148.159:80
Referrer Policy: no-referrer
Response Headers
Connection: keep-alive
Content-Length: 169
Content-Type: text/html
Date: Sat, 21 Aug 2021 23:35:00 GMT
Location: http://mysite/auth/register/verify?next=http://mysite/email/verify/4/4PWWX681MW1sdNe8x3oLRJATQGlWaWDx?signature=fa1a41940dffe9ffc5e6be08ff1d5949d6fe8d04efd2e8aef1bc6b5f6cde58a7
Server: nginx/1.21.1
Т.е. перенаправление точно на такую же ссылку. index.php в исходной ссылке нет а значит и совпадений нет которое бы могло привести к редиректу... (пример https://regex101.com/r/TDxLeH/1/)
А если был бы index.php то регулярное выражение в условии* отработало бы корректно... (пример https://regex101.com/r/fK91U4/1)
*Регулярное выражение в условии
# Remove from everywhere index.php
if ($request_uri ~* "^(.*/)index\.php(/?)(.*)") {
return 301 $1$3;
}
и даже если бы в ссылке было два index.php (пример https://regex101.com/r/FzPlC6/1) просто для этого пришлось бы сделать два редиректа.
P.S. знающих прошу написать комментарий если я оказался прав... чтобы наверняка знать в чём была причина
P.S.S. надеюсь это кому-то поможет :)