summaryrefslogtreecommitdiff
path: root/src/SMAPI.Web/Framework/RewriteRules
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2017-11-01 17:42:18 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2017-11-01 17:42:18 -0400
commite0b72374cd14298aacc6f71dc391fdc9814be37c (patch)
tree2e5d85937c34539c1a0df48423b5136508693ca8 /src/SMAPI.Web/Framework/RewriteRules
parent79118316065a01322d8ea12a14589ec016794c32 (diff)
parent089e6de749ae7cb109af00164d2597c6644c255e (diff)
downloadSMAPI-e0b72374cd14298aacc6f71dc391fdc9814be37c.tar.gz
SMAPI-e0b72374cd14298aacc6f71dc391fdc9814be37c.tar.bz2
SMAPI-e0b72374cd14298aacc6f71dc391fdc9814be37c.zip
Merge branch 'develop' into stable
Diffstat (limited to 'src/SMAPI.Web/Framework/RewriteRules')
-rw-r--r--src/SMAPI.Web/Framework/RewriteRules/ConditionalRedirectToHttpsRule.cs62
-rw-r--r--src/SMAPI.Web/Framework/RewriteRules/ConditionalRewriteSubdomainRule.cs48
-rw-r--r--src/SMAPI.Web/Framework/RewriteRules/RedirectToUrlRule.cs61
3 files changed, 171 insertions, 0 deletions
diff --git a/src/SMAPI.Web/Framework/RewriteRules/ConditionalRedirectToHttpsRule.cs b/src/SMAPI.Web/Framework/RewriteRules/ConditionalRedirectToHttpsRule.cs
new file mode 100644
index 00000000..d6a56bb7
--- /dev/null
+++ b/src/SMAPI.Web/Framework/RewriteRules/ConditionalRedirectToHttpsRule.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Net;
+using System.Text;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite;
+
+namespace StardewModdingAPI.Web.Framework.RewriteRules
+{
+ /// <summary>Redirect requests to HTTPS.</summary>
+ /// <remarks>Derived from <a href="https://stackoverflow.com/a/44526747/262123" /> and <see cref="Microsoft.AspNetCore.Rewrite.Internal.RedirectToHttpsRule"/>.</remarks>
+ internal class ConditionalRedirectToHttpsRule : IRule
+ {
+ /*********
+ ** Properties
+ *********/
+ /// <summary>A predicate which indicates when the rule should be applied.</summary>
+ private readonly Func<HttpRequest, bool> ShouldRewrite;
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="shouldRewrite">A predicate which indicates when the rule should be applied.</param>
+ public ConditionalRedirectToHttpsRule(Func<HttpRequest, bool> shouldRewrite = null)
+ {
+ this.ShouldRewrite = shouldRewrite ?? (req => true);
+ }
+
+ /// <summary>Applies the rule. Implementations of ApplyRule should set the value for <see cref="RewriteContext.Result" /> (defaults to RuleResult.ContinueRules).</summary>
+ /// <param name="context">The rewrite context.</param>
+ public void ApplyRule(RewriteContext context)
+ {
+ HttpRequest request = context.HttpContext.Request;
+
+ // check condition
+ if (this.IsSecure(request) || !this.ShouldRewrite(request))
+ return;
+
+ // redirect request
+ HttpResponse response = context.HttpContext.Response;
+ response.StatusCode = (int)HttpStatusCode.RedirectKeepVerb;
+ response.Headers["Location"] = new StringBuilder()
+ .Append("https://")
+ .Append(request.Host.Host)
+ .Append(request.PathBase)
+ .Append(request.Path)
+ .Append(request.QueryString)
+ .ToString();
+ context.Result = RuleResult.EndResponse;
+ }
+
+ /// <summary>Get whether the request was received over HTTPS.</summary>
+ /// <param name="request">The request to check.</param>
+ public bool IsSecure(HttpRequest request)
+ {
+ return
+ request.IsHttps // HTTPS to server
+ || string.Equals(request.Headers["x-forwarded-proto"], "HTTPS", StringComparison.OrdinalIgnoreCase); // HTTPS to AWS load balancer
+ }
+ }
+}
diff --git a/src/SMAPI.Web/Framework/RewriteRules/ConditionalRewriteSubdomainRule.cs b/src/SMAPI.Web/Framework/RewriteRules/ConditionalRewriteSubdomainRule.cs
new file mode 100644
index 00000000..920632ab
--- /dev/null
+++ b/src/SMAPI.Web/Framework/RewriteRules/ConditionalRewriteSubdomainRule.cs
@@ -0,0 +1,48 @@
+using System;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite;
+
+namespace StardewModdingAPI.Web.Framework.RewriteRules
+{
+ /// <summary>Rewrite requests to prepend the subdomain portion (if any) to the path.</summary>
+ /// <remarks>Derived from <a href="https://stackoverflow.com/a/44526747/262123" />.</remarks>
+ internal class ConditionalRewriteSubdomainRule : IRule
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>A predicate which indicates when the rule should be applied.</summary>
+ private readonly Func<HttpRequest, bool> ShouldRewrite;
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="shouldRewrite">A predicate which indicates when the rule should be applied.</param>
+ public ConditionalRewriteSubdomainRule(Func<HttpRequest, bool> shouldRewrite = null)
+ {
+ this.ShouldRewrite = shouldRewrite ?? (req => true);
+ }
+
+ /// <summary>Applies the rule. Implementations of ApplyRule should set the value for <see cref="RewriteContext.Result" /> (defaults to RuleResult.ContinueRules).</summary>
+ /// <param name="context">The rewrite context.</param>
+ public void ApplyRule(RewriteContext context)
+ {
+ HttpRequest request = context.HttpContext.Request;
+
+ // check condition
+ if (!this.ShouldRewrite(request))
+ return;
+
+ // get host parts
+ string host = request.Host.Host;
+ string[] parts = host.Split('.');
+ if (parts.Length < 2)
+ return;
+
+ // prepend to path
+ request.Path = $"/{parts[0]}{request.Path}";
+ }
+ }
+}
diff --git a/src/SMAPI.Web/Framework/RewriteRules/RedirectToUrlRule.cs b/src/SMAPI.Web/Framework/RewriteRules/RedirectToUrlRule.cs
new file mode 100644
index 00000000..0719e311
--- /dev/null
+++ b/src/SMAPI.Web/Framework/RewriteRules/RedirectToUrlRule.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Net;
+using System.Text.RegularExpressions;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Rewrite;
+
+namespace StardewModdingAPI.Web.Framework.RewriteRules
+{
+ /// <summary>Redirect requests to an external URL if they match a condition.</summary>
+ internal class RedirectToUrlRule : IRule
+ {
+ /*********
+ ** Properties
+ *********/
+ /// <summary>A predicate which indicates when the rule should be applied.</summary>
+ private readonly Func<HttpRequest, bool> ShouldRewrite;
+
+ /// <summary>The new URL to which to redirect.</summary>
+ private readonly string NewUrl;
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="shouldRewrite">A predicate which indicates when the rule should be applied.</param>
+ /// <param name="url">The new URL to which to redirect.</param>
+ public RedirectToUrlRule(Func<HttpRequest, bool> shouldRewrite, string url)
+ {
+ this.ShouldRewrite = shouldRewrite ?? (req => true);
+ this.NewUrl = url;
+ }
+
+ /// <summary>Construct an instance.</summary>
+ /// <param name="pathRegex">A case-insensitive regex to match against the path.</param>
+ /// <param name="url">The external URL.</param>
+ public RedirectToUrlRule(string pathRegex, string url)
+ {
+ Regex regex = new Regex(pathRegex, RegexOptions.IgnoreCase | RegexOptions.Compiled);
+ this.ShouldRewrite = req => req.Path.HasValue && regex.IsMatch(req.Path.Value);
+ this.NewUrl = url;
+ }
+
+ /// <summary>Applies the rule. Implementations of ApplyRule should set the value for <see cref="RewriteContext.Result" /> (defaults to RuleResult.ContinueRules).</summary>
+ /// <param name="context">The rewrite context.</param>
+ public void ApplyRule(RewriteContext context)
+ {
+ HttpRequest request = context.HttpContext.Request;
+
+ // check condition
+ if (!this.ShouldRewrite(request))
+ return;
+
+ // redirect request
+ HttpResponse response = context.HttpContext.Response;
+ response.StatusCode = (int)HttpStatusCode.Redirect;
+ response.Headers["Location"] = this.NewUrl;
+ context.Result = RuleResult.EndResponse;
+ }
+ }
+}