Чтение тела HTTP-запроса в HttpModule

У меня есть.NET Core Web API, работающий в IIS. Я хочу добавить тело запроса в журнале IIS на POST. Поэтому в.NET Full Framework я создал библиотеку классов с одним классом, который реализует IHttpModule. Я должен использовать.NET Full Framework, потому что IHttpModule отсутствует в Core.

Моя проблема в том, что запрос InputStream может быть прочитан только один раз. Поэтому, когда я читаю его в своем коде, поток уже в его конце (и объект Stream был изменен с помощью), когда он попадает в мой Core API. Я перепробовал все, что мог придумать, и много искал.

Что не работает:

var bytes = new byte[request.InputStream.Length];
request.InputStream.Read(bytes, 0, bytes.Length);
request.InputStream.Position = 0;
var content = Encoding.UTF8.GetString(bytes);

Да, я получаю тело очень хорошо, но положение потока не сбрасывается. Сброс положения не помогает.

var reader = new StreamReader(HttpContext.Current.Request.InputStream, Encoding.UTF8, true, 1024, true);
HttpContext.Current.Request.InputStream.Position = 0;

Последний флаг должен указывать потоку, чтобы он оставался открытым, но вызов в ядро ​​все равно не выполняется.

context.HttpContext.Request.Body

Недоступно в стандартном.NET.

Тогда я попробовал это:

var s2 = new MemoryStream(request.TotalBytes);
HttpContext.Current.Request.InputStream.CopyTo(s2);

Все еще не удается. Даже этот небольшой код делает его неудачным:

var v = request.TotalBytes;

Мои мысли до сих пор

Глядя на исходный код потока, я вижу, что некоторые из его внутренних данных изменяются при чтении свойств, поэтому я думаю, что IIS проверяет, что сообщение не было подделано перед отправкой в ​​Kestrel. Может кто-нибудь пролить некоторый свет на это? Может быть, вы знаете другого сделать эту задачу?

Примечание: да, я могу вывести тело сообщения другими способами, используя другие модули IIS, но они не помещают его в стандартный журнал IIS, они создают свои собственные. Я уже использую журнал IIS в стек ELK, поэтому так будет проще.

1 ответ

немного поздно, но я тоже занимался этим несколько часов. Наконец получил решение, используя

      request.GetBufferedInputStream()

вместо

      request.InputStream

(.NET Framework 4.6)

Другие вопросы по тегам