example - post c# asp net
¿Cómo puedo modificar una solicitud POST usando un IHttpModule personalizado y un filtro HttpRequest? (3)
La respuesta a la segunda parte de esta pregunta es devolver el tamaño del contenido modificado, no el tamaño del flujo original. ¡Mirad!
// return bytesRead;
return newByteCountLength;
Visión de conjunto
Deseo poder modificar los parámetros de solicitud y el contenido a servicios web de terceros (ArcGIS Server). Esto se usará para crear una capa de seguridad que existe entre cualquier aplicación cliente y la aplicación del servidor.
Creo que encontré una solución, pero actualmente estoy teniendo algunas dificultades en la implementación.
Posible solución: modificar solicitud con un filtro de solicitud personalizado
Para la solución, implementé un filtro de solicitud personalizado basado en la muestra que se muestra en MSDN . He ''mejorado'' el código para poder buscar y reemplazar el contenido necesario usando expresiones regulares. Esto involucra:
- Convirtiendo el contenido (almacenado en una matriz de bytes) en una cadena.
- Buscando la cadena y realizando las modificaciones necesarias.
- Convirtiendo la cadena modificada en una matriz de bytes y escribiéndola en el buffer.
Un ejemplo se muestra a continuación:
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;
}
Esto parece funcionar bien siempre que la longitud del contenido modificado no sea diferente de la longitud del contenido original. Por ejemplo, si reemplazo un 1 por un 2, todo funciona. Sin embargo, si reemplazo un 1 por un 10 (aumentando así el tamaño del mensaje en 1), entonces recibo un error de ArcGIS Server de que el formato no es compatible.
Esto ha traído dos preocupaciones a mi atención:
- La implementación actual no maneja las solicitudes fragmentadas. Es decir, si la solicitud sie es lo suficientemente grande, se puede llamar a Read varias veces para una única solicitud. ¿Cómo se debe manejar la fragmentación en este escenario?
- ¿Cuál es la causa raíz del mensaje de error? ¿El problema relacionado con la duración del contenido es diferente de la duración de la secuencia? ¿Cómo modifico correctamente el contenido para que cambiar su duración no sea un problema?
¿Alguna idea?
Esta pregunta y su respuesta fueron realmente útiles para mí, sin embargo, la respuesta no es toda la historia si está tratando de insertar grandes cantidades de datos en la transmisión:
Devolver el tamaño de contenido modificado solo es válido si los datos que está insertando en la secuencia no tomarán el número de bytes leídos en el búfer sobre el valor de count
. Si intenta insertar demasiados datos, encontrará que el objeto del buffer
no es lo suficientemente grande como para contener los datos que está insertando, o que al escribir más de un count
bytes en el búfer, está sobrescribiendo algunos datos al final del búfer que estaba destinado a ser dejado solo.
Si necesita insertar más datos de los que el objeto de buffer
actual puede acomodar, deberá almacenar los datos en una matriz de bytes separada y copiarlos en fragmentos a stream.read
se realicen las llamadas a stream.read
.
Como afirma Chris McKeown, esta no es realmente la mejor técnica para filtrar a menos que prometa no modificar el tamaño de los datos. Para completar esta respuesta, he publicado un proyecto de muestra que demuestra cómo gestionar el filtrado de la solicitud y la respuesta utilizando la técnica de almacenamiento intermedio si está interesado.
https://github.com/snives/HttpModuleRewrite
También para preguntas relacionadas con la solución de problemas HttpModules para filtrar esta publicación también fue muy útil. ¿Es posible modificar el contenido de HttpRequest POST en un HttpModule de IIS?