/// <summary> /// Initializes a new instance of the <see cref="SslRedirectContext"/> class. /// </summary> /// <param name="context">The HTTP-specific information about the request.</param> /// <param name="options">The options for the current request.</param> public SslRedirectContext(HttpContext context, SslRedirectOptions options) { HttpContext = context; Options = options.Clone(); _fwh = new Lazy <ForwardedHeader>(() => ForwardedHeader.FromHttpContext(context)); }
/// <summary> /// Constructs a <see cref="ForwardedHeader"/> object from a <see cref="HttpContext"/>. /// </summary> /// <param name="context">The context to parse.</param> /// <returns>The constructed <see cref="ForwardedHeader"/> object or <see langword="null"/>.</returns> public static ForwardedHeader FromHttpContext(HttpContext context) { var headers = context?.Request.Headers ?? throw new ArgumentNullException(nameof(context)); ForwardedHeader result = null; ForwardedHeader header() { if (result == null) { result = new ForwardedHeader(); } return(result); } foreach (var pair in _xProtocolHeaders) { if (headers.ContainsKey(pair.Key)) { header().Protocol = pair.Value.Equals(headers[pair.Key], StringComparison.OrdinalIgnoreCase) ? ProtocolType.Https : ProtocolType.Http; } } if (headers.TryGetValue(HeaderNames.ForwardedFor, out var @for)) { header().For = @for .SelectMany(f => f.Split(new[] { ',' }, RemoveEmptyEntries)) .Select(f => f.Trim()) .ToArray(); } else if (headers.TryGetValue(HeaderNames.ProxyUserIp, out var @ip)) { header().For = @ip; } if (headers.TryGetValue(HeaderNames.ForwardedHost, out var host)) { header().Host = host; } if (headers.TryGetValue(HeaderNames.ForwardedPort, out var pv)) { if (Int32.TryParse(pv, out var port)) { header().Port = port; } } // https://tools.ietf.org/html/rfc7239 if (headers.TryGetValue(HeaderNames.Forwarded, out var fw)) { var values = fw .SelectMany(f => f.Split(new[] { ';', ',' }, RemoveEmptyEntries)) .Select(f => f.Split(new[] { '=' }, RemoveEmptyEntries)) .Where(f => f.Length == 2) .ToLookup(f => f[0].Trim().ToUpperInvariant(), f => f[1].Trim()); if (values.Contains("PROTO")) { header().Protocol = values["PROTO"].Last().Equals("https", StringComparison.OrdinalIgnoreCase) ? ProtocolType.Https : ProtocolType.Http; } if (values.Contains("FOR")) { header().For = values["FOR"].ToArray(); } if (values.Contains("HOST")) { header().Host = values["HOST"].Last(); } if (values.Contains("BY")) { header().By = values["BY"].Last(); } } return(result); }