1

Имеется код связи с определенным сайтом. Через него я получаю данные, которые в процессе успеваю поменять или доработать, а после эти измененные данные мною отправляются вновь на сайт. Все бы ничего, но сам процесс работы, его желательно ускорить, оптимизировать. И чтоб подобное сделать, мне нужно как-то реализовать компрессии gzip для POST метода и декомпрессии gzip для GET метода:

namespace SoftWARE
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net;
    using System.Runtime.InteropServices;
    using System.Configuration;
    using System.Text;
public class Connecter
{
    public CookieContainer cookies = new CookieContainer();
    public string OriginUrl = System.Configuration.ConfigurationManager.AppSettings["OriginUrl"];

    public HttpWebRequest GetNewRequest(string targetUrl, CookieContainer SessionCookieContainer)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(targetUrl);
        request.CookieContainer = SessionCookieContainer;
        request.AllowAutoRedirect = false;
        return request;
    }

    public HttpWebResponse MakeRequest(HttpWebRequest request, CookieContainer SessionCookieContainer, Dictionary<string, string> parameters = null, int TypeRequest = 0)
    {
        request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 OPR/32.0.1948.25Accept: */*";
        request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        request.Proxy = new WebProxy();
        System.Net.ServicePointManager.Expect100Continue = false;
        System.Net.ServicePointManager.UseNagleAlgorithm = false;
        request.ServicePoint.ConnectionLimit = 100;
        ServicePointManager.FindServicePoint(new Uri(this.OriginUrl));
        request.KeepAlive = true;
        request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
        request.Headers["Origin"] = this.OriginUrl;
        if (TypeRequest == 1)
        {
            request.Headers["X-Requested-With"] = "XMLHttpRequest";
        }
        if (TypeRequest == 2)
        {
            request.Headers["Upgrade-Insecure-Requests"] = "1";
        }
        request.CookieContainer = SessionCookieContainer;
        request.AllowAutoRedirect = false;
        if (parameters != null)
        {
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            string s = "";
            foreach (KeyValuePair<string, string> pair in parameters)
            {
                if (s.Length == 0)
                {
                    s += $"{pair.Key}={pair.Value}";
                }
                else
                {
                    s += $"&{pair.Key}={pair.Value}";
                }
            }
            byte[] bytes = Encoding.UTF8.GetBytes(s);
            using (Stream stream = request.GetRequestStream())
            {
                stream.Write(bytes, 0, bytes.Length);
            }
        }
        else
        {
            request.Method = "GET";
        }
        HttpWebResponse response = request.GetResponse() as HttpWebResponse;
        SessionCookieContainer.Add(response.Cookies);
        while (response.StatusCode == HttpStatusCode.Found)
        {
            response.Close();
            request = this.GetNewRequest(response.Headers["Location"], SessionCookieContainer);
            response = (HttpWebResponse)request.GetResponse();
            SessionCookieContainer.Add(response.Cookies);
        }
        return response;
    }
}

}

1 Answers1

0

HttpWebRequest устарел, используйте HttpClient.

Документация:

Важно! Мы не рекомендуем использовать HttpWebRequest для новой разработки. Вместо этого используйте System.Net.Http.HttpClient класс.

Вот, переписал ваш код под HttpClient, старался максимально сохранить вашу логику.

public class Connecter
{
    private readonly HttpClient _client;
    public string OriginUrl { get; }
    public CookieContainer Cookies { get; }
public Connecter(CookieContainer cookies = null)
{
    OriginUrl = ConfigurationManager.AppSettings["OriginUrl"];
    HttpClientHandler handler = new HttpClientHandler()
    { 
        AutomaticDecompression = DecompressionMethods.All // включение поддержки компрессии Content-Encoding: gzip, defalte, br - добавлять заголовок вручную не нужно
        // здесь можно задать еще кучу всяких парамемтров подключения
    }; 
    if (cookies != null)
        handler.CookieContainer = cookies;
    Cookies = handler.CookieContainer;
    _client = new HttpClient(handler)
    {
        BaseAddress = new Uri(OriginUrl),
        //DefaultRequestVersion = HttpVersion.Version20 // поддержка HTTP/2 доступна в .NET Core 3.1, .NET 5 и новее
    };
    _client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 OPR/32.0.1948.25");
    _client.DefaultRequestHeaders.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
}

public Task<string> GetAsync(string url)
{
    return _client.GetStringAsync(url); 
}

public async Task<string> PostFormAsync(string url, Dictionary<string, string> parameters, int TypeRequest = 0)
{
    using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url)
    { 
        Content = new FormUrlEncodedContent(parameters) 
    };
    request.Headers.Add("Origin", OriginUrl);
    if (TypeRequest == 1)
    {
        request.Headers.Add("X-Requested-With", "XMLHttpRequest");
    }
    if (TypeRequest == 2)
    {
        request.Headers.Add("Upgrade-Insecure-Requests", "1");
    }
    using HttpResponseMessage response = await _client.SendAsync(request);
    return await response.Content.ReadAsStringAsync();
}

}

Смысл включения компрессии в том, что вы сообщаете серверу, что поддерживаете декомпрессию. Сервер если пожелает, сожмет свой ответ. HttpClient распакует ответ автоматически.

С куками HttpClient работает как браузер, то есть каждый последующий запрос учитывает куки добавленные сервером в предыдущем запросе. То есть за пределами этого класса вы можете сохранять и загружать куки, например при запуске и завершении приложения.

Лишние настройки протокола я выкинул, так как они либо не на что не влияют, либо совпадают с настройками по умолчанию.

Использовать это вот так.

К примеру, есть ссылка https://my.api/post_method и https://my.api/get_method. В этом случе OriginUrl должен быть https://my.api/, а запросы отправлять нужно вот так.

string getResponseText = await connecter.GetAsync("get_method");
string postResponseText = await connecter.PostFormAsync("post_method", data, 1);

Еще у вас была синтаксическая ошибка в UserAgent, я исправил. Ну и само собой эта конструкция будет работать быстрее, а в .NET Core/.NET 5 - вообще быстро, потому что там используется новый HTTP движок SocketsHttpHandler, в .NET Framework 4.x используется старый движок, поэтому ощутимого прироста скорости может не произойти.

aepot
  • 49,560