Работайте по HTTP-запросу, как он получен в IIS в C # - PullRequest
1 голос
/ 08 августа 2009

У меня есть необходимость переопределить получение необработанного HTTP-запроса, так как он передается на сервер IIS. Я хочу знать, возможно ли это.

У нас есть клиент, который отправляет огромные вызовы веб-службы (десятки Мб), и мы хотим начать действовать на части этих вызовов по мере их поступления (чтобы ускорить общее время выполнения вызова веб-службы). ).

В настоящее время, используя обычные методы веб-службы, код нашего приложения передается вызову веб-службы после его полного получения.

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

Я создал обработчик, который реализует IHttpHandler, но похоже, что на этом этапе в конвейере процесса IIS полностью получил запрос (что не дает нам никакого преимущества по сравнению с нашей текущей моделью). То есть я могу читать InputStream напрямую, но полный запрос уже передан по проводной связи, прежде чем я получу доступ к этому потоку.

Я думаю, что ответ заключается в том, что мне нужно кодировать фильтр ISAPI, чтобы добиться этого, но у меня нет навыков, чтобы делать это на C / C ++. Кто-нибудь знает, есть ли другой способ сделать это без маршрута фильтра ISAPI?

Приемлемым ответом может быть: «Вы должны сделать это как и ISAPI фильтр, чтобы сделать это в C #, проверьте этот документ».

Ответы [ 3 ]

1 голос
/ 08 августа 2009

Вы можете использовать пользовательский HttpModule для подключения практически любой части конвейера IIS. Они работают в IIS 6 (под ASP.NET) и являются основным механизмом расширения в IIS 7.

0 голосов
/ 02 апреля 2018

Короткая версия

Решением является использование HttpRequest.GetBufferlessInputStream .

Длинная версия

Проблема в том, что если вы попытаетесь использовать:

вы должны подождать, пока весь запрос не будет получен, прежде чем он вернет объект Stream . В противоположность этому, метод GetBufferlessInputStream немедленно возвращает объект Stream . Вы можете использовать метод, чтобы начать обработку тела объекта до того, как будет получено полное содержимое тела.

Этот метод может быть полезен, если запрос загружает большой файл, и вы хотите начать доступ к содержимому файла до завершения загрузки. Однако этот метод следует использовать только для сценариев, в которых вы хотите взять на себя всю обработку тела объекта. Это означает, что вы не можете использовать этот метод со страницы .aspx, потому что к моменту запуска страницы .aspx тело сущности уже прочитано.

Единственный недостаток, и это огромный недостаток, это то, что вы сейчас читаете Request.InputStream . Это означает, что вам придется самостоятельно обрабатывать MIME-коды и кодировку base64.

Пример (непроверенный) код

UploadFile.ashx

public class Default : IHttpHandler 
{
   public void ProcessRequest (HttpContext context) 
   {
      var request = context.Request;

      var stm = request.GetBufferlessInputStream(true); //true --> disable web.config limits on request size
      if (!stm.CanRead) 
         throw new Exception("Request input stream is not readable");

      //Setup the buffer we'll be shuffling stream data into
      int bufferLength = 16 * 8040; //use a multiple of 8040 bytes, because SQL Server uses pages of 8040 bytes. And because i'm saving it into SQL Server.
      byte[] buffer = new Byte[bufferLength];

      int bytesRead;
      bytesRead = stm.Read(buffer, 0, buffer.Length);
      while (bytesRead > 0)
      {
         SavePiece(buffer, bytesRead); //whatever you want to do with it
         bytesRead = stm.Read(buffer, 0, buffer.Length);
      }
   }

   private void SavePiece(byte[] buffer, int bufferLength)
   {
      //It's all going to be multipart mime encoded nonsense.
      //Good luck!
   }

   public bool IsReusable { get { return false;}
}

Чтение бонусов

0 голосов
/ 08 августа 2009

Существует множество примеров построения фильтров ISAPI, но ни одного в C #. Я уверен, что это возможно, но не практично и не без множества грязных уловок.

Ваши инвестиции в C # будут хорошо сохраняться в C ++, дайте мне знать, если вам нужна помощь. Между прочим, я рекомендую вам инвестировать в мое стандартное трио - старайтесь поддерживать хорошие знания C #, C ++ и Java.

Я также рекомендую вам рассмотреть модули Apache, они могут предложить более общую гибкость. Вот что я бы сделал:

  1. размещайте эти веб-службы вне IIS - вы никогда не узнаете, когда IIS укусит вас, перезапустив приложение.
  2. Используйте службы WCF, размещайте их в службах Windows, используйте перенаправление для маршрутизации службы в службу WCF.
  3. Подумайте над написанием необработанного приложения для сокетов. В этом случае будет реализован минимальный протокол WS: * для вашего сервиса, и он будет действовать как прокси для реального сервиса. Когда прокси-сервер обнаруживает, что входящее сообщение превышает пороговое значение, он начинает анализировать сообщение, чтобы извлечь то, что он мог обработать сразу.

Результатом будет стандартный WCF (через прокси) для небольших сообщений и нестандартная обработка для всего остального.

Дайте мне знать, если я смогу помочь вам построить его - это то, что мне нравится делать ...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...