Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UrlRule Problem with trailing slash (/) #7670

Closed
Bhoft opened this issue Mar 11, 2015 · 23 comments

Comments

Projects
None yet
@Bhoft
Copy link
Contributor

commented Mar 11, 2015

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

@samdark

This comment has been minimized.

Copy link
Member

commented Mar 11, 2015

Yes, there's difference and it's intentional.

@samdark

This comment has been minimized.

Copy link
Member

commented Mar 11, 2015

@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?

@qiangxue qiangxue added this to the 2.1.x milestone Mar 11, 2015

@Bhoft

This comment has been minimized.

Copy link
Contributor Author

commented Mar 18, 2015

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.

@klimov-paul

This comment has been minimized.

Copy link
Member

commented Mar 18, 2015

@nkovacs

This comment has been minimized.

Copy link
Contributor

commented May 12, 2015

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

@samdark

This comment has been minimized.

Copy link
Member

commented Jun 15, 2015

It seems to a bigger problem than I've thought. Wordpress is adding / at the end of all links posted.

@samdark samdark modified the milestones: 2.0.5, 2.1.x Jun 15, 2015

@samdark

This comment has been minimized.

Copy link
Member

commented Jun 15, 2015

While it could be solved serverside, it's better to do in Yii itself else there will be lots and lots of unexpected 404s.

@samdark

This comment has been minimized.

Copy link
Member

commented Jul 8, 2015

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);
        }
    },
];
@mrsombre

This comment has been minimized.

Copy link

commented Jul 23, 2015

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.

@samdark

This comment has been minimized.

Copy link
Member

commented Jul 23, 2015

301 is better.

@mrsombre

This comment has been minimized.

Copy link

commented Jul 24, 2015

@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)?

@samdark

This comment has been minimized.

Copy link
Member

commented Jul 24, 2015

  • There's no problem with serving 301 instead of 404.
  • To choose with or without / one could configure UrlManager even now.
  • "Don't care" would not make sense if there will be 301 i.e. people would be redirected no matter which URL is used.
@pabloneruda1

This comment has been minimized.

Copy link

commented Sep 21, 2015

This redirect rule works for me in htaccess:

RewriteCond %{THE_REQUEST} \s/+(.+?)/+[?\s]
RewriteRule /$ /%1 [R,L]
@gerpayt

This comment has been minimized.

Copy link

commented Sep 23, 2015

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;
    }
}

@samdark samdark self-assigned this Sep 23, 2015

@pabloneruda1

This comment has been minimized.

Copy link

commented Sep 23, 2015

right, thanks gerpayt

@sganz

This comment has been minimized.

Copy link

commented Oct 27, 2015

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

@SilverFire

This comment has been minimized.

Copy link
Member

commented Jan 9, 2016

@sauron918 please create a separated issue for your problem

dynasource added a commit to dynasource/yii2 that referenced this issue Feb 2, 2016

fix yiisoft#7670 by:
- resolve Url like in the original code
- if request can not be resolved, try again with suffix (if any)
- if request is then resolved, then redirect to the corresponding url

To be able to do this repetition, a new function is created called 'resolveRequest'.
This function looks like the old 'resolve' function.
The old revolve function is use to act as a controller, including a redirect
@schojniak

This comment has been minimized.

Copy link
Contributor

commented Feb 8, 2016

@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;
    }
}
@cronfy

This comment has been minimized.

Copy link
Contributor

commented Apr 18, 2016

@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.

@samdark samdark modified the milestones: 2.0.9, 2.0.10 Jul 6, 2016

@rob006 rob006 referenced this issue Aug 21, 2016

Merged

Add UrlNormalizer for UrlRule and UrlManager #12240

3 of 3 tasks complete
@jnanendraveer

This comment has been minimized.

Copy link

commented Aug 30, 2016

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

@samdark

This comment has been minimized.

Copy link
Member

commented Aug 30, 2016

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.

samdark added a commit that referenced this issue Aug 30, 2016

@agungsijawir

This comment has been minimized.

Copy link

commented Sep 2, 2016

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',
    ],
];
@rishad2m8

This comment has been minimized.

Copy link

commented Mar 12, 2019

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.