Estoy trabajando en una pequeña aplicación C#/WPF que interactúa con un servicio web implementado en Ruby on Rails, utilizando llamadas hechas a mano HttpWebRequest
y serialización JSON. Sin almacenamiento en caché, todo funciona como debería y también tengo la autenticación y compresión HTTP funcionando.HttpWebRequest con almacenamiento en caché habilitado arroja excepciones
Una vez que habilito el almacenamiento en caché, estableciendo request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable);
, las cosas salen mal, en el entorno de producción. Cuando me conecto a una instancia simple de WEBrick, las cosas funcionan bien, recibo HTTP/1.1 304 Not Modified
como se esperaba y HttpWebRequest
entrega el contenido en caché.
Cuando intento lo mismo con el servidor de producción, ejecutando nginx/0.8.53 + Phusion Passenger 3.0.0, la aplicación se rompe. La primera solicitud (no guardada) se sirve correctamente, pero en la segunda solicitud que da como resultado la respuesta 304, obtengo un WebException
que indica que "La solicitud se anuló: la solicitud se canceló." tan pronto como invoco request.GetResponse()
.
He pasado las conexiones a través de fiddler, que no ha ayudado mucho; tanto WEBrick como nginx devuelven un cuerpo de entidad vacío, aunque con diferentes encabezados de respuesta. Interceptar la solicitud y cambiar los encabezados de respuesta para nginx para que coincida con los de WEBrick no cambió nada, lo que me lleva a pensar que podría tratarse de un tema para mantener vivo; Sin embargo, la configuración request.KeepAlive = false;
no cambia nada: no interrumpe las cosas cuando se conecta a WEBrick, y no arregla nada cuando se conecta a nginx.
Por lo que vale la pena, la WebException.InnerException
es una NullReferenceException
con las siguientes StackTrace
:
at System.Net.HttpWebRequest.CheckCacheUpdateOnResponse()
at System.Net.HttpWebRequest.CheckResubmitForCache(Exception& e)
at System.Net.HttpWebRequest.DoSubmitRequestProcessing(Exception& exception)
at System.Net.HttpWebRequest.ProcessResponse()
at System.Net.HttpWebRequest.SetResponse(CoreResponseData coreResponseData)
encabezados para la conexión (de trabajo) WEBrick:
########## request
GET /users/current.json HTTP/1.1
Authorization: Basic *REDACTED*
Content-Type: application/json
Accept: application/json
Accept-Charset: utf-8
Host: testbox.local:3030
If-None-Match: "84a49062768e4ca619b1c081736da20f"
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
########## response
HTTP/1.1 304 Not Modified
X-Ua-Compatible: IE=Edge
Etag: "84a49062768e4ca619b1c081736da20f"
Date: Wed, 01 Dec 2010 18:18:59 GMT
Server: WEBrick/1.3.1 (Ruby/1.8.7/2010-08-16)
X-Runtime: 0.177545
Cache-Control: max-age=0, private, must-revalidate
Set-Cookie: *REDACTED*
cabeceras para el (a excepción de lanzamiento de) conexión nginx:
########## request
GET /users/current.json HTTP/1.1
Authorization: Basic *REDACTED*
Content-Type: application/json
Accept: application/json
Accept-Charset: utf-8
Host: testsystem.local:8080
If-None-Match: "a64560553465e0270cc0a23cc4c33f9f"
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
########## response
HTTP/1.1 304 Not Modified
Connection: keep-alive
Status: 304
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.0
ETag: "a64560553465e0270cc0a23cc4c33f9f"
X-UA-Compatible: IE=Edge,chrome=1
X-Runtime: 0.240160
Set-Cookie: *REDACTED*
Cache-Control: max-age=0, private, must-revalidate
Server: nginx/0.8.53 + Phusion Passenger 3.0.0 (mod_rails/mod_rack)
ACTUALIZACIÓN:
He intentado hacer una caché ETag Manual rápido y sucio-, pero resulta que es un no-voy: tengo un WebException
al invocar request.GetResponce()
, diciéndome que "El servidor remoto devolvió un error: (304) No modificado. " - sí, .NET, lo sabía un poco, y me gustaría (intentar) manejarlo yo mismo, grr.
ACTUALIZACIÓN 2:
Cada vez más cerca de la raíz del problema. Parece que la diferencia es la diferencia en los encabezados de respuesta para la solicitud inicial . WEBrick incluye un encabezado Date: Wed, 01 Dec 2010 21:30:01 GMT
, que no está presente en la respuesta nginx. También hay otras diferencias, pero al interceptar la respuesta inicial de nginx con el violín y agregar un encabezado Date
, los siguientes HttpWebRequest
s pueden procesar las respuestas (no modificadas) nginx 304.
Vamos a tratar de buscar una solución alternativa, así como a obtener nginx para agregar el encabezado de fecha.
Actualización 3:
Parece que el problema es con serverside Phusion de pasajeros, tienen un open issue por la falta de la cabecera Date
. Aún diría que el comportamiento de HttpWebRequest
es ... subóptimo.
ACTUALIZACIÓN 4:
añadido un billete Microsoft Connect para el error.
Hola! Creo que has encontrado un error en HttpWebRequest. ¿Puedes crear un registro de la reproducción (ver http://ferozedaud.blogspot.com/2009/08/tracing-with-systemnet.html) y crear una solicitud de error en http: // connect? De esa forma, Microsoft puede solucionar el problema. – feroze
@feroze: ayer me quedé sin tiempo, pero ahora he agregado el error en Connect. – snemarch