¿Por qué “Content-Length: 0” en las solicitudes POST?

A veces, un cliente envía solicitudes POST con Content-Length: 0 al enviar un formulario (de 10 a más de 40 campos).

Lo probamos con diferentes navegadores y desde diferentes lugares, pero no pudimos reproducir el error. El cliente está utilizando Internet Explorer 7 y un proxy.

Les pedimos que permitieran que su administrador del sistema viera el problema desde su lado. Ejecutando algunas pruebas sin el proxy, etc.

Mientras tanto (medio año más tarde y todavía no hay respuesta), tengo curiosidad si alguien más sabe de problemas similares con una solicitud Content-Length: 0 . Tal vez desde dentro de una red de Windows con un proxy especial para grandes empresas.

¿Hay algún problema conocido con Internet Explorer 7? Con un sistema de proxy? La red de Windows en sí?

Google solo mostró algo en el contexto de la autenticación NTLM (y tal), pero no estamos usando esto en la aplicación web. ¿Tal vez sea por la manera en que el proxy opera en la red del cliente con los inicios de sesión de Windows? (No soy un experto en Windows. Solo estoy adivinando).

No tengo más información sobre la infraestructura.

ACTUALIZACIÓN: en diciembre de 2010 fue posible informar a un administrador sobre esto, incl. enlaces de las respuestas aquí. El contacto se debió a otro problema que también fue causado por el proxy. Sin comentarios desde entonces. Y los mensajes de error todavía están allí. Me río para evitar que lloré.

ACTUALIZACIÓN 2: Este problema existe desde mediados de 2008. Cada pocos meses el cliente está molesto y quiere que se solucione lo antes posible. Les enviamos nuevamente todos los correos electrónicos antiguos y les pedimos que se comuniquen con sus administradores para corregirlo o realizar más pruebas. En diciembre de 2010, pudimos enviar información a 1 administrador. Sin realimentación. El problema no está solucionado y no sabemos si lo intentaron. Y en mayo de 2011, el cliente vuelve a escribir y quiere que se solucione. La misma persona que tiene toda la información desde 2008.

Gracias por todas las respuestas. Ayudaste a mucha gente, como puedo ver en algunos comentarios aquí. Lástima que el mundo real sea así de grotesco para mí.

ACTUALIZACIÓN 3: mayo de 2012 y me preguntaba por qué no había recibido otra solicitud para solucionar esto (ver ACTUALIZACIÓN 2). Estudié el protocolo de error, que solo informa este error único cada vez que ocurre (alrededor de 15 por día). Se detuvo a fines de enero de 2012. Nadie dijo nada. Deben haber hecho algo con su red. Ahora todo esta bien. Desde el verano de 2008 hasta enero de 2012. Lástima que no puedo decirte lo que han hecho.

ACTUALIZACIÓN 4: septiembre de 2015. El sitio web tuvo que recostackr algunos datos y enviarlos al sitio web principal del cliente. Había una API con una cuenta. Cada vez que había un problema nos contactaban, incluso si el problema estaba claramente del otro lado. Desde hace unas semanas, no podemos enviarles los datos. La cuenta ya no está disponible. Tuvieron un relanzamiento y ya no puedo encontrar las páginas que utilizaron los datos de nuestro sitio. El informe de error no se responde y nadie se queja. Supongo que acaban de terminar este proyecto.

ACTUALIZACIÓN 5: marzo de 2017. La API dejó de funcionar en el verano de 2015. El cliente parece continuar pagando por el sitio y todavía está accediendo a él en febrero de 2017. Supongo que lo usan como archivo. Ya no crean ni actualizan ningún dato, por lo que es probable que este error no resurja después de la misteriosa solución de enero de 2012. Pero este sería el problema de otra persona. Me voy.

Internet Explorer no envía campos de formulario si se publican desde un sitio autenticado (NTLM) a un sitio no autenticado (anónimo).

