¿Por qué aparece el error "(304) No modificado" en algunos enlaces cuando uso HttpWebRequest?
-
25-09-2019 - |
Pregunta
¿Alguna idea de por qué en algunos enlaces a los que intento acceder mediante HttpWebRequest aparece "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, ver una copia de archivo en Wayback Machine).
Tenga en cuenta que el concepto del código es un servidor proxy simple, por lo que apunto mi navegador a este fragmento de código que se ejecuta localmente, que recibe la solicitud de mi navegador y luego lo activa creando un nuevo HttpWebRequest, como verá en el código.Funciona muy bien para la mayoría de los sitios/enlaces, pero en algunos aparece este error.Verá que un bit clave en el código es donde parece copiar la configuración del encabezado http de la solicitud del navegador a su solicitud al sitio, y se copia en 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 llega 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.ACTUALIZAR AQUÍ
Todavía no puedo resolver esto.Básicamente, puedo identificar 1 enlace que tiene un problema y parece funcionar bien, la segunda vez aparece el error, la tercera vez está bien, la cuarta vez aparece el error, la quinta vez está bien, etc.Como si hubiera algún estado que no se borra o algo en el código.Intenté limpiar un poco el código usando declaraciones de tipo "usando", etc.
Aquí está el código.Si alguien puede entender por qué cada segunda vez que busco un enlace como http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css (a partir de la segunda vez, no la primera) a través de este código proxy aparece 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 segundo 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
Primero, esto no es un error.El 3xx
denota una redirección.Los verdaderos errores son 4xx
(error del cliente) y 5xx
(Error del Servidor).
Si un cliente obtiene un 304 Not Modified
, entonces es responsabilidad del cliente mostrar el recurso en cuestión desde su propia caché.En general, el proxy no debería preocuparse por esto.Es sólo el mensajero.
Otros consejos
Este es el comportamiento previsto.
Cuando realiza una solicitud HTTP, el servidor normalmente devuelve código 200 OK
.si estableces If-Modified-Since
, el servidor puede regresar 304 Not modified
(y la respuesta no tendrá el contenido).Se supone que esta es su señal de que la página no ha sido modificada.
El Los autores de la clase han decidido tontamente. eso 304
debe tratarse como un error y generar una excepción.Ahora tienes que limpiarlos detectando la excepción cada vez que intentas usar If-Modified-Since
.
Solo presionando F5 no siempre está funcionando.
¿por qué?
Porque su ISP también almacena en caché los datos web por usted.
Solución: Forzar actualización.
Fuerce la actualización de su navegador presionando CONTROL + F5 en Firefox o Chrome para borrar también el caché del ISP, en lugar de simplemente presionar F5
Luego podrá ver la respuesta 200 en lugar de 304 en el navegador. F12 Pestaña de red de herramientas de desarrollador.
Otro truco es añadir un signo de interrogación. ?
al final de la cadena URL de la página solicitada:
http://localhost:52199/Customers/Create?
El signo de interrogación garantizará que el navegador actualice la solicitud sin almacenar en caché ninguna solicitud anterior.
Además en Estudio visual puede configurar el navegador predeterminado para Cromo en Incógnito modo para evitar problemas de caché durante el desarrollo, agregando Chrome en modo incógnito como navegador predeterminado, consulte los pasos (autoilustrados):
Creo que no has instalado estas funciones.ver abajo en la imagen.
Yo también sufrí este problema hace unos días.Después de instalar esta función, lo resolví.Si no ha instalado esta función, instálela.
Proceso de instalación:
- ir al estudio de Android
- Herramientas
- Androide
- Administrador de SDK
- Apariencia y comportamiento
- SDK de Android