diff options
-rw-r--r-- | docs/release-notes.md | 1 | ||||
-rw-r--r-- | src/SMAPI.Web/Framework/LogParser/PastebinClient.cs | 41 |
2 files changed, 30 insertions, 12 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md index 833f96b4..683e97b8 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -9,6 +9,7 @@ * Updated compatibility list. * The [log parser][] no longer expires logs after a week. * The [log parser][] now lets you close modals with `ESC` or a click outside it. + * Fixed [log parser][] error when uploading very large logs. * For modders: * Added `DaysSinceStart` property to `SDate` dates. diff --git a/src/SMAPI.Web/Framework/LogParser/PastebinClient.cs b/src/SMAPI.Web/Framework/LogParser/PastebinClient.cs index 60441234..1cfaed17 100644 --- a/src/SMAPI.Web/Framework/LogParser/PastebinClient.cs +++ b/src/SMAPI.Web/Framework/LogParser/PastebinClient.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; +using System.Text; using System.Threading.Tasks; +using System.Web; using Pathoschild.Http.Client; namespace StardewModdingAPI.Web.Framework.LogParser @@ -67,6 +69,8 @@ namespace StardewModdingAPI.Web.Framework.LogParser } } + /// <summary>Save a paste to Pastebin.</summary> + /// <param name="content">The paste content.</param> public async Task<SavePasteResponse> PostAsync(string content) { try @@ -77,18 +81,18 @@ namespace StardewModdingAPI.Web.Framework.LogParser // post to API string response = await this.Client - .PostAsync("api/api_post.php") - .WithBodyContent(new FormUrlEncodedContent(new Dictionary<string, string> - { - ["api_option"] = "paste", - ["api_user_key"] = this.UserKey, - ["api_dev_key"] = this.DevKey, - ["api_paste_private"] = "1", // unlisted - ["api_paste_name"] = $"SMAPI log {DateTime.UtcNow:s}", - ["api_paste_expire_date"] = "N", // never expire - ["api_paste_code"] = content - })) - .AsString(); + .PostAsync("api/api_post.php") + .WithBodyContent(this.GetFormUrlEncodedContent(new Dictionary<string, string> + { + ["api_option"] = "paste", + ["api_user_key"] = this.UserKey, + ["api_dev_key"] = this.DevKey, + ["api_paste_private"] = "1", // unlisted + ["api_paste_name"] = $"SMAPI log {DateTime.UtcNow:s}", + ["api_paste_expire_date"] = "N", // never expire + ["api_paste_code"] = content + })) + .AsString(); // handle Pastebin errors if (string.IsNullOrWhiteSpace(response)) @@ -113,5 +117,18 @@ namespace StardewModdingAPI.Web.Framework.LogParser { this.Client.Dispose(); } + + + /********* + ** Private methods + *********/ + /// <summary>Build an HTTP content body with form-url-encoded content.</summary> + /// <param name="data">The content to encode.</param> + /// <remarks>This bypasses an issue where <see cref="FormUrlEncodedContent"/> restricts the body length to the maximum size of a URL, which isn't applicable here.</remarks> + private HttpContent GetFormUrlEncodedContent(IDictionary<string, string> data) + { + string body = string.Join("&", from arg in data select $"{HttpUtility.UrlEncode(arg.Key)}={HttpUtility.UrlEncode(arg.Value)}"); + return new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded"); + } } } |