Чтение тела 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)