summaryrefslogtreecommitdiff
path: root/src/SMAPI.Web.LegacyRedirects
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2019-12-02 22:48:00 -0500
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2019-12-02 22:48:00 -0500
commitd34f369d35290bca96cc7225d9765d1a8a66fa8b (patch)
tree141bc6b30760bf5745b7adb9ce60f0cf6c8fa720 /src/SMAPI.Web.LegacyRedirects
parenta3f21685049cabf2d824c8060dc0b1de47e9449e (diff)
parent1128451acf56cf479864047c0bb8bb18e232fa00 (diff)
downloadSMAPI-d34f369d35290bca96cc7225d9765d1a8a66fa8b.tar.gz
SMAPI-d34f369d35290bca96cc7225d9765d1a8a66fa8b.tar.bz2
SMAPI-d34f369d35290bca96cc7225d9765d1a8a66fa8b.zip
Merge branch 'develop' into stable
Diffstat (limited to 'src/SMAPI.Web.LegacyRedirects')
-rw-r--r--src/SMAPI.Web.LegacyRedirects/Controllers/ModsApiController.cs33
-rw-r--r--src/SMAPI.Web.LegacyRedirects/Framework/LambdaRewriteRule.cs37
-rw-r--r--src/SMAPI.Web.LegacyRedirects/Program.cs23
-rw-r--r--src/SMAPI.Web.LegacyRedirects/Properties/launchSettings.json29
-rw-r--r--src/SMAPI.Web.LegacyRedirects/SMAPI.Web.LegacyRedirects.csproj21
-rw-r--r--src/SMAPI.Web.LegacyRedirects/Startup.cs94
6 files changed, 237 insertions, 0 deletions
diff --git a/src/SMAPI.Web.LegacyRedirects/Controllers/ModsApiController.cs b/src/SMAPI.Web.LegacyRedirects/Controllers/ModsApiController.cs
new file mode 100644
index 00000000..44ed0b6b
--- /dev/null
+++ b/src/SMAPI.Web.LegacyRedirects/Controllers/ModsApiController.cs
@@ -0,0 +1,33 @@
+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>();
+ }
+ }
+}
diff --git a/src/SMAPI.Web.LegacyRedirects/Framework/LambdaRewriteRule.cs b/src/SMAPI.Web.LegacyRedirects/Framework/LambdaRewriteRule.cs
new file mode 100644
index 00000000..e5138e5c
--- /dev/null
+++ b/src/SMAPI.Web.LegacyRedirects/Framework/LambdaRewriteRule.cs
@@ -0,0 +1,37 @@
+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);
+ }
+ }
+}
diff --git a/src/SMAPI.Web.LegacyRedirects/Program.cs b/src/SMAPI.Web.LegacyRedirects/Program.cs
new file mode 100644
index 00000000..6adee877
--- /dev/null
+++ b/src/SMAPI.Web.LegacyRedirects/Program.cs
@@ -0,0 +1,23 @@
+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();
+ }
+ }
+}
diff --git a/src/SMAPI.Web.LegacyRedirects/Properties/launchSettings.json b/src/SMAPI.Web.LegacyRedirects/Properties/launchSettings.json
new file mode 100644
index 00000000..e9a1b210
--- /dev/null
+++ b/src/SMAPI.Web.LegacyRedirects/Properties/launchSettings.json
@@ -0,0 +1,29 @@
+{
+ "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"
+ }
+ }
+} \ No newline at end of file
diff --git a/src/SMAPI.Web.LegacyRedirects/SMAPI.Web.LegacyRedirects.csproj b/src/SMAPI.Web.LegacyRedirects/SMAPI.Web.LegacyRedirects.csproj
new file mode 100644
index 00000000..a3d5c2b6
--- /dev/null
+++ b/src/SMAPI.Web.LegacyRedirects/SMAPI.Web.LegacyRedirects.csproj
@@ -0,0 +1,21 @@
+<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.0" />
+ <PackageReference Include="Pathoschild.Http.FluentClient" Version="3.3.1" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\SMAPI.Toolkit.CoreInterfaces\SMAPI.Toolkit.CoreInterfaces.csproj" />
+ <ProjectReference Include="..\SMAPI.Toolkit\SMAPI.Toolkit.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/src/SMAPI.Web.LegacyRedirects/Startup.cs b/src/SMAPI.Web.LegacyRedirects/Startup.cs
new file mode 100644
index 00000000..4af51575
--- /dev/null
+++ b/src/SMAPI.Web.LegacyRedirects/Startup.cs
@@ -0,0 +1,94 @@
+using System.Net;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Rewrite;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Newtonsoft.Json;
+using SMAPI.Web.LegacyRedirects.Framework;
+using StardewModdingAPI.Toolkit.Serialization;
+
+namespace SMAPI.Web.LegacyRedirects
+{
+ /// <summary>The web app startup configuration.</summary>
+ public class Startup
+ {
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>The method called by the runtime to add services to the container.</summary>
+ /// <param name="services">The service injection container.</param>
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services
+ .AddControllers()
+ .AddNewtonsoftJson(options => Startup.ConfigureJsonNet(options.SerializerSettings));
+ }
+
+ /// <summary>The method called by the runtime to configure the HTTP request pipeline.</summary>
+ /// <param name="app">The application builder.</param>
+ /// <param name="env">The hosting environment.</param>
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ app.UseDeveloperExceptionPage();
+
+ app
+ .UseRewriter(this.GetRedirectRules())
+ .UseRouting()
+ .UseAuthorization()
+ .UseEndpoints(endpoints => endpoints.MapControllers());
+ }
+
+ /// <summary>Configure a Json.NET serializer.</summary>
+ /// <param name="settings">The serializer settings to edit.</param>
+ internal static void ConfigureJsonNet(JsonSerializerSettings settings)
+ {
+ foreach (JsonConverter converter in new JsonHelper().JsonSettings.Converters)
+ settings.Converters.Add(converter);
+
+ settings.Formatting = Formatting.Indented;
+ settings.NullValueHandling = NullValueHandling.Ignore;
+ }
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>Get the redirect rules to apply.</summary>
+ private RewriteOptions GetRedirectRules()
+ {
+ var redirects = new RewriteOptions();
+
+ redirects.Add(
+ new LambdaRewriteRule((context, request, response) =>
+ {
+ string host = request.Host.Host;
+
+ // map API requests to proxy
+ // This is needed because the low-level HTTP client SMAPI uses for Linux/Mac compatibility doesn't support redirects.
+ if (host == "api.smapi.io")
+ {
+ request.Path = $"/api{request.Path}";
+ return;
+ }
+
+ // redirect other requests to Azure
+ string newRoot = 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",
+ _ => "smapi.io"
+ };
+ response.StatusCode = (int)HttpStatusCode.PermanentRedirect;
+ response.Headers["Location"] = $"{(request.IsHttps ? "https" : "http")}://{newRoot}{request.PathBase}{request.Path}{request.QueryString}";
+ context.Result = RuleResult.EndResponse;
+ })
+ );
+
+ return redirects;
+ }
+ }
+}