Как я могу изменить POST-запрос, используя собственный IHttpModule и фильтр HttpRequest? - PullRequest
4 голосов
/ 13 июля 2010

Обзор

Я хочу иметь возможность изменять параметры запроса и контент для сторонних веб-сервисов (ArcGIS Server). Это будет использоваться для создания уровня безопасности, который существует между любым клиентским приложением и серверным приложением.

Я думаю, что нашел решение, но в настоящее время у меня есть некоторые трудности в реализации.

Потенциальное решение: изменить запрос с помощью пользовательского фильтра запросов

Для решения я реализовал пользовательский фильтр запросов, основанный на образце , показанном в MSDN . Я «усовершенствовал» код, чтобы я мог искать и заменять необходимый контент с помощью регулярных выражений. Это включает в себя:

  1. Преобразование содержимого (хранящегося в байтовом массиве) в строку.
  2. Поиск строки и выполнение любых необходимых изменений.
  3. Преобразование измененной строки в байтовый массив и запись его в буфер.

Пример показан ниже:

public override int Read(byte[] buffer, int offset, int count)
{
    int bytesRead = _stream.Read(buffer, offset, count);

    string orgContent = Encoding.UTF8.GetString(buffer, offset, bytesRead);
    string orgContentDecoded = HttpUtility.UrlDecode(orgContent);

    string layersPattern = @"&layers=(show|hide|include|exclude):([0-9]+,?)+";
    Regex layersRegex = new Regex(layersPattern, RegexOptions.IgnoreCase);

    string[] permittedLayers = new string[] { "0" , "1" };
    string replacementLayers = "&layers=show:" + String.Join(",", permittedLayers);
    string newContentDecoded = layersRegex.Replace(orgContentDecoded, replacementLayers);

    string newContent =  newContentDecoded.Replace(",", "%2C").Replace(":", "%3A");

    byte[] newBuffer = Encoding.UTF8.GetBytes(newContent);
    int newByteCountLength = Encoding.UTF8.GetByteCount(newContent);

    Encoding.UTF8.GetBytes(newContent, 0, Encoding.UTF8.GetByteCount(newContent), buffer, 0);

    return bytesRead;
}

Кажется, это работает хорошо, если длина измененного контента не отличается от оригинальной длины контента. Например, если я заменяю 1 на 2, все работает. Однако, если я заменяю 1 на 10 (таким образом увеличивая размер сообщения на 1), я получаю сообщение об ошибке от ArcGIS Server, что формат не поддерживается.

Это привлекло мое внимание к двум проблемам:

  1. Текущая реализация не обрабатывает фрагментированные запросы. То есть, если запрос sie достаточно большой, Read может быть вызван несколько раз для одного запроса. Как следует обрабатывать фрагменты в этом сценарии?
  2. Что является основной причиной сообщения об ошибке? Проблема связана с длиной контента, отличной от длины потока? Как правильно изменить содержимое, чтобы изменение его длины не было проблемой?

Есть мысли?

Ответы [ 3 ]

4 голосов
/ 15 июля 2010

Ответом на вторую часть этого вопроса является возвращение измененного размера контента, а не размера исходного потока.Вот!

// return bytesRead;
return newByteCountLength;
2 голосов
/ 21 августа 2013

Этот вопрос и ваш ответ были действительно полезны для меня, однако, если вы пытаетесь вставить в поток большие объемы данных, ответ - не вся история:

Возврат только измененного размера контентадопустимо, если данные, которые вы вставляете в поток, не будут принимать количество прочитанных байтов в буфере сверх значения count.Если вы попытаетесь вставить слишком много данных, вы либо обнаружите, что объект buffer недостаточно велик для хранения данных, которые вы вставляете, либо что, записав в буфер более count байтов,Вы перезаписываете некоторые данные в конце буфера, который должен был быть оставлен в покое.

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

0 голосов
/ 24 февраля 2016

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

https://github.com/snives/HttpModuleRewrite

Также для вопросов, связанных с устранением неполадок HttpModules для фильтрации этого сообщения также было очень полезно Можно ли изменить содержимое HttpRequest POST в IIS HttpModule?

...