Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirecting HTTPS site to non-www in ASP.NET Core application

I'm setting up my first ASP.NET core application. This application runs on HTTPS. Currently, I have two domains that respond: domain.dk and www.domain.dk, and I want to 301 redirect www to non www.

I've Googled a lot and ended up adding the following class:

public class NonWwwRule : IRule
{
    public void ApplyRule(RewriteContext context)
    {
        var req = context.HttpContext.Request;
        var currentHost = req.Host;
        if (currentHost.Host.StartsWith("www."))
        {
            var newHost = new HostString(currentHost.Host.Substring(4), currentHost.Port ?? 80);
            var newUrl = new StringBuilder().Append("https://").Append(newHost).Append(req.PathBase).Append(req.Path).Append(req.QueryString);
            context.HttpContext.Response.Redirect(newUrl.ToString());
            context.Result = RuleResult.EndResponse;
        }
    }
}

Which I then added to the Configure method in my Startup.cs:

var options = new RewriteOptions();
options.Rules.Add(new NonWwwRule());
app.UseRewriter(options);

However, my site still doesn't respond to this and both www and without works.

EDIT:

I added logging. In my ApplyRule, I spammed some logs in:

    public void ApplyRule(RewriteContext context)
    {
        _logger.LogInformation("ApplyRule added");

        var req = context.HttpContext.Request;
        var currentHost = req.Host;

        _logger.LogInformation("Currenthost: " + currentHost.Host + " & URL: " + req.Path);

        if (currentHost.Host.StartsWith("www."))
        {

            _logger.LogInformation("currentHost.Host.StartsWith");

            var newHost = new HostString(currentHost.Host.Substring(4), currentHost.Port ?? 443);
            var newUrl = new StringBuilder().Append("https://").Append(newHost).Append(req.PathBase).Append(req.Path).Append(req.QueryString);
            _logger.LogInformation("newURL: " + newUrl);
            context.HttpContext.Response.Redirect(newUrl.ToString());
            _logger.LogInformation("response added: " + newUrl.ToString());
            context.Result = RuleResult.EndResponse;
            _logger.LogInformation("EndResponse added");
        }
    }

Reading my logs, I get the impression that it is only called for JS files but not for the main request.

