为什么我收到“(304) Not Modified”使用 HttpWebRequest 时某些链接出错?

发布于 2024-08-28 08:37:34 字数 10605 浏览 6 评论 0原文

任何想法为什么在我尝试使用 HttpWebRequest 访问的某些链接上我收到“远程服务器返回错误:(304) 未修改”。在代码中?

我使用的代码来自 Jeff 的帖子这里(该页面似乎已经消失,请参阅在 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 个有问题的链接,并且似乎工作正常,第二次出现错误,第三次正常,第四次出现错误,第五次正常等等。好像有某种状态未清除或代码中的一些东西。我尝试使用“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'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();
        }
    }
}

这是我看到的一个例子 - 第一个命中很好,第二个有错误......

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.

Any ideas why on some links that I try to access using HttpWebRequest I am getting "The remote server returned an error: (304) Not Modified." in the code?

The code I'm using is from Jeff's post here (the page seems to have disappeared, see an archive copy at the Wayback Machine).

Note the concept of the code is a simple proxy server, so I'm pointing my browser at this locally running piece of code, which gets my browsers request, and then proxies it on by creating a new HttpWebRequest, as you'll see in the code. It works great for most sites/links, but for some this error comes up. You will see one key bit in the code is where it seems to copy the http header settings from the browser request to it's request out to the site, and it copies in the header attributes. Not sure if the issue is something to do with how it mimics this aspect of the request and then what happens as the result comes back?

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

I get the issue for example from http://en.wikipedia.org/wiki/Main_Page

PS. UPDATE HERE

Still can't work this out. Basically I can identify 1 link which has an issue, and it seems to work fine, 2nd time it gets the error, 3rd time OK, 4th time gets the error, 5th time OK etc. As if there is some state not getting cleared or something in the code. I've tried to clean up the code a bit using "using" type statements etc.

Here's the code. If anyone can spot why every 2nd time I browse to a link like http://newsimg.bbc.co.uk/css/screen/1_0_16/nol/v4/story.css (starting at the 2nd time, not the first) via this proxy code I get the error I'd love to hear.

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();
        }
    }
}

And here is an example of what I see - first hit is good, 2nd has 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

清眉祭 2024-09-04 08:37:34

首先,这不是一个错误。 3xx 表示重定向。真正的错误是 4xx(客户端错误)和5xx< /a>(服务器错误)。

如果客户端收到 304 Not Modified ,那么客户端有责任从自己的缓存中显示有问题的资源。一般来说,代理不应该担心这一点。这只是使者。

First, this is not an error. The 3xx denotes a redirection. The real errors are 4xx (client error) and 5xx (server error).

If a client gets a 304 Not Modified, then it's the client's responsibility to display the resouce in question from its own cache. In general, the proxy shouldn't worry about this. It's just the messenger.

护你周全 2024-09-04 08:37:34

这是有意的行为。

当您发出 HTTP 请求时,服务器通常会返回代码 200 OK。如果设置了If-Modified-Since,服务器可能会返回304 Not Modified(并且响应中不会有内容)。这应该是提示您该页面尚未被修改。

该课程的作者愚蠢地决定304 应被视为错误并引发异常。现在,您必须在每次尝试使用 If-Modified-Since 时捕获异常来进行清理。

This is intended behavior.

When you make an HTTP request, the server normally returns code 200 OK. If you set If-Modified-Since, the server may return 304 Not modified (and the response will not have the content). This is supposed to be your cue that the page has not been modified.

The authors of the class have foolishly decided that 304 should be treated as an error and throw an exception. Now you have to clean up after them by catching the exception every time you try to use If-Modified-Since.

蓝天 2024-09-04 08:37:34

仅按 F5 并不总是有效。

为什么?

因为您的 ISP 也在为您缓存网络数据。

解决方案:强制刷新。

在 Firefox 或 Chrome 中按 CTRL + F5 强制刷新浏览器以清除 ISP 缓存,而不是仅按 F5

然后您可以看到 200在浏览器 F12 开发人员工具网络选项卡中响应而不是 304。

另一个技巧是在请求页面的 URL 字符串末尾添加问号 ?

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

问号将确保浏览器刷新请求而不缓存任何先前的请求。

此外,在 Visual Studio 中,您可以将默认浏览器设置为隐身模式下的 Chrome,以避免开发时出现缓存问题,方法是将 Chrome 添加到隐身模式:默认浏览器,请参阅步骤(自图解):

转到浏览器列表
选择浏览方式...
单击“添加”。 ..
指向在您的平台上运行 chrome.exe,添加参数“Incognito”

Just pressing F5 is not always working.

why?

Because your ISP is also caching web data for you.

Solution: Force Refresh.

Force refresh your browser by pressing CTRL + F5 in Firefox or Chrome to clear ISP cache too, instead of just pressing F5

You then can see 200 response instead of 304 in the browser F12 developer tools network tab.

Another trick is to add question mark ? at the end of the URL string of the requested page:

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

The question mark will ensure that the browser refresh the request without caching any previous requests.

Additionally in Visual Studio you can set the default browser to Chrome in Incognito mode to avoid cache issues while developing, by adding Chrome in Incognito mode as default browser, see the steps (self illustrated):

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

空城旧梦 2024-09-04 08:37:34

这不是一个问题,而是因为缓存......

要解决这个问题,请在端点调用中添加时间戳,例如 axios.get('/api/products')

时间戳之后应该是 axios.get(/api/products?${Date.now()}

它将解析您的 304 状态代码。

It is not an issue it is because of caching...

To overcome this add a timestamp to your endpoint call, e.g. axios.get('/api/products').

After timestamp it should be axios.get(/api/products?${Date.now()}.

It will resolve your 304 status code.

メ斷腸人バ 2024-09-04 08:37:34

如果网络状态为 304(未修改) - 这是 Google Chrome 的解决方案:打开 DevTools → 设置 → 首选项 → 网络并选中禁用缓存(当 DevTools 打开时)

If you have status 304 (Not Modified) in Network – Here is solution for Google Chrome: Open DevTools → Settings → Preferences → Network and check Disable cache (while DevTools is open)

抚笙 2024-09-04 08:37:34

我认为您还没有安装这些功能。见下图。

在此处输入图像描述

前几天我也遇到了这个问题。安装此功能后,我解决了它。如果您尚未安装此功能,请安装它。

安装过程:

  1. 进入android studio
  2. Tools
  3. Android
  4. SDK Manager
  5. Appearance & 行为
  6. Android SDK

I think you have not installed these features. see below in picture.

enter image description here

I also suffered from this problem some days ago. After installing this feature then I solved it. If you have not installed this feature then installed it.

Install Process:

  1. go to android studio
  2. Tools
  3. Android
  4. SDK Manager
  5. Appearance & Behavior
  6. Android SDK
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文