migrate subdomain redirects to Azure
This commit is contained in:
parent
5e6f1640dc
commit
9d86f20ca7
|
@ -17,6 +17,7 @@
|
|||
|
||||
* For SMAPI developers:
|
||||
* When deploying web services to a single-instance app, the MongoDB server can now be replaced with in-memory storage.
|
||||
* Merged the separate legacy redirects app on AWS into the main app on Azure.
|
||||
|
||||
## 3.5
|
||||
Released 27 April 2020 for Stardew Valley 1.4.1 or later.
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Pathoschild.Http.Client;
|
||||
using StardewModdingAPI.Toolkit.Framework.Clients.WebApi;
|
||||
|
||||
namespace SMAPI.Web.LegacyRedirects.Controllers
|
||||
{
|
||||
/// <summary>Provides an API to perform mod update checks.</summary>
|
||||
[ApiController]
|
||||
[Produces("application/json")]
|
||||
[Route("api/v{version}/mods")]
|
||||
public class ModsApiController : Controller
|
||||
{
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Fetch version metadata for the given mods.</summary>
|
||||
/// <param name="model">The mod search criteria.</param>
|
||||
[HttpPost]
|
||||
public async Task<IEnumerable<ModEntryModel>> PostAsync([FromBody] ModSearchModel model)
|
||||
{
|
||||
using IClient client = new FluentClient("https://smapi.io/api");
|
||||
|
||||
Startup.ConfigureJsonNet(client.Formatters.JsonFormatter.SerializerSettings);
|
||||
|
||||
return await client
|
||||
.PostAsync(this.Request.Path)
|
||||
.WithBody(model)
|
||||
.AsArray<ModEntryModel>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite;
|
||||
|
||||
namespace SMAPI.Web.LegacyRedirects.Framework
|
||||
{
|
||||
/// <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 LambdaRewriteRule : IRule
|
||||
{
|
||||
/*********
|
||||
** Accessors
|
||||
*********/
|
||||
/// <summary>Rewrite an HTTP request if needed.</summary>
|
||||
private readonly Action<RewriteContext, HttpRequest, HttpResponse> Rewrite;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="rewrite">Rewrite an HTTP request if needed.</param>
|
||||
public LambdaRewriteRule(Action<RewriteContext, HttpRequest, HttpResponse> rewrite)
|
||||
{
|
||||
this.Rewrite = rewrite ?? throw new ArgumentNullException(nameof(rewrite));
|
||||
}
|
||||
|
||||
/// <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;
|
||||
HttpResponse response = context.HttpContext.Response;
|
||||
this.Rewrite(context, request, response);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace SMAPI.Web.LegacyRedirects
|
||||
{
|
||||
/// <summary>The main app entry point.</summary>
|
||||
public class Program
|
||||
{
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>The main app entry point.</summary>
|
||||
/// <param name="args">The command-line arguments.</param>
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Host
|
||||
.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(builder => builder.UseStartup<Startup>())
|
||||
.Build()
|
||||
.Run();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:52756",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"SMAPI.Web.LegacyRedirects": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "/",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="aws-beanstalk-tools-defaults.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.2" />
|
||||
<PackageReference Include="Pathoschild.Http.FluentClient" Version="4.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SMAPI.Toolkit.CoreInterfaces\SMAPI.Toolkit.CoreInterfaces.csproj" />
|
||||
<ProjectReference Include="..\SMAPI.Toolkit\SMAPI.Toolkit.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Rewrite;
|
||||
|
||||
namespace StardewModdingAPI.Web.Framework.RedirectRules
|
||||
{
|
||||
/// <summary>Redirect hostnames to a URL if they match a condition.</summary>
|
||||
internal class RedirectHostsToUrlsRule : RedirectMatchRule
|
||||
{
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <summary>Maps a lowercase hostname to the resulting redirect URL.</summary>
|
||||
private readonly Func<string, string> Map;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="statusCode">The status code to use for redirects.</param>
|
||||
/// <param name="map">Hostnames mapped to the resulting redirect URL.</param>
|
||||
public RedirectHostsToUrlsRule(HttpStatusCode statusCode, Func<string, string> map)
|
||||
{
|
||||
this.StatusCode = statusCode;
|
||||
this.Map = map ?? throw new ArgumentNullException(nameof(map));
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** Private methods
|
||||
*********/
|
||||
/// <summary>Get the new redirect URL.</summary>
|
||||
/// <param name="context">The rewrite context.</param>
|
||||
/// <returns>Returns the redirect URL, or <c>null</c> if the redirect doesn't apply.</returns>
|
||||
protected override string GetNewUrl(RewriteContext context)
|
||||
{
|
||||
// get requested host
|
||||
string host = context.HttpContext.Request.Host.Host;
|
||||
if (host == null)
|
||||
return null;
|
||||
|
||||
// get new host
|
||||
host = this.Map(host);
|
||||
if (host == null)
|
||||
return null;
|
||||
|
||||
// rewrite URL
|
||||
UriBuilder uri = this.GetUrl(context.HttpContext.Request);
|
||||
uri.Host = host;
|
||||
return uri.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite;
|
||||
|
||||
namespace StardewModdingAPI.Web.Framework.RedirectRules
|
||||
{
|
||||
/// <summary>Redirect matching requests to a URL.</summary>
|
||||
internal abstract class RedirectMatchRule : IRule
|
||||
{
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <summary>The status code to use for redirects.</summary>
|
||||
protected HttpStatusCode StatusCode { get; set; } = HttpStatusCode.Redirect;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <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)
|
||||
{
|
||||
string newUrl = this.GetNewUrl(context);
|
||||
if (newUrl == null)
|
||||
return;
|
||||
|
||||
HttpResponse response = context.HttpContext.Response;
|
||||
response.StatusCode = (int)HttpStatusCode.Redirect;
|
||||
response.Headers["Location"] = newUrl;
|
||||
context.Result = RuleResult.EndResponse;
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** Protected methods
|
||||
*********/
|
||||
/// <summary>Get the new redirect URL.</summary>
|
||||
/// <param name="context">The rewrite context.</param>
|
||||
/// <returns>Returns the redirect URL, or <c>null</c> if the redirect doesn't apply.</returns>
|
||||
protected abstract string GetNewUrl(RewriteContext context);
|
||||
|
||||
/// <summary>Get the full request URL.</summary>
|
||||
/// <param name="request">The request.</param>
|
||||
protected UriBuilder GetUrl(HttpRequest request)
|
||||
{
|
||||
return new UriBuilder
|
||||
{
|
||||
Scheme = request.Scheme,
|
||||
Host = request.Host.Host,
|
||||
Port = request.Host.Port ?? -1,
|
||||
Path = request.PathBase + request.Path,
|
||||
Query = request.QueryString.Value
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Rewrite;
|
||||
|
||||
namespace StardewModdingAPI.Web.Framework.RedirectRules
|
||||
{
|
||||
/// <summary>Redirect paths to URLs if they match a condition.</summary>
|
||||
internal class RedirectPathsToUrlsRule : RedirectMatchRule
|
||||
{
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <summary>Regex patterns matching the current URL mapped to the resulting redirect URL.</summary>
|
||||
private readonly IDictionary<Regex, string> Map;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="map">Regex patterns matching the current URL mapped to the resulting redirect URL.</param>
|
||||
public RedirectPathsToUrlsRule(IDictionary<string, string> map)
|
||||
{
|
||||
this.Map = map.ToDictionary(
|
||||
p => new Regex(p.Key, RegexOptions.IgnoreCase | RegexOptions.Compiled),
|
||||
p => p.Value
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** Protected methods
|
||||
*********/
|
||||
/// <summary>Get the new redirect URL.</summary>
|
||||
/// <param name="context">The rewrite context.</param>
|
||||
/// <returns>Returns the redirect URL, or <c>null</c> if the redirect doesn't apply.</returns>
|
||||
protected override string GetNewUrl(RewriteContext context)
|
||||
{
|
||||
string path = context.HttpContext.Request.Path.Value;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
foreach ((Regex pattern, string url) in this.Map)
|
||||
{
|
||||
if (pattern.IsMatch(path))
|
||||
return pattern.Replace(path, url);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Rewrite;
|
||||
|
||||
namespace StardewModdingAPI.Web.Framework.RedirectRules
|
||||
{
|
||||
/// <summary>Redirect requests to HTTPS.</summary>
|
||||
internal class RedirectToHttpsRule : RedirectMatchRule
|
||||
{
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <summary>Matches requests which should be ignored.</summary>
|
||||
private readonly Func<HttpRequest, bool> Except;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="except">Matches requests which should be ignored.</param>
|
||||
public RedirectToHttpsRule(Func<HttpRequest, bool> except = null)
|
||||
{
|
||||
this.Except = except ?? (req => false);
|
||||
this.StatusCode = HttpStatusCode.RedirectKeepVerb;
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
** Protected methods
|
||||
*********/
|
||||
/// <summary>Get the new redirect URL.</summary>
|
||||
/// <param name="context">The rewrite context.</param>
|
||||
/// <returns>Returns the redirect URL, or <c>null</c> if the redirect doesn't apply.</returns>
|
||||
protected override string GetNewUrl(RewriteContext context)
|
||||
{
|
||||
HttpRequest request = context.HttpContext.Request;
|
||||
if (request.IsHttps || this.Except(request))
|
||||
return null;
|
||||
|
||||
UriBuilder uri = this.GetUrl(request);
|
||||
uri.Scheme = "https";
|
||||
return uri.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
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
|
||||
{
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
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
|
||||
{
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <summary>Get the new URL to which to redirect (or <c>null</c> to skip).</summary>
|
||||
private readonly Func<HttpRequest, 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.NewUrl = req => shouldRewrite(req) ? url : null;
|
||||
}
|
||||
|
||||
/// <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.NewUrl = req => req.Path.HasValue ? regex.Replace(req.Path.Value, url) : null;
|
||||
}
|
||||
|
||||
/// <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 rewrite
|
||||
string newUrl = this.NewUrl(request);
|
||||
if (newUrl == null || newUrl == request.Path.Value)
|
||||
return;
|
||||
|
||||
// redirect request
|
||||
HttpResponse response = context.HttpContext.Response;
|
||||
response.StatusCode = (int)HttpStatusCode.Redirect;
|
||||
response.Headers["Location"] = newUrl;
|
||||
context.Result = RuleResult.EndResponse;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using Hangfire;
|
||||
using Hangfire.MemoryStorage;
|
||||
using Hangfire.Mongo;
|
||||
|
@ -27,7 +28,7 @@ using StardewModdingAPI.Web.Framework.Clients.Nexus;
|
|||
using StardewModdingAPI.Web.Framework.Clients.Pastebin;
|
||||
using StardewModdingAPI.Web.Framework.Compression;
|
||||
using StardewModdingAPI.Web.Framework.ConfigModels;
|
||||
using StardewModdingAPI.Web.Framework.RewriteRules;
|
||||
using StardewModdingAPI.Web.Framework.RedirectRules;
|
||||
using StardewModdingAPI.Web.Framework.Storage;
|
||||
|
||||
namespace StardewModdingAPI.Web
|
||||
|
@ -270,26 +271,49 @@ namespace StardewModdingAPI.Web
|
|||
/// <summary>Get the redirect rules to apply.</summary>
|
||||
private RewriteOptions GetRedirectRules()
|
||||
{
|
||||
var redirects = new RewriteOptions();
|
||||
var redirects = new RewriteOptions()
|
||||
// shortcut paths
|
||||
.Add(new RedirectPathsToUrlsRule(new Dictionary<string, string>
|
||||
{
|
||||
[@"^/3\.0\.?$"] = "https://stardewvalleywiki.com/Modding:Migrate_to_SMAPI_3.0",
|
||||
[@"^/(?:buildmsg|package)(?:/?(.*))$"] = "https://github.com/Pathoschild/SMAPI/blob/develop/docs/technical/mod-package.md#$1", // buildmsg deprecated, remove when SDV 1.4 is released
|
||||
[@"^/community\.?$"] = "https://stardewvalleywiki.com/Modding:Community",
|
||||
[@"^/compat\.?$"] = "https://smapi.io/mods",
|
||||
[@"^/docs\.?$"] = "https://stardewvalleywiki.com/Modding:Index",
|
||||
[@"^/install\.?$"] = "https://stardewvalleywiki.com/Modding:Player_Guide/Getting_Started#Install_SMAPI",
|
||||
[@"^/troubleshoot(.*)$"] = "https://stardewvalleywiki.com/Modding:Player_Guide/Troubleshooting$1",
|
||||
[@"^/xnb\.?$"] = "https://stardewvalleywiki.com/Modding:Using_XNB_mods"
|
||||
}))
|
||||
|
||||
// legacy paths
|
||||
.Add(new RedirectPathsToUrlsRule(this.GetLegacyPathRedirects()))
|
||||
|
||||
// subdomains
|
||||
.Add(new RedirectHostsToUrlsRule(HttpStatusCode.PermanentRedirect, host => host switch
|
||||
{
|
||||
"api.smapi.io" => "smapi.io/api",
|
||||
"json.smapi.io" => "smapi.io/json",
|
||||
"log.smapi.io" => "smapi.io/log",
|
||||
"mods.smapi.io" => "smapi.io/mods",
|
||||
_ => host.EndsWith(".smapi.io")
|
||||
? "smapi.io"
|
||||
: null
|
||||
}))
|
||||
|
||||
// redirect to HTTPS (except API for Linux/Mac Mono compatibility)
|
||||
redirects.Add(new ConditionalRedirectToHttpsRule(
|
||||
shouldRewrite: req =>
|
||||
req.Host.Host != "localhost"
|
||||
&& !req.Path.StartsWithSegments("/api")
|
||||
));
|
||||
.Add(
|
||||
new RedirectToHttpsRule(except: req => req.Host.Host == "localhost" || req.Path.StartsWithSegments("/api"))
|
||||
);
|
||||
|
||||
// shortcut redirects
|
||||
redirects.Add(new RedirectToUrlRule(@"^/3\.0\.?$", "https://stardewvalleywiki.com/Modding:Migrate_to_SMAPI_3.0"));
|
||||
redirects.Add(new RedirectToUrlRule(@"^/(?:buildmsg|package)(?:/?(.*))$", "https://github.com/Pathoschild/SMAPI/blob/develop/docs/technical/mod-package.md#$1")); // buildmsg deprecated, remove when SDV 1.4 is released
|
||||
redirects.Add(new RedirectToUrlRule(@"^/community\.?$", "https://stardewvalleywiki.com/Modding:Community"));
|
||||
redirects.Add(new RedirectToUrlRule(@"^/compat\.?$", "https://smapi.io/mods"));
|
||||
redirects.Add(new RedirectToUrlRule(@"^/docs\.?$", "https://stardewvalleywiki.com/Modding:Index"));
|
||||
redirects.Add(new RedirectToUrlRule(@"^/install\.?$", "https://stardewvalleywiki.com/Modding:Player_Guide/Getting_Started#Install_SMAPI"));
|
||||
redirects.Add(new RedirectToUrlRule(@"^/troubleshoot(.*)$", "https://stardewvalleywiki.com/Modding:Player_Guide/Troubleshooting$1"));
|
||||
redirects.Add(new RedirectToUrlRule(@"^/xnb\.?$", "https://stardewvalleywiki.com/Modding:Using_XNB_mods"));
|
||||
return redirects;
|
||||
}
|
||||
|
||||
// redirect legacy canimod.com URLs
|
||||
/// <summary>Get the redirects for legacy paths that have been moved elsewhere.</summary>
|
||||
private IDictionary<string, string> GetLegacyPathRedirects()
|
||||
{
|
||||
var redirects = new Dictionary<string, string>();
|
||||
|
||||
// canimod.com => wiki
|
||||
var wikiRedirects = new Dictionary<string, string[]>
|
||||
{
|
||||
["Modding:Index#Migration_guides"] = new[] { "^/for-devs/updating-a-smapi-mod", "^/guides/updating-a-smapi-mod" },
|
||||
|
@ -306,7 +330,7 @@ namespace StardewModdingAPI.Web
|
|||
foreach ((string page, string[] patterns) in wikiRedirects)
|
||||
{
|
||||
foreach (string pattern in patterns)
|
||||
redirects.Add(new RedirectToUrlRule(pattern, "https://stardewvalleywiki.com/" + page));
|
||||
redirects.Add(pattern, "https://stardewvalleywiki.com/" + page);
|
||||
}
|
||||
|
||||
return redirects;
|
||||
|
|
|
@ -77,8 +77,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Toolkit.CoreInterface
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Web", "SMAPI.Web\SMAPI.Web.csproj", "{80EFD92F-728F-41E0-8A5B-9F6F49A91899}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Web.LegacyRedirects", "SMAPI.Web.LegacyRedirects\SMAPI.Web.LegacyRedirects.csproj", "{159AA5A5-35C2-488C-B23F-1613C80594AE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
SMAPI.Internal\SMAPI.Internal.projitems*{0634ea4c-3b8f-42db-aea6-ca9e4ef6e92f}*SharedItemsImports = 5
|
||||
|
@ -138,10 +136,6 @@ Global
|
|||
{80EFD92F-728F-41E0-8A5B-9F6F49A91899}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{80EFD92F-728F-41E0-8A5B-9F6F49A91899}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{80EFD92F-728F-41E0-8A5B-9F6F49A91899}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{159AA5A5-35C2-488C-B23F-1613C80594AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{159AA5A5-35C2-488C-B23F-1613C80594AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{159AA5A5-35C2-488C-B23F-1613C80594AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{159AA5A5-35C2-488C-B23F-1613C80594AE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
Loading…
Reference in New Issue