2018-03-05 14:44:33.380 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/Content/styles/styles.css?v=RAlju8RYSVrnTxqDUl4Jj9OkakB2USJn8Hg8TkcZ2AY  
2018-03-05 14:44:33.383 +00:00 [Information] Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware: Sending file. Request path: '/Content/styles/styles.css'. Physical path: 'D:\home\site\wwwroot\wwwroot\Content\styles\styles.css'
2018-03-05 14:44:33.383 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 2.8044ms 200 text/css
2018-03-05 14:44:33.638 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/Content/images/common/logo-dark.png  
2018-03-05 14:44:33.640 +00:00 [Information] Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware: Sending file. Request path: '/Content/images/common/logo-dark.png'. Physical path: 'D:\home\site\wwwroot\wwwroot\Content\images\common\logo-dark.png'
2018-03-05 14:44:33.640 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 2.1224ms 200 image/png
2018-03-05 14:44:33.886 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/js/site.min.js  
2018-03-05 14:44:33.887 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 0.6345ms 302 
2018-03-05 14:44:34.019 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/Content/images/icons/result.svg  
2018-03-05 14:44:34.021 +00:00 [Information] Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware: Sending file. Request path: '/Content/images/icons/result.svg'. Physical path: 'D:\home\site\wwwroot\wwwroot\Content\images\icons\result.svg'
2018-03-05 14:44:34.023 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 4.6392ms 200 image/svg+xml
2018-03-05 14:44:34.175 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/Content/images/icons/customerfocused.svg  
2018-03-05 14:44:34.175 +00:00 [Information] Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware: Sending file. Request path: '/Content/images/icons/customerfocused.svg'. Physical path: 'D:\home\site\wwwroot\wwwroot\Content\images\icons\customerfocused.svg'
2018-03-05 14:44:34.176 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 0.9026ms 200 image/svg+xml
2018-03-05 14:44:34.180 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/Content/images/icons/responsible.svg  
2018-03-05 14:44:34.184 +00:00 [Information] Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware: Sending file. Request path: '/Content/images/icons/responsible.svg'. Physical path: 'D:\home\site\wwwroot\wwwroot\Content\images\icons\responsible.svg'
2018-03-05 14:44:34.185 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 4.8705ms 200 image/svg+xml
2018-03-05 14:44:34.186 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://likvido.dk/js/site.min.js  
2018-03-05 14:44:34.186 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 0.527ms 404 
2018-03-05 14:44:34.265 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/Content/images/icons/professional.svg  
2018-03-05 14:44:34.265 +00:00 [Information] Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware: Sending file. Request path: '/Content/images/icons/professional.svg'. Physical path: 'D:\home\site\wwwroot\wwwroot\Content\images\icons\professional.svg'
2018-03-05 14:44:34.265 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 0.855ms 200 image/svg+xml
2018-03-05 14:44:33.887 +00:00 [Information] Likvido.Website.Main.Startup: ApplyRule added
2018-03-05 14:44:33.887 +00:00 [Information] Likvido.Website.Main.Startup: Currenthost: www.likvido.dk & URL: /js/site.min.js
2018-03-05 14:44:33.887 +00:00 [Information] Likvido.Website.Main.Startup: currentHost.Host.StartsWith
2018-03-05 14:44:33.887 +00:00 [Information] Likvido.Website.Main.Startup: newURL: https://likvido.dk:443/js/site.min.js
2018-03-05 14:44:33.887 +00:00 [Information] Likvido.Website.Main.Startup: response added: https://likvido.dk:443/js/site.min.js
2018-03-05 14:44:33.887 +00:00 [Information] Likvido.Website.Main.Startup: EndResponse added
2018-03-05 14:44:34.186 +00:00 [Information] Likvido.Website.Main.Startup: ApplyRule added
2018-03-05 14:44:34.186 +00:00 [Information] Likvido.Website.Main.Startup: Currenthost: likvido.dk & URL: /js/site.min.js
2018-03-05 14:44:34.611 +00:00 [Information] Likvido.Website.Main.Startup: ApplyRule added
2018-03-05 14:44:34.611 +00:00 [Information] Likvido.Website.Main.Startup: Currenthost: www.likvido.dk & URL: /js/site.min.js
2018-03-05 14:44:34.611 +00:00 [Information] Likvido.Website.Main.Startup: currentHost.Host.StartsWith
2018-03-05 14:44:34.611 +00:00 [Information] Likvido.Website.Main.Startup: newURL: https://likvido.dk:443/js/site.min.js
2018-03-05 14:44:34.611 +00:00 [Information] Likvido.Website.Main.Startup: response added: https://likvido.dk:443/js/site.min.js
2018-03-05 14:44:34.611 +00:00 [Information] Likvido.Website.Main.Startup: EndResponse added
2018-03-05 14:44:34.714 +00:00 [Information] Likvido.Website.Main.Startup: ApplyRule added
2018-03-05 14:44:34.714 +00:00 [Information] Likvido.Website.Main.Startup: Currenthost: likvido.dk & URL: /js/site.min.js
2018-03-05 14:44:34.478 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/  
2018-03-05 14:44:34.478 +00:00 [Information] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker: Executing action method Likvido.Website.Main.Controllers.HomeController.Index (Likvido.Website.Main) with arguments ((null)) - ModelState is Valid
2018-03-05 14:44:34.478 +00:00 [Information] Likvido.Website.Main.Controllers.HomeController: TEST INDEX LOGGER
2018-03-05 14:44:34.479 +00:00 [Information] Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor: Executing ViewResult, running view at path /Views/Home/Index.cshtml.
2018-03-05 14:44:34.479 +00:00 [Information] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker: Executed action Likvido.Website.Main.Controllers.HomeController.Index (Likvido.Website.Main) in 0.9628ms
2018-03-05 14:44:34.481 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 2.4825ms 200 text/html; charset=utf-8
2018-03-05 14:44:34.484 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/Content/images/pages/bg-image-2.jpg  
2018-03-05 14:44:34.485 +00:00 [Information] Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware: Sending file. Request path: '/Content/images/pages/bg-image-2.jpg'. Physical path: 'D:\home\site\wwwroot\wwwroot\Content\images\pages\bg-image-2.jpg'
2018-03-05 14:44:34.486 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/Content/images/icons/phone-icon-3.svg  
2018-03-05 14:44:34.487 +00:00 [Information] Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware: Sending file. Request path: '/Content/images/icons/phone-icon-3.svg'. Physical path: 'D:\home\site\wwwroot\wwwroot\Content\images\icons\phone-icon-3.svg'
2018-03-05 14:44:34.487 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 0.9784ms 200 image/svg+xml
2018-03-05 14:44:34.500 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 16.1968ms 200 image/jpeg
2018-03-05 14:44:34.610 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://www.likvido.dk/js/site.min.js  
2018-03-05 14:44:34.611 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 1.3489ms 302 
2018-03-05 14:44:34.713 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://likvido.dk/js/site.min.js  
2018-03-05 14:44:34.714 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 0.573ms 404 
like image 986
Lars Holdgaard Avatar asked Feb 28 '18 07:02

Lars Holdgaard


2 Answers

From the logs, it looks like you have the middleware the wrong way round

It should be

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            var options = new RewriteOptions();
            options.Rules.Add(new NonWwwRule());
            app.UseRewriter(options);
            app.UseStaticFiles();

            app.UseMvc();
        }

It should be rewriter first, then static, then MVC

like image 133
Umar Karimabadi Avatar answered Oct 14 '22 12:10

Umar Karimabadi


And for all of you who ware crazy enough to do that in F#:

open Microsoft.AspNetCore.Http

type NonWwwRule () =
    interface IRule with
        member __.ApplyRule context =
            let request = context.HttpContext.Request
            let host = request.Host

            if host.Host.StartsWith("www.", StringComparison.OrdinalIgnoreCase) then
                let nonWwwPort = if host.Port.HasValue then host.Port.Value else 443
                let nonWwwHost = HostString(host.Host.Substring 4, nonWwwPort)
                let nonWwwPath = 
                    (sprintf "https://%s%s%s%s" 
                        nonWwwHost.Value
                        request.PathBase.Value 
                        request.Path.Value 
                        request.QueryString.Value)

                context.HttpContext.Response.Redirect nonWwwPath
                context.HttpContext.Response.StatusCode <- 301

                context.Result <- RuleResult.EndResponse
let options = RewriteOptions()
options.Rules.Add(NonWwwRule())
app.UseRewriter options |> ignore
like image 41
asp_net Avatar answered Oct 14 '22 12:10

asp_net