Заголовок тупо кликбейтный, сразу говорю — такие реврайты не задача для веб сервера. Почему — потому что кейсов здесь — овер до хрена. И все их предусматривать и засерать конфиги хреново читаемыми реврайт правилами… (которые потом ещё вылезут в самом неожиданном месте в виде 500 ошибки). Ну например варианты запросов:
- //// => /
- /path/// => /path
- ///path/ => /path
- /path////path => /path/path
- ////path/////path///// => /path/path
- и т.д.
а зачем это всё «причёсывать» реврайтами? На фига козе баян? Есть php — гибкий язык в отличии от директив Nginx/Apache2, позволяющий это же реализовать 1 раз без ошибок и забыть. Вот так:
$request = strtok($_SERVER['REQUEST_URI'], '?');
if (preg_match('#//#', $request)) { // убираем 2 и более слешей в url
$uri = preg_replace('#[/]+$#', '', $request);
$uri = preg_replace('#[/]{2,}#', '/', $uri);
$uri = $uri ?: '/';
if ($QUERY_STRING = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY)) {
$uri .= '?' . $QUERY_STRING;
}
header("HTTP/1.1 301 Moved Permanently");
header("Location: $uri");
exit;
}
if ($request != '/' && preg_match('#/$#', $request)) { // убираем крайний слеш если это не главная
$uri = preg_replace('#[/]+$#', '', $request);
$uri = $uri ?: '/';
if ($QUERY_STRING = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY)) {
$uri .= '?' . $QUERY_STRING;
}
header("HTTP/1.1 301 Moved Permanently");
header("Location: $uri");
exit;
}
if (preg_match('#index\.(php|html)$#', $request)) {
header("HTTP/1.1 301 Moved Permanently");
header("Location: " . dirname($request));
exit;
}