2010-04-08 394 views
28

Alguna idea de por qué en algunos enlaces a los que intento acceder usando HttpWebRequest me aparece "El servidor remoto devolvió un error: (304) No modificado". en el código?¿Por qué recibo el error "(304) No modificado" en algunos enlaces cuando uso HttpWebRequest?

El código que estoy usando es de Jeff's post here (la página parece haber desaparecido, vea un archive copy at the 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 mi solicitud de navegadores y luego la genera mediante una nueva HttpWebRequest, como usted Veré en el código. Funciona muy bien para la mayoría de los sitios/enlaces, pero para algunos este error aparece. Verá que un bit clave en el código es donde parece copiar la configuración del encabezado http desde la solicitud del navegador hasta su solicitud al sitio y copia los atributos del encabezado. No estoy seguro de si el problema tiene que ver con la forma en que imita este aspecto de la solicitud y, luego, ¿qué sucede cuando vuelve el resultado?

case "If-Modified-Since": 
    request.IfModifiedSince = DateTime.Parse(listenerContext.Request.Headers[key]); 
    break; 

me sale el tema, por ejemplo, a partir http://en.wikipedia.org/wiki/Main_Page

PS. ACTUALIZAR AQUÍ

Todavía no se puede resolver esto. Básicamente puedo identificar 1 enlace que tiene un problema, y ​​parece funcionar bien, la segunda vez que recibe el error, la 3ª vez OK, la 4ª vez recibe el error, la 5ª vez OK, etc. Como si hubiera algún estado que no haya sido aprobado o algo en el código. He intentado limpiar un poco el código usando instrucciones de tipo "usar", etc.

Aquí está el código. Si alguien puede ver por qué cada 2 veces que navego por un enlace como http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css (comenzando por la 2 ª vez, no la primera) a través de este código proxy obtengo 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í es un ejemplo de lo que veo - primer golpe es bueno, segundo tiene errores ...

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. 
+0

posible duplicado de [HttpWebRequest.GetResponse arroja WebException en HTTP 304] (http://stackoverflow.com/questions/1366848/httpwebrequest-getresponse-throws-webexception-on-http-304) – Sebastian

Respuesta

66

En primer lugar, esto no es un error. El 3xx denota una redirección. Los errores reales 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 propio caché. En general, el proxy no debe preocuparse por esto. Es solo el mensajero.

+1

gracias - por lo que está diciendo entonces, lo que debería hacer es capturar la excepción (justo en el momento en que hago la solicitud), pero luego verifique qué hay en la excepción y si es un 304, entonces continúe. – Greg

+2

No, si ha enviado un if-modified-since o if-none-match implica que tiene una copia local (en caché): el servidor le está dando instrucciones para usar esa copia. – symcbean

+1

OK - solo tuve que asegurarme de haber devuelto el mismo código de estado en la solicitud local y esto parece funcionar. Consulte http://stackoverflow.com/questions/2611264/httplistener-how-do-i-send-a-webexception-http-304-not-modified-error-back-to para obtener más detalles sobre el código – Greg

12

Este es el comportamiento previsto.

Cuando realiza una solicitud HTTP, el servidor normalmente devuelve el código 200 OK. Si configura If-Modified-Since, el servidor puede devolver 304 Not modified (y la respuesta no tendrá el contenido). Se supone que esto es su señal de que la página no ha sido modificada.

El authors of the class have foolishly decided que 304 debe tratarse como un error y lanzar una excepción. Ahora tiene que limpiar después de ellos capturando la excepción cada vez que intente usar If-Modified-Since.

0

Creo que no ha instalado estas funciones. ver abajo en la imagen.

enter image description here

también he sufrido de este problema hace algunos días. Después de instalar esta característica, lo resolví. Si no ha instalado esta característica, entonces la instaló.

Proceso de Instalación:

  1. ir a Android Studio
  2. Herramientas
  3. Android
  4. Manager SDK
  5. Apariencia & Comportamiento
  6. SDK de Android
+1

No .. esto no es una respuesta –

3

páginas de Compensación en caché en el navegador se pueden lograr en Firefox o Chrome pulsando CTRL + F5 en lugar de simplemente presionando F5

A continuación, puede ver respuesta 200 en lugar de 304 en el navegador F12 herramientas de desarrollo pestaña de red

Cuestiones relacionadas