Прочитайте первые n символов HttpContent

Я хочу регистрировать информацию об ответах HttpRequestMessage в программе Visual C# Web API. Я хочу использовать обработчик сообщений (наследование от DelegatingHandler), как это:

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
{
    // log request.Method & request.RequestUri
    var result = await base.SendAsync(request, cancellationToken);
    // log first 100 chars of result.Content
    return result
}

Проблема в том, что result.Content иногда будет огромным, поэтому я хочу ограничить его печатью только первых N символов (примерно 50).

Что я пробовал:

  • Копирование всего этого в строку с toString() и используя SubString, Это именно то, что я хочу, но, кажется, расточительно читать огромные строки в памяти, а затем использовать только первые несколько символов - я чувствую, что должен быть лучший способ.
  • Различные решения со всего Интернета, которые читают символы, но удаляют их из потока. Мне нужно отправить полный поток обратно как есть.

1 ответ

При этом вы можете скопировать необходимую информацию из потока и передать ответ туда, куда он идет.

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) {
    // log request.Method & request.RequestUri
    var response = await base.SendAsync(request, cancellationToken);
    // log first 100 chars of response.Content
    var N = 100;
    var first_100_Chars = await ReadFirstNCharsOfHttpContent(response.Content, N);

    return response;
}

private static async Task<string> ReadFirstNCharsOfHttpContent(HttpContent httpContent, int N = 100) {
    //get the content Stream
    var contentStream = await httpContent.ReadAsStreamAsync().ConfigureAwait(false);
    //How big is it
    var streamLength = contentStream.Length;
    // Get the size of the buffer to be read
    var bufferSize = (int)(streamLength > N ? N : (N > streamLength ? streamLength : N));
    var ms = new System.IO.MemoryStream(bufferSize);
    //copy only the needed length
    await contentStream.CopyToAsync(ms, bufferSize);

    // The StreamReader will read from the current 
    // position of the MemoryStream which is currently 
    // set at the end of the data we just copied to it.

    // We need to set the position to 0 in order to read 
    // from the beginning.
    ms.Position = 0;
    //reset content position just to be safe.
    contentStream.Position = 0;

    var sr = new System.IO.StreamReader(ms);
    var logString = sr.ReadToEnd();

    return logString;
}
Другие вопросы по тегам