powered by simpleCommunicator - 2.0.36     © 2025 Programmizd 02
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / httpclient bytes recieved|sent
11 сообщений из 11, страница 1 из 1
httpclient bytes recieved|sent
    #40068342
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
возник вопрос как подсчитать это дело
вроде как бы просто сделать такое
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
		public static long GetSize(this HttpRequestMessage request)
		{
			var sizeReq = request.Content?.Headers.ContentLength ?? 0;
			var headerReq = request.Headers.ToString().Length;
			return sizeReq + headerReq;
		}

		public static long GetSize(this HttpResponseMessage responce)
		{
			if (responce == null) return 0;
			var sizeResp = responce.Content?.Headers.ContentLength ?? 0;
			var headerResp = responce.Headers.ToString().Length;
			return sizeResp + headerResp;
		}


но когда компрессия заголовки длины вырезаются. кто сталкивался с таким есть какое то адекватное решение?2 раза читать респонс?

причина простая.. метрики с ос имеют паразитные метрики всех служб + самого прометуса и все учитывается там, а хотелось бы понять что именно приложухой генериться
...
Рейтинг: 0 / 0
httpclient bytes recieved|sent
    #40068377
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На ум приходит кастомный middleware который перехватит запрос в нужный момент до компрессии.
...
Рейтинг: 0 / 0
httpclient bytes recieved|sent
    #40068391
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu
но когда компрессия заголовки длины вырезаются. кто сталкивался с таким есть какое то адекватное решение?2 раза читать респонс?


Можно сделать прокси-поток, который будет считать респонз :)
...
Рейтинг: 0 / 0
httpclient bytes recieved|sent
    #40068422
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
На ум приходит кастомный middleware который перехватит запрос в нужный момент до компрессии.

имеешь ввижу на сервере и дописывать в заголовки?
...
Рейтинг: 0 / 0
httpclient bytes recieved|sent
    #40068423
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt

Можно сделать прокси-поток, который будет считать респонз :)

хм а в какую точку тогда воткнуть?вот есть сервер и есть моя приложуха что шлет через httpclient
и эт будет как я понимаю 2 считывание ж
...
Рейтинг: 0 / 0
httpclient bytes recieved|sent
    #40068424
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu
имеешь ввижу на сервере и дописывать в заголовки?

Да, как-то так. Не уверен, правда, что после записи в body можно писать что-то в заголовки - под IIS было такое ограничение, сейчас не знаю - не было случая проверить.
...
Рейтинг: 0 / 0
httpclient bytes recieved|sent
    #40068460
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu
хм а в какую точку тогда воткнуть?вот есть сервер и есть моя приложуха что шлет через httpclient
и эт будет как я понимаю 2 считывание ж


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

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.WebSockets;
using System.Reflection;
using System.Security.Authentication.ExtendedProtection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;

namespace HttpClientSnifferExample
{
    class Program
    {
        static async Task Main(string[] args)
        {
            // DI просто для примера
            var services = new ServiceCollection();
            // настраиваем HTTP клиента
            services.AddHttpClient("test")
                // здесь добавляем наш супер-хендлер
                .AddHttpMessageHandler(() => new WrapperHandler())
                .ConfigureHttpClient(client =>
                {
                    client.BaseAddress = new Uri("https://postman-echo.com");
                });

            var serviceProvider = services.BuildServiceProvider();

            var factory = serviceProvider.GetRequiredService<IHttpClientFactory>();
            var client = factory.CreateClient("test");

            // выполняем тестовый запрос
            var response = await client.PostAsync("post", new StringContent("{\"test\": 123}", Encoding.UTF8, "application/json"));

            // получаем реальный размер запроса
            if (response.RequestMessage!.Options.TryGetValue(new HttpRequestOptionsKey<long>("RequestLength"),
                out var requestLength))
            {
                Console.WriteLine($"Real request length: {requestLength}");
            }

            // получаем реальный размер ответа (вообще он должен быть прочитан для начала)
            if (response.RequestMessage!.Options.TryGetValue(new HttpRequestOptionsKey<long>("ResponseLength"),
                out var responseLength))
            {
                Console.WriteLine($"Real response length: {responseLength}");
            }

            // просто посмотреть чё там
            var requestContent = await response.RequestMessage.Content.ReadAsStringAsync();
            var responseContent = await response.Content.ReadAsStringAsync();

            Console.WriteLine($"Request:\n{requestContent}\n\n");
            Console.WriteLine($"Response:\n{responseContent}\n\n");
        }
    }

