Hi i have added a UrlManager rules like given below added to my config
'<project:[-a-zA-Z]+>/<controller:\w+>' => '<controller>',
'<project:[-a-zA-Z]+>/<controller:\w+>/<action:\w+>' => '<controller>/<action>',
If i then call a url like
/projectname/controllername/action (works)
/projectname/controllername (works pointing to the default action in the controller)
/projectname/controllername/ (with trailing slash doens't work)
But the Url with a trailing slash produces a 404 error on the SiteController.
This is because the UrlRule doesn't match.
if i change the UrlRule to the code below (\w* instead of \w+) the default controller action is called.
'<project:[-a-zA-Z]+>/<controller:\w+>/<action:\w*>' => '<controller>/<action>',
I also tested the UrlRules in yii1 but there the UrlRules from the top are also working with a trailing / in the Url but not in yii2.
So I guess there is some kind of "bug".
I Don't Know if the trailing slashes are removed in the Request in yii1 but not in yii2.
But there is clearly some difference between the 2 frameworks.
Regards Horizons
Yes, there's difference and it's intentional.
@yiisoft/core-developers it's not the first time people are asking about it. Maybe we should redirect to proper URL instead of not allowing to use incorrect one altogether?
is it somehow possible that something is added to the pattern so that a optional trailing / is in the pattern.
In my project case where the url was only /projectname or /projectname/ it would be something like
$this->pattern ='#^(?P<project>[-a-zA-Z]+)(?:[/])?$#u';
instead of
$this->pattern ='#^(?P<project>[-a-zA-Z]+)$#u';
so this was added (?:[/])?
So that both url's would work.
Maybe this trailing slash pattern is added to the pattern in the UrlRule init when some placeholder is in the pattern or some variable is set.
The documentation is wrong. It says "the leading and ending slashes are ignored": http://www.yiiframework.com/doc-2.0/guide-runtime-routing.html#url-rules
It seems to a bigger problem than I've thought. Wordpress is adding /
at the end of all links posted.
While it could be solved serverside, it's better to do in Yii itself else there will be lots and lots of unexpected 404s.
Could be done app-side like the following:
$config = [
// ...
'params' => require(__DIR__ . '/params.php'),
// redirect to the page with the trailing slash
'on beforeRequest' => function () {
$app = Yii::$app;
$pathInfo = $app->request->pathInfo;
if (!empty($pathInfo) && substr($pathInfo, -1) !== '/') {
$app->response->redirect('/' . rtrim($pathInfo) . '/', 301);
}
},
];
This leads to problems with search engines, as URI with and without ending slash may be different documents. All site should use only one style and return 301 or 404 for wrong ones.
301 is better.
@samdark then it should be an option to choose between with/without ending slash. And option to allow both for people who don't care about seo. And maybe 404 as default option (for BC)?
/
one could configure UrlManager even now.This redirect rule works for me in htaccess:
RewriteCond %{THE_REQUEST} \s/+(.+?)/+[?\s]
RewriteRule /$ /%1 [R,L]
Add a route at last line '<url:.+>/' => 'site/redirect',
and add a action
public function actionRedirect($url = '')
{
if (substr($url, -1) == '/') {
return $this->redirect('/' . substr($url, 0, -1));
} else {
throw new NotFoundHttpException;
}
}
right, thanks gerpayt
Not sure where all the slash/no slash ended up but ran into something as well when porting some Yii1 code over to Yii2.
Docs have it stated incorrectly if the a requests getPathInfo() is used.
In the docs it states -
A path info refers to the part that is after the entry script and before the question mark (query string). The starting and ending slashes are both removed.
When doing something like $request->getPathInfo(); it returns the trailing slash. This is not so much about handling the route, but different results expected for getPathInfo().
No big deal either way, just want the docs to match what it really is supposed to be, solved by rtrim() the slash prior to using the getPathInfo() value in my code, again not a huge one, just letting folks know the docs may not match functionality.
Thanks
Sandy
@sauron918 please create a separated issue for your problem
@gerpayt:
slash should be inside regular expression:
'<url:.+/>' => 'site/redirect'
some improvements: 301 redirect, baseUrl, one redirect in case of many slashes
public function actionRedirect($url)
{
if (substr($url, -1) == '/') {
return $this->redirect(Yii::$app->getRequest()->getBaseUrl() . '/' . rtrim($url, '/'), 301);
} else {
throw new NotFoundHttpException;
}
}
@samdark could you please take a look at my pull request? I hope it will help to solve the issue. I use this approach on sites I develop.
Still waiting for write answer. Why I will use 301 redirect for trailing slash?. As you guys know in yii1 better for url manager. Some guys has post like that
/projectname => projectcontroller/index
/projectname/ => projectcontroller/index
/projectname/action => projectcontroller/action
/projectname/projectspecifc_controller => projectspecifc_controller/index
/projectname/projectspecifc_controller/ => projectspecifc_controller/index
/projectname/projectspecifc_controller/action => projectspecifc_controller/action
It's not perfect answer. I have configure like that
'baseUrl' => '/',
'enablePrettyUrl' => true,
'showScriptName' => false,
'suffix' => '/',
'enableStrictParsing' => true,
My code working fine.
Thanks
Because search engines think a/
and a
are different URLs and since these contain the same content, your website is getting penalized for duplicated content. 301 solves the issue.
Another .htaccess rewrite rule before checking directory.
# see http://stackoverflow.com/a/11880879/2485734
RewriteCond %{REQUEST_URI} !(/$|\.)
RewriteRule (.*) %{REQUEST_URI}/ [R=301,L]
and the config for UrlManager
, enabling suffix
return [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
'showScriptName' => false,
'suffix' => '/',
'rules' => [
'/' => 'site/index',
'product/<slug>' => 'product/view',
'product-category/<name>' => 'product-category/index',
'search/<keyword>' => 'search/result',
],
];
I've experienced similar issue with IIS. So if anyone still experiencing trailing slash issue,
Please use following URL rewrite Rule in web.config
<rule name="SEO - Remove trailing slash" stopProcessing="false">
<match url="(.*)/$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Redirect" url="{R:1}" />
</rule>
Most helpful comment
@samdark could you please take a look at my pull request? I hope it will help to solve the issue. I use this approach on sites I develop.