Skip to content

Instantly share code, notes, and snippets.

@mattwhetton
Last active November 24, 2020 23:22
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattwhetton/72d1cd532115e103600b6b6cfd5c50dc to your computer and use it in GitHub Desktop.
Save mattwhetton/72d1cd532115e103600b6b6cfd5c50dc to your computer and use it in GitHub Desktop.
Simple OWIN middleware for doing an HTTPs redirect for all requests
// Ref: http://www.codenutz.com/https-redirect-asp-net-core-using-owin-middleware/
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Builder;
namespace SomeNamespace
{
public class HttpsRedirectMiddleware {
private RequestDelegate _next;
public HttpsRedirectMiddleware(RequestDelegate next) {
_next = next;
}
public async Task Invoke(HttpContext context){
var protoHeader = context.Request.Headers["X-Forwarded-Proto"].ToString();
if(context.Request.IsHttps || protoHeader.ToLower().Equals("https"))
await _next.Invoke(context);
}
else
{
context.Response.Redirect($"https://{context.Request.Host}{context.Request.Path}");
}
}
}
public static class HttpsRedirectMiddlewareExtensions
{
public static IApplicationBuilder UseHttpsRedirect(this IApplicationBuilder builder)
{
return builder.UseMiddleware<HttpsRedirectMiddleware>();
}
}
}
@Lutando
Copy link

Lutando commented Aug 19, 2016

line 19 you're missing open parentheses at the end :)

@jtheisen
Copy link

This isn't OWIN, it's ASP.NET Core.

@BojoDimov
Copy link

With a little change works like a charm. Thank you!

@atom1cx
Copy link

atom1cx commented Oct 12, 2018

The code for OWIN is look like this:

    public async override Task Invoke(IOwinContext context)
    {
        var protoHeader = context.Request.Headers["X-Forwarded-Proto"]?.ToString();
        if (context.Request.IsSecure || (protoHeader != null && protoHeader.ToLower().Equals("https")))
        {
            await Next.Invoke(context);
        }
        else
        {
            context.Response.StatusCode = 302;
            context.Response.Redirect($"https://{context.Request.Host}{context.Request.Path}{context.Request.QueryString}");
        }
    }

@Steinblock
Copy link

@atom1cx

            context.Response.Redirect($"https://{context.Request.Host}{context.Request.Path}{context.Request.QueryString}");

did not work for me beause I use non standard http/https (10080/10043) ports and my webapp listens on a different base path "/app"

  • context.Request.Host already includes the port (localhost:10080)
  • context.Request.Path did not include the basepath (only /path) for http://localhost:10080/app/path

so the best thing is to se context.Request.Uri for redirection.

  • StatusCode 302 is deprecated (has been replaced by 303 but still works in most browsers) but 307 might be a better choice for post requests, since 302/303 perform a GET redirect. Usually not a big issue for browsers but an api might start the communication with a post request.

this is my modified version that works pretty well

    public enum RedirectStatusCode
    {
        Permanent = 301,
        SeeOther = 303,
        Temporary = 307,
    }

    public class HttpsRedirectMiddleware : OwinMiddleware
    {
        private readonly int httpsPort;
        private readonly RedirectStatusCode statusCode;

        public HttpsRedirectMiddleware(OwinMiddleware next, int httpsPort, RedirectStatusCode statusCode) : base(next)
        {
            this.httpsPort = httpsPort;
            this.statusCode = statusCode;
        }

        public override async Task Invoke(IOwinContext context)
        {
            var protoHeader = context.Request.Headers["X-Forwarded-Proto"]?.ToString();
            if (context.Request.IsSecure || (protoHeader != null && protoHeader.ToLower().Equals("https")))
            {
                await Next.Invoke(context);
            }
            else
            {
                context.Response.StatusCode = (int)statusCode;
                var location = httpsPort == 443
                    ? $"https://{context.Request.Uri.Host}{context.Request.Uri.PathAndQuery}"
                    : $"https://{context.Request.Uri.Host}:{httpsPort}{context.Request.Uri.PathAndQuery}";
                context.Response.Redirect(location);
            }
        }
    }

    public static class HttpsRedirectMiddlewareExtensions
    {
        public static IAppBuilder UseHttpsRedirect(this IAppBuilder builder, int httpsPort = 443, RedirectStatusCode statusCode = RedirectStatusCode.SeeOther)
        {
            return builder.Use<HttpsRedirectMiddleware>(httpsPort, statusCode);
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment