¿Alguna idea de por qué en algunos enlaces a los que intento acceder usando HttpWebRequest obtengo «El servidor remoto devolvió un error: (304) No modificado» en el código?
El código que estoy usando es de la publicación de Jeff aquí (la página parece haber desaparecido, vea una copia de archivo en la Wayback Machine).
Tenga en cuenta que el concepto del código es un servidor proxy simple, por lo que estoy apuntando mi navegador a esta pieza de código que se ejecuta localmente, que recibe la solicitud de mis navegadores y luego la activa creando un nuevo HttpWebRequest, como verá en el código. Funciona muy bien para la mayoría de los sitios / enlaces, pero para algunos aparece este error. Verá que un bit clave en el código es donde parece copiar la configuración del encabezado http desde la solicitud del navegador a su solicitud al sitio, y copia los atributos del encabezado. ¿No está seguro de si el problema tiene algo que ver con cómo imita este aspecto de la solicitud y luego qué sucede cuando regresa el resultado?
case "If-Modified-Since":
request.IfModifiedSince = DateTime.Parse(listenerContext.Request.Headers[key]);
break;
Recibo el problema, por ejemplo, de http://en.wikipedia.org/wiki/Main_Page
PD. ACTUALIZA AQUÍ
Todavía no puedo resolver esto. Básicamente puedo identificar 1 enlace que tiene un problema, y parece funcionar bien, 2ª vez recibe el error, 3ª vez OK, 4ª vez obtiene el error, 5ª vez OK, etc. Como si hubiera algún estado que no se borra o algo en el código. He intentado limpiar un poco el código usando instrucciones de tipo «using», etc.
Aquí está el código. Si alguien puede detectar por qué cada 2ª vez que navego a un enlace como http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css (a partir de la 2ª vez, no la primera) a través de este código proxy, recibo el error que me encantaría escuchar.
class Program
{
static void Main(string[] args)
{
Proxy p = new Proxy(8080);
Thread proxythread = new Thread(new ThreadStart(p.Start));
proxythread.Start();
Console.WriteLine("Proxy Started. Press Any Key To Stop...");
Console.ReadKey();
p.Stop();
}
}
public class Proxy
{
private HttpListener _listener;
private int _port;
public Proxy(int port)
{
int defaultport = 8080;
// Setup Thread Pool
System.Threading.ThreadPool.SetMaxThreads(50, 1000);
System.Threading.ThreadPool.SetMinThreads(50, 50);
// Sanitize Port Number
if (port < 1024 || port > 65535)
port = defaultport;
// Create HttpListener Prefix
string prefix = string.Format("http://*:{0}/", port);
_port = port;
// Create HttpListener
_listener = new HttpListener();
_listener.Prefixes.Add(prefix);
}
public void Start()
{
_listener.Start();
while (true)
{
HttpListenerContext request = null;
try
{
request = _listener.GetContext();
// Statistics (by Greg)
int availThreads = -1;
int compPortThreads = -1;
ThreadPool.GetAvailableThreads(out availThreads, out compPortThreads);
log("INFO", request.Request.Url.ToString(), "START - [" + availThreads + "]");
ThreadPool.QueueUserWorkItem(ProcessRequest, request);
}
catch (HttpListenerException ex)
{
log("ERROR", "NA", "INFO: HttpListenerException - " + ex.Message);
break;
}
catch (InvalidOperationException ex)
{
log("ERROR", "NA", "INFO: InvalidOperationException - " + ex.Message);
break;
}
}
}
public void Stop()
{
_listener.Stop();
}
private void log(string sev, string uri, string message)
{
Console.Out.WriteLine(Process.GetCurrentProcess().Id + " - " + sev + " (" + uri + "): " + message);
}
private void ProcessRequest(object _listenerContext)
{
#region local variables
HttpWebRequest psRequest; // Request to send to remote web server
HttpWebResponse psResponse; // Response from remote web server
List<byte> requestBody = new List<byte>(); // Byte array to hold the request's body
List<byte> responseBody = new List<byte>(); // Byte array to hold the response's body
byte[] buffer;
string uri = "";
#endregion
var listenerContext = (HttpListenerContext)_listenerContext;
uri = listenerContext.Request.Url.ToString().Replace(string.Format(":{0}", _port), "");
// Create Interent Request
HttpWebRequest internetRequest = (HttpWebRequest)WebRequest.Create(uri);
#region Build Request Up
internetRequest.Method = listenerContext.Request.HttpMethod;
internetRequest.ProtocolVersion = listenerContext.Request.ProtocolVersion;
internetRequest.UserAgent = listenerContext.Request.UserAgent;
foreach (string key in listenerContext.Request.Headers.AllKeys)
{
try
{
switch (key)
{
case "Proxy-Connection":
case "Connection":
internetRequest.KeepAlive = (listenerContext.Request.Headers[key].ToLower() == "keep-alive") ? true : false;
break;
case "Content-Length":
internetRequest.ContentLength = listenerContext.Request.ContentLength64;
break;
case "Content-Type":
internetRequest.ContentType = listenerContext.Request.ContentType;
break;
case "Accept":
internetRequest.Accept = listenerContext.Request.Headers[key];
break;
case "Host":
break;
case "Referer":
internetRequest.Referer = listenerContext.Request.Headers[key];
break;
case "If-Modified-Since":
internetRequest.IfModifiedSince = DateTime.Parse(listenerContext.Request.Headers[key]);
break;
default:
internetRequest.Headers.Add(key, listenerContext.Request.Headers[key]);
break;
}
}
catch (Exception ex)
{
Console.WriteLine("Error settup up psRequest object. Error = " + ex.Message + "n" + ex.StackTrace);
}
}
#endregion
#region Copy content into request
buffer = new byte[1024];
using (Stream instream = listenerContext.Request.InputStream)
{
int incount = instream.Read(buffer, 0, buffer.Length);
while (incount > 0)
{
internetRequest.GetRequestStream().Write(buffer, 0, incount);
incount = instream.Read(buffer, 0, buffer.Length);
}
}
#endregion
// Get Internet Response
HttpWebResponse internetResponse = null;
try
{
using (internetResponse = (HttpWebResponse)internetRequest.GetResponse())
{
#region Configure Local Response Header Keys
foreach (string key in internetResponse.Headers.Keys)
{
try
{
switch (key)
{
case "Transfer-Encoding":
listenerContext.Response.SendChunked = (internetResponse.Headers[key].ToLower() == "chunked") ? true : false;
break;
case "Content-Length":
listenerContext.Response.ContentLength64 = internetResponse.ContentLength;
break;
case "Content-Type":
listenerContext.Response.ContentType = internetResponse.Headers[key];
break;
case "Keep-Alive":
listenerContext.Response.KeepAlive = true;
break;
default:
listenerContext.Response.Headers.Add(key, internetResponse.Headers[key]);
break;
}
}
catch (Exception ex)
{
log("ERROR", uri, "Error settup up listenerContext.Response objects. Error = " + ex.Message + "n" + ex.StackTrace);
}
}
#endregion
try
{
// Transfer the body data from Internet Response to Internal Response
buffer = new byte[1024];
using (Stream inputStream = internetResponse.GetResponseStream())
{
int outcount = inputStream.Read(buffer, 0, buffer.Length);
while (outcount > 0)
{
listenerContext.Response.OutputStream.Write(buffer, 0, outcount);
outcount = inputStream.Read(buffer, 0, buffer.Length);
}
}
}
catch (Exception ex)
{
log("ERROR", uri, "Could not obtain response from URI: " + ex.Message);
}
finally
{
listenerContext.Response.OutputStream.Close();
}
}
}
catch (Exception ex)
{
//if (ex is InvalidOperationException ||
// ex is ProtocolViolationException ||
// ex is WebException)
//{
// log(uri, "Could not successfully get response: " + ex.GetType() + " - " + ex.Message);
// listenerContext.Response.Close();
// return;
//}
//else { throw; }
log("ERROR", uri, "Could not successfully get response: " + ex.GetType() + " - " + ex.Message);
listenerContext.Response.Close();
}
}
}
Y aquí hay un ejemplo de lo que veo: el primer golpe es bueno, el 2º tiene error …
Proxy Started. Press Any Key To Stop...
2080 - INFO (http://newsimg.bbc.co.uk:8080/css/screen/1_0_16/nol/v4/story.css): START - [50]
2080 - INFO (http://newsimg.bbc.co.uk:8080/css/screen/1_0_16/nol/v4/story.css): START - [50]
2080 - ERROR (http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css): Could not successfully get response: System.Net.WebException - The remote server returned an error: (304) Not Modified.
Solución
En primer lugar, esto no es un error. El 3xx
denota una redirección. Los errores reales son 4xx
(error de cliente) y 5xx
(error de servidor).
Si un cliente obtiene un 304 No modificado
, entonces es responsabilidad del cliente mostrar el resouce en cuestión desde su propia caché. En general, el proxy no debería preocuparse por esto. Es solo el mensajero.
Otras respuestas
Solo presionar no siempre funciona.F5
¿por qué?
Porque su ISP también está almacenando en caché los datos web por usted.
Solución: Forzar actualización.
Forzar la actualización de su navegador presionando + en Firefox o Chrome para borrar la caché del ISP también, en lugar de simplemente presionar CTRLF5F5
A continuación, puede ver 200 respuestas en lugar de 304 en la pestaña de red de herramientas de desarrollo del navegador.F12
Otro truco es agregar un signo de interrogación al final de la cadena de URL de la página solicitada:?
http://localhost:52199/Customers/Create?
El signo de interrogación asegurará que el navegador actualice la solicitud sin almacenar en caché ninguna solicitud anterior.
Además, en Visual Studio puede configurar el navegador predeterminado en Chrome en modo incógnito para evitar problemas de caché durante el desarrollo, agregando Chrome en modo incógnito como navegador predeterminado, consulte los pasos (autoilustrado):