Htaccess проблема с бесконечным циклом

У меня возникла проблема с файлом .htaccess.

Файл изменяет уродливый URL-адрес, такой как http://localhost/news.php?article_slug=example-1, на http://localhost/news/example-1

Это работает отлично, но когда я перехожу к http://localhost/news, я получаю ошибку 404.

Внутри news.php у меня есть перенаправление; поэтому, если в URL-адресе нет слага статьи, он будет перенаправлен на last.php.

мой PHP-код на news.php

$article_slug=$_GET['article_slug'];
if (empty($_GET)) {
header("Location: ../latest.php");
die();// no data passed by get
}

Это то, что у меня сейчас есть в моем файле .htaccsess

Options -MultiViews
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteRule ^news/([\w\d-]+)$ /news.php?article_slug=$1[QSA,L]
RewriteCond %{QUERY_STRING} article_slug=([\w\d-]+)
RewriteRule ^news$ /news/%1 [R,L]

RewriteRule ^category/([\w-]+)$ /category.php?category_slug=$1&page=$2 [QSA]

Когда я пытаюсь отладить это самостоятельно (с очень небольшими знаниями) и добавляю следующую строку, она перенаправляется на last.php

RewriteRule ^([^/]*)/?$ /news.php [L,QSA]

но на перенаправленной странице я получаю следующую ошибку

The page isn’t redirecting properly

Firefox has detected that the server is redirecting the request for this 
address in a way that will never complete.

This problem can sometimes be caused by disabling or refusing to accept cookies

Когда я использую инструменты разработчика в firefox, как прокомментировал IMSoP, все, что я вижу, это несколько раз перезагружается последний.php.

Это не просто изолировано только от last.php, но и от любого файла на сервере, который не указан в файле доступа.

когда я удаляю строку

RewriteRule ^([^/]*)/?$ /news.php [L,QSA]

Я могу загрузить файл PHP, но он не перенаправляется с news.php и http://localhost/news не найден, но http://localhost/news/example-1 работает.

Здесь вы упустили важную часть информации: в PHP, если нет slug, куда он перенаправляется? Вы также можете увидеть фактическую последовательность перенаправлений, которым пытался следовать Firefox, на вкладке «Сеть» инструментов разработчика (нажмите F12), так что вы также можете добавить ее сводку. (Нажмите редактировать, не пытайтесь втиснуть это в комментарий.)

IMSoP 11.02.2023 10:51

при использовании инструментов разработчика кажется, что одна и та же страница перезагружается несколько раз

Nashie 11.02.2023 10:58

Какая же страница? Вы должны помнить, что мы не можем видеть через ваше плечо, вы должны быть конкретными каждый раз.

IMSoP 11.02.2023 11:12
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
3
74
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

но когда я захожу в http://localhost/news я получаю ошибку 404.

Ни одно из ваших правил не ловит такой запрос, поэтому перезаписи не происходит, и вы получаете 404.

RewriteRule ^([^/]*)/?$ /news.php [L,QSA]

Это перезаписывает все в /news.php, включая /latest.php, на которое вы перенаправляете в своем PHP-скрипте, и цикл повторяется, что приводит к циклу перенаправления на /latest.php.

Однако это перенаправление в вашем PHP-коде также предполагает наличие косой черты в исходном запросе. т.е. должно быть /news/ (с косой чертой в конце), а не /news (без косой черты), как вы указываете в вопросе.

Было бы лучше перенаправить на корневой (или абсолютный) URL-адрес в вашем PHP-скрипте. т.е. header('Location: /latest.php');

RewriteRule ^news/([\w\d-]+)$ /news.php?article_slug=$1[QSA,L]
RewriteCond %{QUERY_STRING} article_slug=([\w\d-]+)
RewriteRule ^news$ /news/%1 [R,L]

(Обратите внимание, что вам не хватает пробела перед аргументом «флаги» в первом правиле.)

Первое правило можно изменить, чтобы разрешить news/, а не только news/<something>. Это достигается простым изменением квантификатора с + (1 или более) на * (0 или более) в подшаблоне захвата.

Второе правило в настоящее время ничего не делает. Вероятно, вам следует ориентироваться на news.php здесь. Но правила тоже в неправильном порядке.

Как отмечено в моем ответе на ваш предыдущий вопрос, класс сокращенных символов \d не нужен, поскольку \w (словные символы) уже включает цифры.

Вместо этого попробуйте следующее:

RewriteCond %{QUERY_STRING} (?:^|&)article_slug=([\w-]*)(?:$|&)
RewriteRule ^news\.php$ /news/%1 [R=301,L]

RewriteRule ^news/([\w-]*)$ /news.php?article_slug=$1 [QSA,L]

