From cb6c5e2de2ae5e8d2596893e97c7ad410fc395f5 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Sat, 6 Jun 2020 16:34:20 +0200 Subject: [PATCH] Make it possible for WebBrowser to post custom data While this isn't required for ASF (at least right now), it'll allow plugins to use ASF's WebBrowser for sending e.g. json to third-party endpoints. --- ArchiSteamFarm/ArchiWebHandler.cs | 4 +-- ArchiSteamFarm/WebBrowser.cs | 48 ++++++++++++++++++++----------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index 96e92c7fa..e16884437 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -913,7 +913,7 @@ namespace ArchiSteamFarm { } } - WebBrowser.ObjectResponse response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.ObjectResponse response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject>(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false); if (response == null) { return null; @@ -1028,7 +1028,7 @@ namespace ArchiSteamFarm { } } - WebBrowser.ObjectResponse response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.ObjectResponse response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject>>(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false); if (response == null) { return null; diff --git a/ArchiSteamFarm/WebBrowser.cs b/ArchiSteamFarm/WebBrowser.cs index 2c525c399..9602e6359 100644 --- a/ArchiSteamFarm/WebBrowser.cs +++ b/ArchiSteamFarm/WebBrowser.cs @@ -25,6 +25,7 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Text; using System.Threading.Tasks; using System.Xml; using AngleSharp; @@ -284,7 +285,7 @@ namespace ArchiSteamFarm { [ItemCanBeNull] [PublicAPI] - public async Task UrlPost(string request, IReadOnlyCollection> data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { + public async Task UrlPost(string request, T data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries)); @@ -321,7 +322,7 @@ namespace ArchiSteamFarm { [ItemCanBeNull] [PublicAPI] - public async Task UrlPostToHtmlDocument(string request, IReadOnlyCollection> data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { + public async Task UrlPostToHtmlDocument(string request, T data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries)); @@ -366,21 +367,21 @@ namespace ArchiSteamFarm { [ItemCanBeNull] [PublicAPI] - public async Task> UrlPostToJsonObject(string request, IReadOnlyCollection> data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { + public async Task> UrlPostToJsonObject(string request, TData data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where TResult : class where TData : class { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries)); return null; } - ObjectResponse result = null; + ObjectResponse result = null; for (byte i = 0; i < maxTries; i++) { await using StreamResponse response = await UrlPostToStream(request, data, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); if (response?.StatusCode.IsClientErrorCode() == true) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { - result = new ObjectResponse(response); + result = new ObjectResponse(response); } break; @@ -390,21 +391,21 @@ namespace ArchiSteamFarm { continue; } - T obj; + TResult obj; try { using StreamReader steamReader = new StreamReader(response.Content); using JsonReader jsonReader = new JsonTextReader(steamReader); JsonSerializer serializer = new JsonSerializer(); - obj = serializer.Deserialize(jsonReader); + obj = serializer.Deserialize(jsonReader); } catch (Exception e) { ArchiLogger.LogGenericWarningException(e); continue; } - return new ObjectResponse(response, obj); + return new ObjectResponse(response, obj); } if (maxTries > 1) { @@ -567,7 +568,7 @@ namespace ArchiSteamFarm { return null; } - return await InternalRequest(new Uri(request), HttpMethod.Get, null, referer, httpCompletionOption).ConfigureAwait(false); + return await InternalRequest(new Uri(request), HttpMethod.Get, null, referer, httpCompletionOption).ConfigureAwait(false); } private async Task InternalHead(string request, string referer = null) { @@ -577,10 +578,10 @@ namespace ArchiSteamFarm { return null; } - return await InternalRequest(new Uri(request), HttpMethod.Head, null, referer).ConfigureAwait(false); + return await InternalRequest(new Uri(request), HttpMethod.Head, null, referer).ConfigureAwait(false); } - private async Task InternalPost(string request, IReadOnlyCollection> data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) { + private async Task InternalPost(string request, T data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) where T : class { if (string.IsNullOrEmpty(request)) { ArchiLogger.LogNullError(nameof(request)); @@ -590,7 +591,7 @@ namespace ArchiSteamFarm { return await InternalRequest(new Uri(request), HttpMethod.Post, data, referer, httpCompletionOption).ConfigureAwait(false); } - private async Task InternalRequest(Uri requestUri, HttpMethod httpMethod, IReadOnlyCollection> data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte maxRedirections = MaxTries) { + private async Task InternalRequest(Uri requestUri, HttpMethod httpMethod, T data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte maxRedirections = MaxTries) where T : class { if ((requestUri == null) || (httpMethod == null)) { ArchiLogger.LogNullError(nameof(requestUri) + " || " + nameof(httpMethod)); @@ -605,10 +606,23 @@ namespace ArchiSteamFarm { #endif if (data != null) { - try { - request.Content = new FormUrlEncodedContent(data); - } catch (UriFormatException) { - request.Content = new StringContent(string.Join("&", data.Select(kv => WebUtility.UrlEncode(kv.Key) + "=" + WebUtility.UrlEncode(kv.Value))), null, "application/x-www-form-urlencoded"); + switch (data) { + case IReadOnlyCollection> dictionary: + try { + request.Content = new FormUrlEncodedContent(dictionary); + } catch (UriFormatException) { + request.Content = new StringContent(string.Join("&", dictionary.Select(kv => WebUtility.UrlEncode(kv.Key) + "=" + WebUtility.UrlEncode(kv.Value))), null, "application/x-www-form-urlencoded"); + } + + break; + case string text: + request.Content = new StringContent(text); + + break; + default: + request.Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json"); + + break; } } @@ -732,7 +746,7 @@ namespace ArchiSteamFarm { } [ItemCanBeNull] - private async Task UrlPostToStream(string request, IReadOnlyCollection> data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { + private async Task UrlPostToStream(string request, T data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));