aspnet / BasicMiddleware

[Archived] Basic middleware components for ASP.NET Core. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
169 stars 84 forks source link

No ability to enforce Lower Case URLS with Rewrite #252

Closed OWAProjects closed 5 years ago

OWAProjects commented 7 years ago

Hi there, Since the removal of rewrite rules from the web.config file due to the wwwroot change in RC2 I'm struggling to find any way of enforcing Lower Case URL redirect. Is there any solution to this?

I believe it's quite an important SEO feature to ensure all site urls maintain lowercase structure instead of serving the same page from both lowercase and uppercase.

Previous web.config rule:

<rule name="LowerCaseRule1" enabled="true" stopProcessing="true">
    <match url="[A-Z]" ignoreCase="false" />
    <action type="Redirect" url="{ToLower:{URL}}" />
</rule>
jkotalik commented 7 years ago

Sorry for not responding to this quicker. We implemented a parser of IISUrlRewrite rules for this scenario. There is a few things you need to do to get this working.

  1. Copy the rule into a separate file, calling whatever you want.
  2. Change the ToLower:{URL} to ToLower{R:0} (we currently do not support the URL keyword in IIS rules)
  3. Add two outer xml sections around the rule (like it normally is in web.config)
  4. Call in your Configure method:
    var options = new RewriteOptions().AddIISUrlRewrite(new StreamReader("test.txt"));
    app.UseRewriter(options);

    Let me know if that works for you. Our IISUrlRewrite parser is a subset of what is supported in IIS.

OWAProjects commented 7 years ago

Thanks for the help, I've managed to get this working with the following:

var rewriteOptions = new RewriteOptions()
    .AddRedirect("(.*[^/])$", "$1/")
     .AddIISUrlRewrite(env.ContentRootFileProvider, "Lowercase.xml");
<rewrite>
  <rules>
    <rule name="LowerCaseRule1" enabled="true" stopProcessing="true">
        <match url="[A-Z]" ignoreCase="false" />
        <action type="Redirect" url="{ToLower:{R:0}}" />
    </rule>
  </rules>
</rewrite>
OWAProjects commented 7 years ago

Scratch that, the rule works for simple scenarios however completely fails on more complicated URLS.

For instance Account/Login will redirect to account/login/ - Great However a complicated URL such as

3328134-Red-Soil-Metal-And-Iron-Works redirects through a Path as follows:

/r /r/

Which because unfound goes to /Home/Errors/404/ /h /h/

and then stuck in a redirect loop because /h/ doesn't exist and the URL redirect cannot find /home/errors/404/ which is a valid URL path and works if you go directly to it.

Is this something wrong with the rule or the rewrite options? This rule was working fine in IIS for complicated url structures. The rewrite pattern should be able to handle this type of URL easily and not fail and attempt to go to the first letter of the URL. Any thoughts @jkotalik ? Thanks.

EDIT:

I've completely removed the rewrite package and this kind of behaviour is still happening? Any URL with a trailingslash is being redirected to the first letter of it's URL path: /BespokeService - works /BespokeService/ - goes to /b

I don't understand why this is now happening since It's been working fine beforehand, possibly an issue with a .NetCore update?

jkotalik commented 7 years ago

Very odd. Just to confirm, when you say completely removed the rewrite package, you removed all uses of .UseRewriter(options)? Also, when you tried to access, for example, /BespokeService/, you hard refreshed the page (ctrl+shift+r), are in private browsing, or have disabled caching? I want to isolate the problem to either the rewrite package or outside of it.

OWAProjects commented 7 years ago

I believe you were correct about the caching, I had removed the UseRewriter line and removed the nuget package and the issue was still happening but whilst trying it within incognito the standard routing worked correct.

Having said that, after ensuring the cache is cleared and re-enabling the rewriting the trailing slash rule works fine however the Lowercase rule is still causing issues with incorrect redirects. In terms of the /BespokeService/ URL i think this could be because i'm using just the action and ignoring the controller, could this catch the rule out?

I'm unsure of the reason why "3328134-Red-Soil-Metal-And-Iron-Works" fails to redirect as this follows the correct /controller/action/ID routing so this might be due to it's complexity?

Much appreciate your time on this.

jkotalik commented 7 years ago

Gah I'm sorry. I now understand what the first rule was doing now. The reason it is failing is the regex is checking just for characters between A-Z, and captures just that character if it matches. R:0 returns the matched pattern from the Regex, which will just happen to be the first capital letter, in this case R. Fortunately we can fix this by just capturing everything around the matched capital letter. Change the url to be ".[A-Z]." and that (hopefully) should work.

Thanks for the patience! Rewrite rules are hard to get right.

aspnet-hello commented 5 years ago

We periodically close 'discussion' issues that have not been updated in a long period of time.

We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate.