From 6dff9779a349945d502dee67d5d4dd8e63b4f753 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 25 Sep 2017 17:39:51 -0400 Subject: use POST for SMAPI update checks to avoid issues with long queries (#336) --- .../Controllers/ModsController.cs | 17 +++++++++++++++-- .../Framework/VersionConstraint.cs | 15 +++++++++++++++ src/StardewModdingAPI.Web/Startup.cs | 19 +++---------------- 3 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 src/StardewModdingAPI.Web/Framework/VersionConstraint.cs (limited to 'src/StardewModdingAPI.Web') diff --git a/src/StardewModdingAPI.Web/Controllers/ModsController.cs b/src/StardewModdingAPI.Web/Controllers/ModsController.cs index 566577e4..f29de45a 100644 --- a/src/StardewModdingAPI.Web/Controllers/ModsController.cs +++ b/src/StardewModdingAPI.Web/Controllers/ModsController.cs @@ -14,6 +14,7 @@ namespace StardewModdingAPI.Web.Controllers { /// Provides an API to perform mod update checks. [Produces("application/json")] + [Route("api/{version:semanticVersion}/[controller]")] internal class ModsController : Controller { /********* @@ -79,16 +80,28 @@ namespace StardewModdingAPI.Web.Controllers /// The namespaced mod keys to search as a comma-delimited array. [HttpGet] public async Task> GetAsync(string modKeys) + { + string[] modKeysArray = modKeys?.Split(',').Select(p => p.Trim()).ToArray(); + if (modKeysArray == null || !modKeysArray.Any()) + return new Dictionary(); + + return await this.PostAsync(new ModSearchModel(modKeysArray)); + } + + /// Fetch version metadata for the given mods. + /// The mod search criteria. + [HttpPost] + public async Task> PostAsync([FromBody] ModSearchModel search) { // sort & filter keys - string[] modKeysArray = (modKeys?.Split(',').Select(p => p.Trim()).ToArray() ?? new string[0]) + string[] modKeys = (search?.ModKeys?.ToArray() ?? new string[0]) .Distinct(StringComparer.CurrentCultureIgnoreCase) .OrderBy(p => p, StringComparer.CurrentCultureIgnoreCase) .ToArray(); // fetch mod info IDictionary result = new Dictionary(StringComparer.CurrentCultureIgnoreCase); - foreach (string modKey in modKeysArray) + foreach (string modKey in modKeys) { // parse mod key if (!this.TryParseModKey(modKey, out string vendorKey, out string modID)) diff --git a/src/StardewModdingAPI.Web/Framework/VersionConstraint.cs b/src/StardewModdingAPI.Web/Framework/VersionConstraint.cs new file mode 100644 index 00000000..be9c0918 --- /dev/null +++ b/src/StardewModdingAPI.Web/Framework/VersionConstraint.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Routing.Constraints; + +namespace StardewModdingAPI.Web.Framework +{ + /// Constrains a route value to a valid semantic version. + internal class VersionConstraint : RegexRouteConstraint + { + /********* + ** Public methods + *********/ + /// Construct an instance. + public VersionConstraint() + : base(@"^v(?>(?0|[1-9]\d*))\.(?>(?0|[1-9]\d*))(?>(?:\.(?0|[1-9]\d*))?)(?:-(?(?>[a-z0-9]+[\-\.]?)+))?$") { } + } +} diff --git a/src/StardewModdingAPI.Web/Startup.cs b/src/StardewModdingAPI.Web/Startup.cs index d5b828b7..eaf14983 100644 --- a/src/StardewModdingAPI.Web/Startup.cs +++ b/src/StardewModdingAPI.Web/Startup.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Rewrite; +using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -42,6 +43,7 @@ namespace StardewModdingAPI.Web { services .Configure(this.Configuration.GetSection("ModUpdateCheck")) + .Configure(options => options.ConstraintMap.Add("semanticVersion", typeof(VersionConstraint))) .AddMemoryCache() .AddMvc() .ConfigureApplicationPartManager(manager => manager.FeatureProviders.Add(new InternalControllerFeatureProvider())) @@ -62,22 +64,7 @@ namespace StardewModdingAPI.Web loggerFactory.AddDebug(); app .UseRewriter(new RewriteOptions().Add(new RewriteSubdomainRule())) // convert subdomain.smapi.io => smapi.io/subdomain for routing - .UseMvc(route => - { - route.MapRoute( - name: "API", - template: "api/{version}/{controller}/{action?}", - defaults: new - { - action = "GetAsync" - }, - constraints: new - { - // version regex from SMAPI's SemanticVersion implementation - version = @"^v(?>(?0|[1-9]\d*))\.(?>(?0|[1-9]\d*))(?>(?:\.(?0|[1-9]\d*))?)(?:-(?(?>[a-z0-9]+[\-\.]?)+))?$" - } - ); - }); + .UseMvc(); } } } -- cgit