Esta es una característica para situaciones de respuesta desafiante (sitios web NTLM o Kerberos) donde IE puede esperar que la primera solicitud POST conduzca inmediatamente a una respuesta HTTP 401 requerida de autenticación (que incluye un desafío), y solo a la segunda solicitud POST ( que incluye la respuesta al desafío) en realidad será aceptado. En estas situaciones, IE no carga el cuerpo de solicitud posiblemente grande con la primera solicitud por motivos de rendimiento. Gracias a EricLaw por publicar esa información en los comentarios.

Este comportamiento ocurre cada vez que se realiza una HTTP POST desde una página NTLM autenticada (es decir, Intranet) a una página no autenticada (es decir, Internet) o si la página no autenticada es parte de un conjunto de marcos, donde la página de conjunto de marcos está autenticada.

La solución alternativa es utilizar una solicitud GET como método de formulario o asegurarse de que la página no autenticada se abra en una pestaña / ventana nueva (favorito / destino de enlace) sin un conjunto de marcos parcialmente autenticado. Tan pronto como el modelo de autenticación para toda la ventana sea consistente, IE comenzará a enviar contenidos de forma nuevamente.


Esto es fácil de reproducir con MS-IE y un filtro de autenticación NTLM en el lado del servidor. Tengo el mismo problema con JCIFS (1.2. ), Struts 1. y MS-IE 6/7 en XP-SP2. Finalmente fue arreglado. Hay varias soluciones para completarlo.

  1. cambiar el método de formulario de POST (configuración predeterminada de struts) a GET. Para la mayoría de las páginas con formas de tamaño pequeño, funciona bien. Lamentablemente, tengo posiblemente más de 50 registros para enviar en la secuencia HTTP de vuelta al lado del servidor. IE tiene un límite de URL OBTENIDA de 2038 bytes (no la longitud del parámetro, sino la longitud completa de la URL). Así que esta es una solución rápida, pero no aplicable para mí.

  2. enviar un GET antes de ejecutar la acción POST. Esto fue recomendado en MS-KB. Mi proyecto tiene muchos procedimientos heredados y no correría el riesgo en el momento adecuado. Nunca lo he intentado porque todavía necesita un procesamiento de autenticación adicional cuando se recibe GET por capa de filtro según mi conocimiento de MS-KB y no me gustaría cambiar el comportamiento con otros navegadores, por ejemplo, Firefox, Opera.

  3. detectar si se envió POST con cero contenido-longitud (puede obtenerlo de la estructura de hash de propiedades del encabezado con su marco). Si es así, active un ciclo de autenticación NTLM mediante el código de desafío de DC o caché y espere una respuesta NTLM. Cuando se recibe el mensaje NTLM type2 y la sesión sigue siendo válida, no es necesario autenticar al usuario, sino simplemente reenviarlo a la acción esperada si POST content-length no es cero. Por cierto, esto boostía los tráficos de red. Por lo tanto, compruebe la configuración del tiempo de vida de la memoria caché y la configuración soTimeOut de la sesión SMB antes de aplicar el cambio porfavor. O, más simple, puede simplemente enviar un estado 401 no autorizado a MS-IE y el navegador enviará una solicitud POST con los datos en respuesta.

  4. MS-KB ha proporcionado una solución técnica con KB-923155 (no pude publicar más de un enlace debido a un bajo número de reputación: {), pero parece que no funciona. ¿Alguien publicaría una solución viable aquí? Gracias 🙂 Aquí hay un enlace de referencia, http://www.websina.com/bugzero/kb/browser-ie.html

Tenemos un cliente en nuestro sistema con exactamente el mismo problema. Hemos apuntado hacia el proxy / firewall. IAS de Microsoft. Está eliminando el cuerpo POST y enviando contenido-longitud: 0. Sin embargo, no podemos hacer mucho para evitar las solicitudes GET, ya que esto expone nombres de usuario / contraseñas, etc. en la cadena URL. Hay casi 7.000 usuarios en nuestro sistema y solo uno con el problema … también solo uno que usa Microsoft IAS, por lo que tiene que ser esto.

Hay una gran probabilidad de que el servidor proxy implemente HTTP 1.0.

En HTTP 1.0, debe usar el campo de encabezado Content-Length: ( Consulte la sección 10.4 aquí )

Se requiere una longitud de contenido válida en todas las solicitudes HTTP / 1.0 POST. Un servidor HTTP / 1.0 debe responder con un mensaje 400 (solicitud incorrecta) si no puede determinar la duración del contenido del mensaje de solicitud.

La solicitud que entra en el proxy es HTTP 1.1 y, por lo tanto, no es necesario utilizar el campo de encabezado Content-Length. El encabezado Content-Length generalmente se usa, pero no siempre. Vea el siguiente fragmento del HTTP 1.1 RFC S. 14.13 .

Las aplicaciones DEBEN usar este campo para indicar la longitud de transferencia del cuerpo del mensaje, a menos que esto esté prohibido por las reglas de la sección 4.4 . Cualquier contenido-longitud mayor que o igual a cero es un valor válido.

La sección 4.4 describe cómo determinar la longitud de un cuerpo de mensaje si no se proporciona una longitud de contenido.

Por lo tanto, el servidor proxy no ve el encabezado Content-Length, que asume que es absolutamente necesario en HTTP 1.0 si hay un cuerpo. Entonces asume 0 para que la solicitud eventualmente llegue al servidor. Recuerde que el proxy no conoce las reglas de la especificación HTTP 1.1, por lo que no sabe cómo manejar la situación cuando no hay un encabezado Content-Length.

¿Estás 100% seguro de que tu solicitud especifica el encabezado Content-Length? Si usa otro medio como se define en la sección 4.4 porque cree que el servidor es 1.1 (porque no conoce el proxy 1.0 entre ellos), entonces tendrá el problema descrito.

Quizás pueda usar HTTP GET en lugar de eludir el problema.

Este es un problema conocido para Internet Explorer 6, pero no para 7 que yo sepa. Puede instalar esta solución para el arreglo IE6 KB831167 .

Puedes leer más sobre esto aquí .

Algunas preguntas para ti:

  • ¿Sabes qué tipo de proxy?
  • ¿Sabes si hay un cuerpo real enviado en la solicitud?
  • ¿Sucede constantemente cada vez? ¿O solo algunas veces?
  • ¿Hay algún dato binario enviado en la solicitud? Tal vez los datos comienzan con un \ 0 y el proxy tiene un error con los datos binarios.

Si el usuario está pasando por un proxy ISA que usa autenticación NTLM, entonces suena como este problema, que tiene una solución provista (un parche para el proxy ISA)

http://support.microsoft.com/kb/942638
Las solicitudes POST que no tienen un cuerpo POST pueden enviarse a un servidor web publicado en ISA Server 2006

¿Estás seguro de que estas solicitudes provienen de un “cliente”?

He tenido este problema con bots antes; a veces prueban los sitios para los formularios “contáctenos” enviando solicitudes POST en blanco basadas en el URI de acción en las tags FORM que descubren durante el rastreo.

La presencia y los posibles valores del encabezado ContentLength en HTTP se describen en HTTP (supongo 1/1) RFC:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13

En HTTP, DEBE enviarse siempre que la longitud del mensaje pueda determinarse antes de ser transferido

Ver también:

Si se recibe un mensaje con un campo de encabezado Transfer-Encoding y un campo de encabezado Content-Length, este último DEBE ignorarse. http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

¿Tal vez su mensaje lleva un encabezado Transfer-Encoding?

Edición posterior: también tenga en cuenta que “DEBERÍA”, tal como se utiliza en el RFC es muy importante y no es equivalente a “DEBE”:

3. DEBERÍA Esta palabra, o el adjetivo “RECOMENDADO”, significa que puede haber razones válidas en circunstancias particulares para ignorar un elemento en particular, pero las implicaciones completas deben ser entendidas y sopesadas cuidadosamente antes de elegir un curso diferente. Ref: http://www.ietf.org/rfc/rfc2119.txt

Google también muestra esto como un error de IE (algunas versiones, de todos modos) después de que una conexión https alcanza el tiempo de espera de keepalive y se vuelve a conectar al servidor. La solución parece estar configurando el servidor para que no use keepalive para IE bajo https.

El hotfix de Microsoft para KB821814 puede establecer Content-Length en 0:

La revisión que describe este artículo implementa un cambio de código en Wininet.dll para:

  • Detecta la condición RESET en una solicitud POST.
  • Guarde los datos que se publicarán.
  • Vuelva a intentar la solicitud POST con la longitud del contenido establecida en 0. Esto evita que se produzca el restablecimiento y permite que se complete el proceso de autenticación.
  • Vuelva a intentar la solicitud POST original.

Teníamos un cliente que usaba el mismo sitio web en modo anónimo y NTLM (en diferentes puertos). Descubrimos que en nuestro caso el 401 estaba relacionado con la aplicación Riverbed Steelhead utilizada para la optimización http. La primera señal que nos indicó esa dirección fue un encabezado X-RBT-Optimized-By. El problema fue la función Gratuito 401:

Esta característica se puede usar con autenticación por solicitud y por conexión, pero es más efectiva cuando se usa con autenticación por solicitud. Con la autenticación por solicitud, cada solicitud debe autenticarse contra el servidor antes de que el servidor sirva el objeto al cliente. Sin embargo, la mayoría de los navegadores no almacenan en caché la respuesta del servidor que requiere autenticación y, por lo tanto, perderá un viaje de ida y vuelta por cada solicitud GET. Con Gratuitous 401, el dispositivo Steelhead del lado del cliente almacenará en caché la respuesta del servidor y cuando el cliente envía la solicitud GET sin ningún encabezado de autenticación, responderá localmente con un mensaje “401 no autorizado” y, por lo tanto, guardará un viaje de ida y vuelta. Tenga en cuenta que el módulo HTTP no participa en la autenticación real. Lo que hace el módulo HTTP es informar al cliente que el servidor requiere autenticación sin necesidad de perder un viaje de ida y vuelta.

curl envía solicitudes PUT/POST con Content-Length: 0 cuando está configurado para usar HTTP proxy. Es un truco para superar el almacenamiento en búfer requerido en caso de una primera solicitud no autorizada de PUT/POST al proxy. En el caso de las solicitudes GET/HEAD curl simplemente repite la consulta. El esquema para PUT/POST es como:

  1. Enviar la primera solicitud PUT/POST con Content-Length establecida en 0.

  2. Obtener respuesta El código de estado HTTP de 407 significa que tenemos que usar la autorización del proxy. Prepare encabezados para la autenticación de proxy para la solicitud de envío.

  3. Enviar de nuevo la solicitud con los encabezados completados para autenticación de proxy y datos reales a POST / PUT.

También tuve un problema cuando las solicitudes del navegador IE 11 de un cliente tenían Content-Length: 0 y no incluían el contenido POST esperado. Cuando el cliente usó Firefox o Chrome, el contenido esperado se incluyó en la solicitud.

Resolví la causa porque el cliente estaba usando una URL HTTP en lugar de una URL HTTPS (por ejemplo, http://... , no https://... ) y nuestra aplicación usa HSTS. Parece que puede haber un error en IE 11 que cuando una solicitud se actualiza a HTTPS debido a HSTS se pierde el contenido de la solicitud.

Hacer que el cliente corrigiera la URL a https://... dio como resultado que el contenido se incluyera en la solicitud POST y resolvió el problema.

No he investigado si en realidad es un error en IE 11 en esta etapa.