From d4345a1a16d3be67d240d00194de899b026e21e8 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Sun, 13 Sep 2020 21:43:25 +0200 Subject: [PATCH] Closes #1964 --- .../SteamTokenDumperPlugin.cs | 2 +- ArchiSteamFarm/ArchiWebHandler.cs | 110 +++++++++--------- ArchiSteamFarm/Statistics.cs | 4 +- ArchiSteamFarm/Utilities.cs | 25 ++-- ArchiSteamFarm/WebBrowser.cs | 71 ++++++----- 5 files changed, 112 insertions(+), 100 deletions(-) diff --git a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs index a23062323..4af9bc149 100644 --- a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs @@ -429,7 +429,7 @@ namespace ArchiSteamFarm.OfficialPlugins.SteamTokenDumper { ASF.ArchiLogger.LogGenericInfo($"Submitting registered apps/subs/depots: {appTokens.Count}/{packageTokens.Count}/{depotKeys.Count}..."); - WebBrowser.ObjectResponse? response = await ASF.WebBrowser.UrlPostToJsonObject(request, requestData, requestOptions: WebBrowser.ERequestOptions.ReturnClientErrors).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await ASF.WebBrowser.UrlPostToJsonObject(request, data: requestData, requestOptions: WebBrowser.ERequestOptions.ReturnClientErrors).ConfigureAwait(false); if ((response?.Content?.Data == null) || response.StatusCode.IsClientErrorCode()) { ASF.ArchiLogger.LogGenericWarning(Strings.WarningFailed); diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index 388e2641a..632c832a9 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -407,7 +407,7 @@ namespace ArchiSteamFarm { foreach (Steam.TradeOfferSendRequest trade in trades) { data["json_tradeoffer"] = JsonConvert.SerializeObject(trade); - WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data, referer).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data: data, referer: referer).ConfigureAwait(false); if (response?.Content == null) { return (false, mobileTradeOfferIDs); @@ -422,7 +422,7 @@ namespace ArchiSteamFarm { } [PublicAPI] - public async Task UrlGetToHtmlDocumentWithSession(string host, string request, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { + public async Task UrlGetToHtmlDocumentWithSession(string host, string request, IReadOnlyCollection>? headers = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(request)) { throw new ArgumentNullException(nameof(host) + " || " + nameof(request)); } @@ -440,7 +440,7 @@ namespace ArchiSteamFarm { if (sessionExpired.GetValueOrDefault(true)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlGetToHtmlDocumentWithSession(host, request, referer, requestOptions, true, --maxTries).ConfigureAwait(false); + return await UrlGetToHtmlDocumentWithSession(host, request, headers, referer, requestOptions, true, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -469,7 +469,7 @@ namespace ArchiSteamFarm { } } - WebBrowser.HtmlDocumentResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlGetToHtmlDocument(host + request, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.HtmlDocumentResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlGetToHtmlDocument(host + request, headers, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); if (response == null) { return null; @@ -477,7 +477,7 @@ namespace ArchiSteamFarm { if (IsSessionExpiredUri(response.FinalUri)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlGetToHtmlDocumentWithSession(host, request, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlGetToHtmlDocumentWithSession(host, request, headers, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -490,14 +490,14 @@ namespace ArchiSteamFarm { if (await IsProfileUri(response.FinalUri).ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.WarningWorkaroundTriggered, nameof(IsProfileUri))); - return await UrlGetToHtmlDocumentWithSession(host, request, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlGetToHtmlDocumentWithSession(host, request, headers, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } return response; } [PublicAPI] - public async Task?> UrlGetToJsonObjectWithSession(string host, string request, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) where T : class { + public async Task?> UrlGetToJsonObjectWithSession(string host, string request, IReadOnlyCollection>? headers = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) where T : class { if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(request)) { throw new ArgumentNullException(nameof(host) + " || " + nameof(request)); } @@ -515,7 +515,7 @@ namespace ArchiSteamFarm { if (sessionExpired.GetValueOrDefault(true)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlGetToJsonObjectWithSession(host, request, referer, requestOptions, true, --maxTries).ConfigureAwait(false); + return await UrlGetToJsonObjectWithSession(host, request, headers, referer, requestOptions, true, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -544,7 +544,7 @@ namespace ArchiSteamFarm { } } - WebBrowser.ObjectResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlGetToJsonObject(host + request, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlGetToJsonObject(host + request, headers, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); if (response == null) { return default; @@ -552,7 +552,7 @@ namespace ArchiSteamFarm { if (IsSessionExpiredUri(response.FinalUri)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlGetToJsonObjectWithSession(host, request, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlGetToJsonObjectWithSession(host, request, headers, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -565,14 +565,14 @@ namespace ArchiSteamFarm { if (await IsProfileUri(response.FinalUri).ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.WarningWorkaroundTriggered, nameof(IsProfileUri))); - return await UrlGetToJsonObjectWithSession(host, request, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlGetToJsonObjectWithSession(host, request, headers, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } return response; } [PublicAPI] - public async Task UrlGetToXmlDocumentWithSession(string host, string request, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { + public async Task UrlGetToXmlDocumentWithSession(string host, string request, IReadOnlyCollection>? headers = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(request)) { throw new ArgumentNullException(nameof(host) + " || " + nameof(request)); } @@ -590,7 +590,7 @@ namespace ArchiSteamFarm { if (sessionExpired.GetValueOrDefault(true)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlGetToXmlDocumentWithSession(host, request, referer, requestOptions, true, --maxTries).ConfigureAwait(false); + return await UrlGetToXmlDocumentWithSession(host, request, headers, referer, requestOptions, true, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -619,7 +619,7 @@ namespace ArchiSteamFarm { } } - WebBrowser.XmlDocumentResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlGetToXmlDocument(host + request, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.XmlDocumentResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlGetToXmlDocument(host + request, headers, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); if (response == null) { return null; @@ -627,7 +627,7 @@ namespace ArchiSteamFarm { if (IsSessionExpiredUri(response.FinalUri)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlGetToXmlDocumentWithSession(host, request, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlGetToXmlDocumentWithSession(host, request, headers, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -640,14 +640,14 @@ namespace ArchiSteamFarm { if (await IsProfileUri(response.FinalUri).ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.WarningWorkaroundTriggered, nameof(IsProfileUri))); - return await UrlGetToXmlDocumentWithSession(host, request, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlGetToXmlDocumentWithSession(host, request, headers, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } return response; } [PublicAPI] - public async Task UrlHeadWithSession(string host, string request, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { + public async Task UrlHeadWithSession(string host, string request, IReadOnlyCollection>? headers = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(request)) { throw new ArgumentNullException(nameof(host) + " || " + nameof(request)); } @@ -665,7 +665,7 @@ namespace ArchiSteamFarm { if (sessionExpired.GetValueOrDefault(true)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlHeadWithSession(host, request, referer, requestOptions, true, --maxTries).ConfigureAwait(false); + return await UrlHeadWithSession(host, request, headers, referer, requestOptions, true, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -694,7 +694,7 @@ namespace ArchiSteamFarm { } } - WebBrowser.BasicResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlHead(host + request, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.BasicResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlHead(host + request, headers, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); if (response == null) { return false; @@ -702,7 +702,7 @@ namespace ArchiSteamFarm { if (IsSessionExpiredUri(response.FinalUri)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlHeadWithSession(host, request, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlHeadWithSession(host, request, headers, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -715,14 +715,14 @@ namespace ArchiSteamFarm { if (await IsProfileUri(response.FinalUri).ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.WarningWorkaroundTriggered, nameof(IsProfileUri))); - return await UrlHeadWithSession(host, request, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlHeadWithSession(host, request, headers, referer, requestOptions, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } return true; } [PublicAPI] - public async Task UrlPostToHtmlDocumentWithSession(string host, string request, IDictionary? data = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, ESession session = ESession.Lowercase, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { + public async Task UrlPostToHtmlDocumentWithSession(string host, string request, IReadOnlyCollection>? headers = null, IDictionary? data = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, ESession session = ESession.Lowercase, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(request) || !Enum.IsDefined(typeof(ESession), session)) { throw new ArgumentNullException(nameof(host) + " || " + nameof(request) + " || " + nameof(session)); } @@ -740,7 +740,7 @@ namespace ArchiSteamFarm { if (sessionExpired.GetValueOrDefault(true)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlPostToHtmlDocumentWithSession(host, request, data, referer, requestOptions, session, true, --maxTries).ConfigureAwait(false); + return await UrlPostToHtmlDocumentWithSession(host, request, headers, data, referer, requestOptions, session, true, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -792,7 +792,7 @@ namespace ArchiSteamFarm { } } - WebBrowser.HtmlDocumentResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToHtmlDocument(host + request, data, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.HtmlDocumentResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToHtmlDocument(host + request, headers, data, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); if (response == null) { return null; @@ -800,7 +800,7 @@ namespace ArchiSteamFarm { if (IsSessionExpiredUri(response.FinalUri)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlPostToHtmlDocumentWithSession(host, request, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlPostToHtmlDocumentWithSession(host, request, headers, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -813,14 +813,14 @@ namespace ArchiSteamFarm { if (await IsProfileUri(response.FinalUri).ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.WarningWorkaroundTriggered, nameof(IsProfileUri))); - return await UrlPostToHtmlDocumentWithSession(host, request, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlPostToHtmlDocumentWithSession(host, request, headers, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } return response; } [PublicAPI] - public async Task?> UrlPostToJsonObjectWithSession(string host, string request, IDictionary? data = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, ESession session = ESession.Lowercase, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) where T : class { + public async Task?> UrlPostToJsonObjectWithSession(string host, string request, IReadOnlyCollection>? headers = null, IDictionary? data = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, ESession session = ESession.Lowercase, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) where T : class { if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(request) || !Enum.IsDefined(typeof(ESession), session)) { throw new ArgumentNullException(nameof(host) + " || " + nameof(request) + " || " + nameof(session)); } @@ -838,7 +838,7 @@ namespace ArchiSteamFarm { if (sessionExpired.GetValueOrDefault(true)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlPostToJsonObjectWithSession(host, request, data, referer, requestOptions, session, true, --maxTries).ConfigureAwait(false); + return await UrlPostToJsonObjectWithSession(host, request, headers, data, referer, requestOptions, session, true, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -890,7 +890,7 @@ namespace ArchiSteamFarm { } } - WebBrowser.ObjectResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject>(host + request, data, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject>(host + request, headers, data, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); if (response == null) { return null; @@ -898,7 +898,7 @@ namespace ArchiSteamFarm { if (IsSessionExpiredUri(response.FinalUri)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlPostToJsonObjectWithSession(host, request, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlPostToJsonObjectWithSession(host, request, headers, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -911,14 +911,14 @@ namespace ArchiSteamFarm { if (await IsProfileUri(response.FinalUri).ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.WarningWorkaroundTriggered, nameof(IsProfileUri))); - return await UrlPostToJsonObjectWithSession(host, request, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlPostToJsonObjectWithSession(host, request, headers, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } return response; } [PublicAPI] - public async Task?> UrlPostToJsonObjectWithSession(string host, string request, ICollection>? data = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, ESession session = ESession.Lowercase, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) where T : class { + public async Task?> UrlPostToJsonObjectWithSession(string host, string request, IReadOnlyCollection>? headers = null, ICollection>? data = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, ESession session = ESession.Lowercase, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) where T : class { if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(request) || !Enum.IsDefined(typeof(ESession), session)) { throw new ArgumentNullException(nameof(host) + " || " + nameof(request) + " || " + nameof(session)); } @@ -936,7 +936,7 @@ namespace ArchiSteamFarm { if (sessionExpired.GetValueOrDefault(true)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlPostToJsonObjectWithSession(host, request, data, referer, requestOptions, session, true, --maxTries).ConfigureAwait(false); + return await UrlPostToJsonObjectWithSession(host, request, headers, data, referer, requestOptions, session, true, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -991,7 +991,7 @@ namespace ArchiSteamFarm { } } - WebBrowser.ObjectResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject>>(host + request, data, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject>>(host + request, headers, data, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); if (response == null) { return null; @@ -999,7 +999,7 @@ namespace ArchiSteamFarm { if (IsSessionExpiredUri(response.FinalUri)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlPostToJsonObjectWithSession(host, request, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlPostToJsonObjectWithSession(host, request, headers, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -1012,14 +1012,14 @@ namespace ArchiSteamFarm { if (await IsProfileUri(response.FinalUri).ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.WarningWorkaroundTriggered, nameof(IsProfileUri))); - return await UrlPostToJsonObjectWithSession(host, request, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlPostToJsonObjectWithSession(host, request, headers, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } return response; } [PublicAPI] - public async Task UrlPostWithSession(string host, string request, IDictionary? data = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, ESession session = ESession.Lowercase, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { + public async Task UrlPostWithSession(string host, string request, IReadOnlyCollection>? headers = null, IDictionary? data = null, string? referer = null, WebBrowser.ERequestOptions requestOptions = WebBrowser.ERequestOptions.None, ESession session = ESession.Lowercase, bool checkSessionPreemptively = true, byte maxTries = WebBrowser.MaxTries) { if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(request) || !Enum.IsDefined(typeof(ESession), session)) { throw new ArgumentNullException(nameof(host) + " || " + nameof(request) + " || " + nameof(session)); } @@ -1037,7 +1037,7 @@ namespace ArchiSteamFarm { if (sessionExpired.GetValueOrDefault(true)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlPostWithSession(host, request, data, referer, requestOptions, session, true, --maxTries).ConfigureAwait(false); + return await UrlPostWithSession(host, request, headers, data, referer, requestOptions, session, true, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -1089,7 +1089,7 @@ namespace ArchiSteamFarm { } } - WebBrowser.BasicResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlPost(host + request, data, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.BasicResponse? response = await WebLimitRequest(host, async () => await WebBrowser.UrlPost(host + request, headers, data, referer, requestOptions).ConfigureAwait(false)).ConfigureAwait(false); if (response == null) { return false; @@ -1097,7 +1097,7 @@ namespace ArchiSteamFarm { if (IsSessionExpiredUri(response.FinalUri)) { if (await RefreshSession().ConfigureAwait(false)) { - return await UrlPostWithSession(host, request, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlPostWithSession(host, request, headers, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed); @@ -1110,7 +1110,7 @@ namespace ArchiSteamFarm { if (await IsProfileUri(response.FinalUri).ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.WarningWorkaroundTriggered, nameof(IsProfileUri))); - return await UrlPostWithSession(host, request, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); + return await UrlPostWithSession(host, request, headers, data, referer, requestOptions, session, checkSessionPreemptively, --maxTries).ConfigureAwait(false); } return true; @@ -1173,7 +1173,7 @@ namespace ArchiSteamFarm { { "giftcardid", giftCardID.ToString() } }; - WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamStoreURL, request, data).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamStoreURL, request, data: data).ConfigureAwait(false); if (response?.Content == null) { return false; @@ -1210,7 +1210,7 @@ namespace ArchiSteamFarm { { "tradeofferid", tradeID.ToString() } }; - WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data, referer, WebBrowser.ERequestOptions.ReturnServerErrors).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data: data, referer: referer, requestOptions: WebBrowser.ERequestOptions.ReturnServerErrors).ConfigureAwait(false); if (response == null) { return (false, false); @@ -1244,7 +1244,7 @@ namespace ArchiSteamFarm { { "subid", subID.ToString() } }; - using WebBrowser.HtmlDocumentResponse? response = await UrlPostToHtmlDocumentWithSession(SteamStoreURL, request, data).ConfigureAwait(false); + using WebBrowser.HtmlDocumentResponse? response = await UrlPostToHtmlDocumentWithSession(SteamStoreURL, request, data: data).ConfigureAwait(false); return response?.Content?.SelectSingleNode("//div[@class='add_free_content_success_area']") != null; } @@ -1270,7 +1270,7 @@ namespace ArchiSteamFarm { { "Privacy", JsonConvert.SerializeObject(userPrivacy.Settings) } }; - WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data: data).ConfigureAwait(false); if (response?.Content == null) { return false; @@ -1295,7 +1295,7 @@ namespace ArchiSteamFarm { // Extra entry for sessionID Dictionary data = new Dictionary(2, StringComparer.Ordinal) { { "appid_to_clear_from_queue", appID.ToString() } }; - return await UrlPostWithSession(SteamStoreURL, request, data).ConfigureAwait(false); + return await UrlPostWithSession(SteamStoreURL, request, data: data).ConfigureAwait(false); } internal async Task DeclineTradeOffer(ulong tradeID) { @@ -1352,7 +1352,7 @@ namespace ArchiSteamFarm { // Extra entry for sessionID Dictionary data = new Dictionary(2, StringComparer.Ordinal) { { "queuetype", "0" } }; - WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamStoreURL, request, data).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamStoreURL, request, data: data).ConfigureAwait(false); return response?.Content?.Queue; } @@ -1928,7 +1928,7 @@ namespace ArchiSteamFarm { data.Add(new KeyValuePair("ck[]", confirmation.Key.ToString())); } - WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data: data).ConfigureAwait(false); return response?.Content?.Success; } @@ -2063,7 +2063,7 @@ namespace ArchiSteamFarm { // Extra entry for sessionID Dictionary data = new Dictionary(2, StringComparer.Ordinal) { { "action", "join" } }; - return await UrlPostWithSession(SteamCommunityURL, request, data, session: ESession.CamelCase).ConfigureAwait(false); + return await UrlPostWithSession(SteamCommunityURL, request, data: data, session: ESession.CamelCase).ConfigureAwait(false); } internal async Task MarkInventory() { @@ -2136,7 +2136,7 @@ namespace ArchiSteamFarm { // Extra entry for sessionID Dictionary data = new Dictionary(2, StringComparer.Ordinal) { { "wallet_code", key } }; - WebBrowser.ObjectResponse? responseValidateCode = await UrlPostToJsonObjectWithSession(SteamStoreURL, requestValidateCode, data).ConfigureAwait(false); + WebBrowser.ObjectResponse? responseValidateCode = await UrlPostToJsonObjectWithSession(SteamStoreURL, requestValidateCode, data: data).ConfigureAwait(false); if (responseValidateCode?.Content == null) { return null; @@ -2155,7 +2155,7 @@ namespace ArchiSteamFarm { if (responseValidateCode.Content.WalletCurrencyCode != responseValidateCode.Content.KeyDetails.CurrencyCode) { const string requestCheckFunds = "/account/createwalletandcheckfunds"; - WebBrowser.ObjectResponse? responseCheckFunds = await UrlPostToJsonObjectWithSession(SteamStoreURL, requestCheckFunds, data).ConfigureAwait(false); + WebBrowser.ObjectResponse? responseCheckFunds = await UrlPostToJsonObjectWithSession(SteamStoreURL, requestCheckFunds, data: data).ConfigureAwait(false); if (responseCheckFunds?.Content == null) { return null; @@ -2168,7 +2168,7 @@ namespace ArchiSteamFarm { const string requestConfirmRedeem = "/account/confirmredeemwalletcode"; - WebBrowser.ObjectResponse? responseConfirmRedeem = await UrlPostToJsonObjectWithSession(SteamStoreURL, requestConfirmRedeem, data).ConfigureAwait(false); + WebBrowser.ObjectResponse? responseConfirmRedeem = await UrlPostToJsonObjectWithSession(SteamStoreURL, requestConfirmRedeem, data: data).ConfigureAwait(false); if (responseConfirmRedeem?.Content == null) { return null; @@ -2199,7 +2199,7 @@ namespace ArchiSteamFarm { { "communityitemid", itemID.ToString() } }; - WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data).ConfigureAwait(false); + WebBrowser.ObjectResponse? response = await UrlPostToJsonObjectWithSession(SteamCommunityURL, request, data: data).ConfigureAwait(false); return response?.Content?.Result == EResult.OK; } @@ -2464,7 +2464,7 @@ namespace ArchiSteamFarm { { "Submit", "Register" } }; - return await UrlPostWithSession(SteamCommunityURL, request, data).ConfigureAwait(false); + return await UrlPostWithSession(SteamCommunityURL, request, data: data).ConfigureAwait(false); } private async Task<(bool Success, string? Result)> ResolveApiKey() { @@ -2565,7 +2565,7 @@ namespace ArchiSteamFarm { }; // This request doesn't go through UrlPostRetryWithSession as we have no access to session refresh capability (this is in fact session initialization) - WebBrowser.BasicResponse? response = await WebLimitRequest(serviceURL, async () => await WebBrowser.UrlPost(serviceURL + request, data, serviceURL).ConfigureAwait(false)).ConfigureAwait(false); + WebBrowser.BasicResponse? response = await WebLimitRequest(serviceURL, async () => await WebBrowser.UrlPost(serviceURL + request, data: data, referer: serviceURL).ConfigureAwait(false)).ConfigureAwait(false); if ((response == null) || IsSessionExpiredUri(response.FinalUri)) { // There is no session refresh capability at this stage diff --git a/ArchiSteamFarm/Statistics.cs b/ArchiSteamFarm/Statistics.cs index cb1f480cc..e79779cb6 100644 --- a/ArchiSteamFarm/Statistics.cs +++ b/ArchiSteamFarm/Statistics.cs @@ -102,7 +102,7 @@ namespace ArchiSteamFarm { { "SteamID", Bot.SteamID.ToString() } }; - WebBrowser.BasicResponse? response = await Bot.ArchiWebHandler.WebBrowser.UrlPost(request, data, requestOptions: WebBrowser.ERequestOptions.ReturnClientErrors).ConfigureAwait(false); + WebBrowser.BasicResponse? response = await Bot.ArchiWebHandler.WebBrowser.UrlPost(request, data: data, requestOptions: WebBrowser.ERequestOptions.ReturnClientErrors).ConfigureAwait(false); if (response == null) { return; @@ -218,7 +218,7 @@ namespace ArchiSteamFarm { { "TradeToken", tradeToken! } }; - WebBrowser.BasicResponse? response = await Bot.ArchiWebHandler.WebBrowser.UrlPost(request, data, requestOptions: WebBrowser.ERequestOptions.ReturnClientErrors).ConfigureAwait(false); + WebBrowser.BasicResponse? response = await Bot.ArchiWebHandler.WebBrowser.UrlPost(request, data: data, requestOptions: WebBrowser.ERequestOptions.ReturnClientErrors).ConfigureAwait(false); if (response == null) { return; diff --git a/ArchiSteamFarm/Utilities.cs b/ArchiSteamFarm/Utilities.cs index d0403ebee..e1f7041f4 100644 --- a/ArchiSteamFarm/Utilities.cs +++ b/ArchiSteamFarm/Utilities.cs @@ -61,6 +61,21 @@ namespace ArchiSteamFarm { return args[^1]; } + [PublicAPI] + public static string? GetCookieValue(this CookieContainer cookieContainer, string url, string name) { + if ((cookieContainer == null) || string.IsNullOrEmpty(url) || string.IsNullOrEmpty(name)) { + throw new ArgumentNullException(nameof(cookieContainer) + " || " + nameof(url) + " || " + nameof(name)); + } + + CookieCollection cookies = cookieContainer.GetCookies(new Uri(url)); + +#if NETFRAMEWORK + return cookies.Count > 0 ? (from Cookie cookie in cookies where cookie.Name == name select cookie.Value).FirstOrDefault() : null; +#else + return cookies.Count > 0 ? cookies.FirstOrDefault(cookie => cookie.Name == name)?.Value : null; +#endif + } + [PublicAPI] public static uint GetUnixTime() => (uint) DateTimeOffset.UtcNow.ToUnixTimeSeconds(); @@ -265,16 +280,6 @@ namespace ArchiSteamFarm { } } - internal static string? GetCookieValue(this CookieContainer cookieContainer, string url, string name) { - if ((cookieContainer == null) || string.IsNullOrEmpty(url) || string.IsNullOrEmpty(name)) { - throw new ArgumentNullException(nameof(cookieContainer) + " || " + nameof(url) + " || " + nameof(name)); - } - - CookieCollection cookies = cookieContainer.GetCookies(new Uri(url)); - - return cookies.Count > 0 ? (from Cookie cookie in cookies where cookie.Name.Equals(name) select cookie.Value).FirstOrDefault() : null; - } - internal static bool RelativeDirectoryStartsWith(string directory, params string[] prefixes) { if (string.IsNullOrEmpty(directory) || (prefixes == null) || (prefixes.Length == 0)) { throw new ArgumentNullException(nameof(directory) + " || " + nameof(prefixes)); diff --git a/ArchiSteamFarm/WebBrowser.cs b/ArchiSteamFarm/WebBrowser.cs index 4189c81db..d5231820c 100644 --- a/ArchiSteamFarm/WebBrowser.cs +++ b/ArchiSteamFarm/WebBrowser.cs @@ -46,9 +46,10 @@ namespace ArchiSteamFarm { private const byte MaxIdleTime = 15; // Defines in seconds, how long socket is allowed to stay in CLOSE_WAIT state after there are no connections to it [PublicAPI] - public TimeSpan Timeout => HttpClient.Timeout; + public readonly CookieContainer CookieContainer = new CookieContainer(); - internal readonly CookieContainer CookieContainer = new CookieContainer(); + [PublicAPI] + public TimeSpan Timeout => HttpClient.Timeout; private readonly ArchiLogger ArchiLogger; private readonly HttpClient HttpClient; @@ -107,7 +108,7 @@ namespace ArchiSteamFarm { } [PublicAPI] - public async Task UrlGetToHtmlDocument(string request, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { + public async Task UrlGetToHtmlDocument(string request, IReadOnlyCollection>? headers = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -115,7 +116,7 @@ namespace ArchiSteamFarm { HtmlDocumentResponse? result = null; for (byte i = 0; i < maxTries; i++) { - await using StreamResponse? response = await UrlGetToStream(request, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); + await using StreamResponse? response = await UrlGetToStream(request, headers, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); if (response?.StatusCode.IsClientErrorCode() == true) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { @@ -157,7 +158,7 @@ namespace ArchiSteamFarm { } [PublicAPI] - public async Task?> UrlGetToJsonObject(string request, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { + public async Task?> UrlGetToJsonObject(string request, IReadOnlyCollection>? headers = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -165,7 +166,7 @@ namespace ArchiSteamFarm { ObjectResponse? result = null; for (byte i = 0; i < maxTries; i++) { - await using StreamResponse? response = await UrlGetToStream(request, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); + await using StreamResponse? response = await UrlGetToStream(request, headers, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); if (response?.StatusCode.IsClientErrorCode() == true) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { @@ -219,7 +220,7 @@ namespace ArchiSteamFarm { } [PublicAPI] - public async Task UrlGetToXmlDocument(string request, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { + public async Task UrlGetToXmlDocument(string request, IReadOnlyCollection>? headers = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -227,7 +228,7 @@ namespace ArchiSteamFarm { XmlDocumentResponse? result = null; for (byte i = 0; i < maxTries; i++) { - await using StreamResponse? response = await UrlGetToStream(request, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); + await using StreamResponse? response = await UrlGetToStream(request, headers, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); if (response?.StatusCode.IsClientErrorCode() == true) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { @@ -271,7 +272,7 @@ namespace ArchiSteamFarm { } [PublicAPI] - public async Task UrlHead(string request, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { + public async Task UrlHead(string request, IReadOnlyCollection>? headers = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -279,7 +280,7 @@ namespace ArchiSteamFarm { BasicResponse? result = null; for (byte i = 0; i < maxTries; i++) { - using HttpResponseMessage? response = await InternalHead(request, referer).ConfigureAwait(false); + using HttpResponseMessage? response = await InternalHead(request, headers, referer).ConfigureAwait(false); if (response == null) { continue; @@ -313,7 +314,7 @@ namespace ArchiSteamFarm { } [PublicAPI] - public async Task UrlPost(string request, T? data = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { + public async Task UrlPost(string request, IReadOnlyCollection>? headers = null, T? data = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -321,7 +322,7 @@ namespace ArchiSteamFarm { BasicResponse? result = null; for (byte i = 0; i < maxTries; i++) { - using HttpResponseMessage? response = await InternalPost(request, data, referer).ConfigureAwait(false); + using HttpResponseMessage? response = await InternalPost(request, headers, data, referer).ConfigureAwait(false); if (response == null) { continue; @@ -355,7 +356,7 @@ namespace ArchiSteamFarm { } [PublicAPI] - public async Task UrlPostToHtmlDocument(string request, T? data = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { + public async Task UrlPostToHtmlDocument(string request, IReadOnlyCollection>? headers = null, T? data = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -363,7 +364,7 @@ namespace ArchiSteamFarm { HtmlDocumentResponse? result = null; for (byte i = 0; i < maxTries; i++) { - await using StreamResponse? response = await UrlPostToStream(request, data, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); + await using StreamResponse? response = await UrlPostToStream(request, headers, data, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); if (response?.StatusCode.IsClientErrorCode() == true) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { @@ -405,7 +406,7 @@ namespace ArchiSteamFarm { } [PublicAPI] - 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 { + public async Task?> UrlPostToJsonObject(string request, IReadOnlyCollection>? headers = null, 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)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -413,7 +414,7 @@ namespace ArchiSteamFarm { 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); + await using StreamResponse? response = await UrlPostToStream(request, headers, data, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); if (response?.StatusCode.IsClientErrorCode() == true) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { @@ -482,7 +483,7 @@ namespace ArchiSteamFarm { } } - internal async Task UrlGetToBinary(string request, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries, IProgress? progressReporter = null) { + internal async Task UrlGetToBinary(string request, IReadOnlyCollection>? headers = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries, IProgress? progressReporter = null) { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -490,7 +491,7 @@ namespace ArchiSteamFarm { BinaryResponse? result = null; for (byte i = 0; i < maxTries; i++) { - await using StreamResponse? response = await UrlGetToStream(request, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); + await using StreamResponse? response = await UrlGetToStream(request, headers, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false); if (response?.StatusCode.IsClientErrorCode() == true) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { @@ -568,7 +569,7 @@ namespace ArchiSteamFarm { return result; } - internal async Task UrlGetToString(string request, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { + internal async Task UrlGetToString(string request, IReadOnlyCollection>? headers = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -576,7 +577,7 @@ namespace ArchiSteamFarm { StringResponse? result = null; for (byte i = 0; i < maxTries; i++) { - using HttpResponseMessage? response = await InternalGet(request, referer).ConfigureAwait(false); + using HttpResponseMessage? response = await InternalGet(request, headers, referer).ConfigureAwait(false); if (response?.StatusCode.IsClientErrorCode() == true) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { @@ -609,31 +610,31 @@ namespace ArchiSteamFarm { return result; } - private async Task InternalGet(string request, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) { + private async Task InternalGet(string request, IReadOnlyCollection>? headers = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) { if (string.IsNullOrEmpty(request)) { throw new ArgumentNullException(nameof(request)); } - return await InternalRequest(new Uri(request), HttpMethod.Get, null, referer, requestOptions, httpCompletionOption).ConfigureAwait(false); + return await InternalRequest(new Uri(request), HttpMethod.Get, headers, null, referer, requestOptions, httpCompletionOption).ConfigureAwait(false); } - private async Task InternalHead(string request, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) { + private async Task InternalHead(string request, IReadOnlyCollection>? headers = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) { if (string.IsNullOrEmpty(request)) { throw new ArgumentNullException(nameof(request)); } - return await InternalRequest(new Uri(request), HttpMethod.Head, null, referer, requestOptions, httpCompletionOption).ConfigureAwait(false); + return await InternalRequest(new Uri(request), HttpMethod.Head, headers, null, referer, requestOptions, httpCompletionOption).ConfigureAwait(false); } - private async Task InternalPost(string request, T? data = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) where T : class { + private async Task InternalPost(string request, IReadOnlyCollection>? headers = null, T? data = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) where T : class { if (string.IsNullOrEmpty(request)) { throw new ArgumentNullException(nameof(request)); } - return await InternalRequest(new Uri(request), HttpMethod.Post, data, referer, requestOptions, httpCompletionOption).ConfigureAwait(false); + return await InternalRequest(new Uri(request), HttpMethod.Post, headers, data, referer, requestOptions, httpCompletionOption).ConfigureAwait(false); } - private async Task InternalRequest(Uri requestUri, HttpMethod httpMethod, T? data = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte maxRedirections = MaxTries) where T : class { + private async Task InternalRequest(Uri requestUri, HttpMethod httpMethod, IReadOnlyCollection>? headers = null, T? data = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte maxRedirections = MaxTries) where T : class { if ((requestUri == null) || (httpMethod == null)) { throw new ArgumentNullException(nameof(requestUri) + " || " + nameof(httpMethod)); } @@ -645,6 +646,12 @@ namespace ArchiSteamFarm { request.Version = HttpClient.DefaultRequestVersion; #endif + if (headers != null) { + foreach ((string header, string value) in headers) { + request.Headers.Add(header, value); + } + } + if (data != null) { switch (data) { case HttpContent content: @@ -751,7 +758,7 @@ namespace ArchiSteamFarm { redirectUri = new UriBuilder(redirectUri) { Fragment = requestUri.Fragment }.Uri; } - return await InternalRequest(redirectUri, httpMethod, data, referer, requestOptions, httpCompletionOption, --maxRedirections).ConfigureAwait(false); + return await InternalRequest(redirectUri, httpMethod, headers, data, referer, requestOptions, httpCompletionOption, --maxRedirections).ConfigureAwait(false); } if (!Debugging.IsUserDebugging) { @@ -781,7 +788,7 @@ namespace ArchiSteamFarm { } } - private async Task UrlGetToStream(string request, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { + private async Task UrlGetToStream(string request, IReadOnlyCollection>? headers = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -789,7 +796,7 @@ namespace ArchiSteamFarm { StreamResponse? result = null; for (byte i = 0; i < maxTries; i++) { - HttpResponseMessage? response = await InternalGet(request, referer, requestOptions, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + HttpResponseMessage? response = await InternalGet(request, headers, referer, requestOptions, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); if (response?.StatusCode.IsClientErrorCode() == true) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) { @@ -822,7 +829,7 @@ namespace ArchiSteamFarm { return result; } - private async Task UrlPostToStream(string request, T? data = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { + private async Task UrlPostToStream(string request, IReadOnlyCollection>? headers = null, T? data = null, string? referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class { if (string.IsNullOrEmpty(request) || (maxTries == 0)) { throw new ArgumentNullException(nameof(request) + " || " + nameof(maxTries)); } @@ -830,7 +837,7 @@ namespace ArchiSteamFarm { StreamResponse? result = null; for (byte i = 0; i < maxTries; i++) { - HttpResponseMessage? response = await InternalPost(request, data, referer, requestOptions, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + HttpResponseMessage? response = await InternalPost(request, headers, data, referer, requestOptions, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); if (response?.StatusCode.IsClientErrorCode() == true) { if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) {