    /// <summary>
    ///     Хендлер для обёртки содержимого запроса и ответа.
    /// </summary>
    public class WrapperHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            request.Content = new HttpContentWrapper(request.Content, request.Options, "RequestLength");
            var response = await base.SendAsync(request, cancellationToken);
            response.Content = new HttpContentWrapper(response.Content, request.Options, "ResponseLength");
            return response;
        }
    }

    /// <summary>
    ///     Обёртка для любого HttpContent, чтобы снифать содержимого и считать реальный размер.
    /// </summary>
    public class HttpContentWrapper : HttpContent
    {
        private readonly HttpContent _baseContent;
        private readonly HttpRequestOptions _options;
        private readonly string _optionsName;

        public HttpContentWrapper(HttpContent baseContent, HttpRequestOptions options, string optionsName)
        {
            _baseContent = baseContent;
            _options = options;
            _optionsName = optionsName;

            if (baseContent.Headers != null)
            {
                foreach (var (key, value) in baseContent.Headers)
                {
                    Headers.Add(key, value);
                }
            }
        }

        protected override async Task SerializeToStreamAsync(Stream stream, TransportContext? context)
        {
            var streamWrapper = new StreamLengthWrapper(stream);
            await _baseContent.CopyToAsync(streamWrapper, context);
            _options.Set(new HttpRequestOptionsKey<long>(_optionsName), streamWrapper.GetProcessedLength());
        }

        // ну это костыли конечно )) куда деваться
        protected override bool TryComputeLength(out long length)
        {
            var lengthParam = new object[] { null };
            var result = _baseContent.GetType().InvokeMember(nameof(TryComputeLength),
                BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, _baseContent, lengthParam);
            length = (long)lengthParam[0];
            return (bool)result!;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _baseContent.Dispose();
            }
        }
    }

    /// <summary>
    ///     Простейшая обёртка любого Stream, конкретно данная обёртка нужна для подсчёта прочитанного/записанного объёма данных.
    /// </summary>
    public class StreamLengthWrapper : Stream
    {
        private readonly Stream _baseStream;
        private long _processedLength;

        public StreamLengthWrapper(Stream baseStream)
        {
            _baseStream = baseStream;
            _processedLength = 0L;
        }

        public long GetProcessedLength() => _processedLength;

        public override void Flush()
        {
            _baseStream.Flush();
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            _processedLength += count;
            return _baseStream.Read(buffer, offset, count);
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException("Seek not supported.");
        }

        public override void SetLength(long value)
        {
            throw new NotSupportedException("SetLength not supported.");
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            _processedLength += count;
            _baseStream.Write(buffer, offset, count);
        }

        public override bool CanRead => _baseStream.CanRead;

        public override bool CanSeek => false;

        public override bool CanWrite => _baseStream.CanWrite;

        public override long Length => _baseStream.Length;

        public override long Position
        {
            get => _baseStream.Position;
            set => throw new NotSupportedException("Set Position not supported.");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _baseStream.Dispose();
            }
        }

        public override ValueTask DisposeAsync()
        {
            return _baseStream.DisposeAsync();
        }
    }
}
...
Рейтинг: 0 / 0
httpclient bytes recieved|sent
    #40068477
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu,

А, так тебе это на стороне клиента надо делать? Тогда у Хвоста самое правильное решение. Кастомные HttpHandler-ы как раз для таких вещей и предназначены. Меня просто выбор форума ASP.NET для темы сбил с толку.
...
Рейтинг: 0 / 0
httpclient bytes recieved|sent
    #40068484
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat ага видимо не правильно выразился что заставил тебя думать о другом)
hVostt спасибо попробую и да httpclient прям странно ограничивает
...
Рейтинг: 0 / 0
httpclient bytes recieved|sent
    #40068489
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
пс. я и сделал это на DelegatingHandler но потом увидел проблему что заголовки могут и вырезаться
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
public class MetricDelegatingHandler : DelegatingHandler
	{
		private readonly ILogger<MetricDelegatingHandler> _logger;
		private readonly IMetricService _metricService;
		public MetricDelegatingHandler(ILogger<MetricDelegatingHandler> logger, IMetricService metricService)
		{
			_logger = logger;
			_metricService = metricService;
		}
		protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
		{
			_metricService?.Http.BytesSent(request.GetSize());
			var response = await base.SendAsync(request, cancellationToken);
			_metricService?.Http.BytesRecieved(response.GetSize());
			return response;
		}
	}
...
Рейтинг: 0 / 0
httpclient bytes recieved|sent
    #40068502
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu
но потом увидел проблему что заголовки могут и вырезаться

Ну, если они вырезаются уже на сервере, то, очевидно, что на клиенте ты уже ничего с этим не поделаешь.
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / httpclient bytes recieved|sent
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]