Обратите внимание, первым правилом должен быть редирект 301 (постоянный), а не 302 (как было изначально). Но всегда сначала тестируйте с 302, чтобы избежать потенциальных проблем с кэшированием.

Это позволяет запрашивать /news/, но не /news (без косой черты в конце). Только один из них может быть каноническим. Если вам нужно также обработать /news, вы должны перенаправить, чтобы добавить косую черту в конце (так что /news/ является каноническим, и URL-адрес, на который вы всегда должны ссылаться). Например, перед двумя приведенными выше правилами:

# Append trailing slash if omitted (canonical redirect)
RewriteRule ^news$ /$0/ [R=301,L]

Резюме

Объединяя вышеперечисленные пункты:

Options -MultiViews

RewriteEngine On

RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]

# Append trailing slash if omitted (canonical redirect)
RewriteRule ^news$ /$0/ [R=301,L]

RewriteCond %{QUERY_STRING} (?:^|&)article_slug=([\w-]*)(?:$|&)
RewriteRule ^news\.php$ /news/%1 [R=301,L]

RewriteRule ^news/([\w-]*)$ /news.php?article_slug=$1 [QSA,L]

RewriteRule ^category/([\w-]+)$ /category.php?category_slug=$1 [QSA,L]

Однако то же самое теперь относится и к вашему URL-адресу /category. Это также обсуждалось в вашем предыдущем вопросе. (Я удалил лишнюю часть &page=$2 и добавил отсутствующий флаг L.)

Если у вас есть много таких URL-адресов, которые следуют похожему шаблону (например, news и category и т. д.), вам не обязательно нужно отдельное правило для каждого. (Упражнение для читателя.)


ОБНОВЛЯТЬ:

$article_slug=$_GET['article_slug'];
if (empty($_GET)) {
header("Location: ../latest.php");
die();// no data passed by get
}

Как обсуждалось в комментариях, это должно читаться так:

$article_slug = $_GET['article_slug'] ?? null;
if (empty($article_slug)) {
    header("Location: /latest.php");
    die(); // no data passed by get
}

Спасибо за вашу помощь еще раз. Я решил уйти и попытаться узнать больше о редактировании файлов .htaccess, поскольку раньше мне никогда не приходилось с ними работать. /news/ показывается, но перенаправление игнорируется, почему это?

Nashie 11.02.2023 12:02

@Nashie Вы говорите, что перенаправление с /news на /news/ игнорируется?

MrWhite 11.02.2023 12:07

Нет, это отлично работает, спасибо, перенаправление с /news/ на last.php, если в URL-адресе нет слага статьи. в php-файле news.php

Nashie 11.02.2023 12:09

поверх news.php у меня есть этот код $article_slug=$_GET['article_slug']; if (пусто($_GET)) { заголовок('Расположение: /latest.php'); умереть(); }

Nashie 11.02.2023 12:13

@Nashie Ах, if (empty($_GET)) должно быть if (empty($article_slug)) - $_GET не пусто, когда есть пустой параметр URL. Вам также необходимо включить некоторую проверку при чтении $_GET['article_slug'], так как этого может не быть (и ваш код выдаст E_NOTICE).

MrWhite 11.02.2023 12:17

Мистер Уайт, вы бриллиант. спасибо, что сделал работу. еще раз спасибо.

Nashie 11.02.2023 12:20

Правила перезаписи по своей сути очень просты: они сопоставляют запрошенный URL с шаблоном, а затем определяют, что делать, если он совпадает.

RewriteRule ^([^/]*)/?$ /news.php [L,QSA]

Шаблон здесь переводится как «должен совпадать с самого начала; все, кроме косой черты, ноль или более раз; необязательная косая черта; должно совпадать до конца». Действие, если оно совпадает, состоит в том, чтобы действовать так, как если бы запрос был для «/news.php», добавляя любые параметры строки запроса.

Это очень широкая модель; он будет соответствовать "news" и "news/", но также будет соответствовать "hello-world" и "__foo--bar..baz/". Единственное, что может помешать этому совпадению, — это другие правила выше вашего конфигурационного файла.

Между тем, каждый раз, когда это правило соответствует, ваш PHP-код в news.php будет выполняться, и если в строке запроса ничего нет, браузеру будет предложено запросить «latest.php».

Но правило также будет соответствовать «latest.php». Итак, когда браузер запрашивает «latest.php», код в «news.php» запускается и сообщает браузеру снова запросить «latest.php»… и мы получаем бесконечный цикл.

Самое простое исправление - просто сделать ваше правило более конкретным, например. ищите конкретно слово "новость":

RewriteRule ^news/?$ /news.php [L,QSA]

Другой распространенный метод — добавить к правилу условие, что оно соответствует только в том случае, если URL-адрес не соответствует реальному имени файла, например:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*)/?$ /news.php [L,QSA]

Другие вопросы по теме