Подтвердить что ты не робот

Почему я получаю сообщение об ошибке "(304)" Не изменено "на некоторых ссылках при использовании HttpWebRequest?

Любые идеи, почему на некоторых ссылках, которые я пытаюсь получить с помощью HttpWebRequest, я получаю "Удаленный сервер возвратил ошибку: (304) Не изменено". в коде?

Код, который я использую, это Jeff post here (страница, похоже, исчезла, см. архивная копия на Wayback Machine).

Обратите внимание, что концепция кода - простой прокси-сервер, поэтому я указываю свой браузер на этом локально запущенном фрагменте кода, который получает мой запрос на браузер, а затем проксирует его, создавая новый HttpWebRequest, см. в коде. Он отлично работает для большинства сайтов/ссылок, но для некоторых возникает эта ошибка. Вы увидите, что один ключевой бит в коде, где он, кажется, скопирует настройки заголовка http из запроса браузера, чтобы он запрашивал сайт, и копирует его в атрибутах заголовка. Не уверен, что проблема связана с тем, как она имитирует этот аспект запроса, а затем что происходит, когда результат возвращается?

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

Я получаю проблему, например, из http://en.wikipedia.org/wiki/Main_Page

PS. ОБНОВЛЕНИЕ ЗДЕСЬ

Все еще не получается это сделать. В принципе, я могу идентифицировать 1 ссылку, у которой есть проблема, и, похоже, она работает нормально, второй раз она получает ошибку, 3-й раз ОК, 4-й раз получает ошибку, 5-е время ОК и т.д. Как будто какое-то состояние не очищается или что-то в коде. Я попытался немного очистить код, используя инструкции типа "using" и т.д.

Вот код. Если каждый может определить, почему каждый второй раз я просматриваю ссылку, например http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css (начиная со второго, а не первого) через этот прокси-сервер Код Я получаю сообщение об ошибке, которое я бы хотел услышать.

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 body
        List<byte> responseBody = new List<byte>(); // Byte array to hold the response 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();
        }
    }
}

И вот пример того, что я вижу - первый удар хорош, второй имеет ошибку...

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.
4b9b3361

Ответ 1

Во-первых, это не ошибка. 3xx обозначает перенаправление. Реальные ошибки 4xx (ошибка клиента) и 5xx (ошибка сервера).

Если клиент получает 304 Not Modified, то это ответственность клиента за отображение рассматриваемого вопроса из его собственного кеша. В общем, прокси не должен беспокоиться об этом. Это просто посланник.

Ответ 2

Это предполагаемое поведение.

Когда вы делаете HTTP-запрос, сервер обычно возвращает код 200 OK. Если вы установите If-Modified-Since, сервер может вернуть 304 Not modified (и ответ не будет содержать контент). Это должно быть вашим сигналом, что страница не была изменена.

авторы этого класса глупо решили, что 304 следует рассматривать как ошибку и вызывать исключение. Теперь вам нужно очистить их, поймав исключение каждый раз, когда вы пытаетесь использовать If-Modified-Since.

Ответ 3

Простое нажатие F5 не всегда работает.

Зачем?

Потому что ваш провайдер также кеширует веб-данные для вас.

Решение: принудительное обновление.

Принудительно обновите ваш браузер, нажав CTRL + F5 в Firefox или Chrome, чтобы очистить кеш интернет-провайдера, вместо того, чтобы просто нажать F5

Затем вы можете увидеть ответ 200 вместо 304 во вкладке сети инструментов разработчика F12.

Еще один трюк - добавить знак вопроса ? в конце строки URL запрашиваемой страницы:

http://localhost:52199/Customers/Create?

Вопросительный знак гарантирует, что браузер обновит запрос без кеширования любых предыдущих запросов.

Кроме того, в Visual Studio вы можете установить браузер по умолчанию в Chrome в режиме инкогнито, чтобы избежать проблем с кэшем при разработке, добавив Chrome в режиме инкогнито в качестве браузера по умолчанию, см. Шаги (как показано на рисунке):

Go to browsers list Select browse with... Click Add... Point to the chrome.exe on your platform, add argument "Incognito" Choose the browser you just added and set as default, then click browse

Ответ 4

Я думаю, что вы не установили эти функции. см. ниже на рисунке.

enter image description here

Я также страдал от этой проблемы несколько дней назад. После установки этой функции я решил ее. Если вы не установили эту функцию, установите ее.

Процесс установки:

  • перейти в студию android studio
  • Инструменты
  • Android
  • Менеджер SDK
  • Внешний вид и поведение
  • Android SDK