Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between UseHttpsRedirection and AddDirectToHttpsPermanent in ASP.NET Core

In the Startup.cs file, consider the following:

public void ConfigureServices(IServiceCollection services)
{
    // Irrelevant code removed

    services.AddHttpsRedirection(options =>
    {
        options.RedirectStatusCode = StatusCodes.Status301MovedPermanently;
    });
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // Irrelevant code removed

    app.UseHttpsRedirection();

    app.UseRewriter(new RewriteOptions()
        .AddRedirectToWwwPermanent()
        .AddRedirectToHttpsPermanent()
    );
}

As far as I know, I have to use the Rewriter to set the AddRedirectToWwwPermanent. My question is, should I be using both app.UseHttpsRedirection() and AddRedirectToHttpsPermanent()? Or if they doing the exact same thing, which should I remove?

I just want to make sure I'm redirecting to Https properly, in conjunction with the Wwww redirect.

like image 223
Daniel Congrove Avatar asked Sep 20 '18 19:09

Daniel Congrove


1 Answers

AddRedirectToHttpsPermanent (or its sibling AddRedirectToHttps) adds a RedirectToHttpsRule to the rewriter. This rule works like this:

if (!context.HttpContext.Request.IsHttps)
{
    var host = context.HttpContext.Request.Host;
    if (SSLPort.HasValue && SSLPort.Value > 0)
    {
        // a specific SSL port is specified
        host = new HostString(host.Host, SSLPort.Value);
    }
    else
    {
        // clear the port
        host = new HostString(host.Host);
    }

    var req = context.HttpContext.Request;
    var newUrl = new StringBuilder().Append("https://").Append(host).Append(req.PathBase).Append(req.Path).Append(req.QueryString);
    var response = context.HttpContext.Response;
    response.StatusCode = StatusCode;
    response.Headers[HeaderNames.Location] = newUrl.ToString();
    context.Result = RuleResult.EndResponse;
    context.Logger?.RedirectedToHttps();
}

So this basically gets the current host name, and builds a new URL that looks the same except it has a https:// in front. And then it sets a 301 HTTP status code and returns the new URL through the Location header.

The rule is then executed as part of the RewriteMiddleware which will basically just loop through all registered rules and will eventually run the above code and then end the response.

In contrast, this is how the HttpsRedirectionMiddleware works internally:

if (context.Request.IsHttps || !TryGetHttpsPort(out var port))
{
    return _next(context);
}

var host = context.Request.Host;
if (port != 443)
{
    host = new HostString(host.Host, port);
}
else
{
    host = new HostString(host.Host);
}

var request = context.Request;
var redirectUrl = UriHelper.BuildAbsolute(
    "https",
    host,
    request.PathBase,
    request.Path,
    request.QueryString);

context.Response.StatusCode = _statusCode;
context.Response.Headers[HeaderNames.Location] = redirectUrl;

_logger.RedirectingToHttps(redirectUrl);

return Task.CompletedTask;

So this will get the host name from the incoming request, and then build an absolute URL using the UriHelper that looks exactly like the current request except that it uses the https:// scheme. And then it sets a 307 HTTP status code result and returns the new URL through the Location header. Since it does not call later middlewares, this will also end the response.

So yeah, those two solutions are very different (not): They use pretty much equivalent code and produce the same result. The only actual difference is that the HttpsRedirectionMiddleware uses a HTTP 307 status code by default.

If you prefer one status code over the other, you can totally configure both middlewares to use your preferred status code instead.


So which middleware should you use to enable HTTPS redirection? It doesn’t really matter. The ASP.NET Core templates come with the HttpsRedirectionMiddleware by default, but that middleware also only exists since ASP.NET Core 2.1.

I’d personally stick with the HttpsRedirectionMiddleware since it conveys its purpose very clearly. But if you have a RewriteMiddleware in place anyway, I would just replace the HttpsRedirectionMiddleware by a RedirectToHttpsRule for the rewrite middleware, so you just have a single middleware that performs redirects. – But in the end, it really doesn’t matter.

like image 117
poke Avatar answered Sep 22 '22 20:09

poke