Баг в роутере с разбором параметров для экшена (LiveStreet 1.0.3)

Разработка под LiveStreet CMS
Если в строке запроса были get-параметры ("?"), то роутер в параметры экшена может добавить последним параметром пустую строку. Слово «может» написано не случайно т.к. все зависит от урла:

// здесь будет получен пустой параметр
test.com/some1/page2/?some_param=value

// а здесь его не будет
test.com/some1/page2?some_param=value


Примечание: на самом деле роутер не «добавит пустую строку», а не сможет убрать последний слеш в урле (до символа "?"), а потом разделит строку по слешам и из-за этого будет существовать пустой параметр.

Диагностирование ошибки

Для теста используются две ссылки:

http://test.com/some1/page2/
http://test.com/some1/page2/?filter[sort]=date

Что делает метод GetRequestUri из роутера? Для начала его код:

/**
 * Метод выполняет первичную обработку $_SERVER['REQUEST_URI']
 *
 * @return string
 */
protected function GetRequestUri()
{
    $sReq = preg_replace("/\/+/", '/', $_SERVER['REQUEST_URI']);
    $sReq = preg_replace("/^\/(.*)\/?$/U", '\\1', $sReq);
    $sReq = preg_replace("/^(.*)\?.*$/U", '\\1', $sReq);
    /**
     * Формируем $sPathWebCurrent ДО применения реврайтов
     */
    self::$sPathWebCurrent = self::GetPathRootWeb() . "/" . join('/', $this->GetRequestArray($sReq));
    return $sReq;
}

Он откидывает все, что после "?" и разбирает на части реквест URI для того, чтобы сформировать на основе этих данных экшен и эвент для последующего запуска.

Для указанных из примера выше двух ссылок будут разные результаты, а именно — будет пустой (!) один параметр.

Данная ошибка актуальна для версии LiveStreet 1.0.3.

Подробно что же делает метод GetRequestUri роутера
  1. Заменяет несколько обратных слешей ("/") подряд на один
    https://github.com/livestreet/livestreet-framework/blob/master/classes/engine/Router.class.php#L230

    $sReq = preg_replace("/\/+/", '/', $_SERVER['REQUEST_URI']);

  2. Убирает слеши по краям т.е. "/some1/page2/" станет «some1/page2»
    https://github.com/livestreet/livestreet-framework/blob/master/classes/engine/Router.class.php#L231

    $sReq = preg_replace("/^\/(.*)\/?$/U", '\\1', $sReq);

  3. Откидывает все после знака "?" включительно
    https://github.com/livestreet/livestreet-framework/blob/master/classes/engine/Router.class.php#L232

    $sReq = preg_replace("/^(.*)\?.*$/U", '\\1', $sReq);


Для первой ссылки из примера:
http://test.com/some1/page2/

роутер сделает все нормально, т.к. нет query-строки. Для второй ссылки:
http://test.com/some1/page2/?filter[sort]=date

вторая регулярка (из метода GetRequestUri) будет не актуальна, а третья, убирая "?" и всю его команду, оставляет последний слеш "/", который должен был быть убран второй регуляркой (за задумкой).

Дев версия лс

В разрабатываемой на момент написания статьи версии лс данный баг исправлен:
https://github.com/livestreet/livestreet-framework/blob/master/classes/engine/Router.class.php#L248

$aRequestUrl = ($sReq == '') ? array() : explode('/', trim($sReq, '/'));

В конце строки добавлено удаление слеша (trim). Мне это решение не нравится т.к. тогда нет смысла в этой регулярке:
https://github.com/livestreet/livestreet-framework/blob/master/classes/engine/Router.class.php#L231

$sReq = preg_replace("/^\/(.*)\/?$/U", '\\1', $sReq);

в связи с тем, что она заменяется этим trim'ом. Лучше вообще тот трим вынести после строки:
https://github.com/livestreet/livestreet-framework/blob/master/classes/engine/Router.class.php#L232

$sReq = preg_replace("/^(.*)\?.*$/U", '\\1', $sReq);

и убрать из
https://github.com/livestreet/livestreet-framework/blob/master/classes/engine/Router.class.php#L248

$aRequestUrl = ($sReq == '') ? array() : explode('/', trim($sReq, '/'));

потому что в дев версии этот трим по своей сути является хаком.

Решение через trim в dev-версии использовано наверное было потому что было не понятно происзождение этой ошибки и почему иногда есть слеш, а иногда — нет.

UPD: топик обновлен и более подробно расписан.
0 комментариев
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.