HttpWebRequest.GetResponse 在 HTTP 304 上抛出 WebException

发布于 2024-08-03 19:49:05 字数 171 浏览 6 评论 0原文

当 Web 服务器使用 HTTP 304(未修改)响应 HttpWebRequest.GetResponse() 时,GetResponse() 会抛出 WebException,如下所示对我来说很奇怪。这是设计使然还是我在这里遗漏了一些明显的东西?

When a web server responds to HttpWebRequest.GetResponse() with HTTP 304 (Not Modified), GetResponse() thows a WebException, which is so very weird to me. Is this by design or am I missing something obvious here?

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

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

发布评论

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

评论(5

来日方长 2024-08-10 19:49:05

好吧,这似乎是一种设计行为,也是 令人烦恼的异常。这可以用以下方法解决:

public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)
{
    try
    {
        return (HttpWebResponse) request.GetResponse();
    }
    catch (WebException ex)
    {
        if(ex.Response == null || ex.Status != WebExceptionStatus.ProtocolError)
            throw; 

        return (HttpWebResponse)ex.Response;
    }
}

Ok, this seems to be a by-design behavior and a perfect example of a vexing exception. This can be solved with this:

public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)
{
    try
    {
        return (HttpWebResponse) request.GetResponse();
    }
    catch (WebException ex)
    {
        if(ex.Response == null || ex.Status != WebExceptionStatus.ProtocolError)
            throw; 

        return (HttpWebResponse)ex.Response;
    }
}
信仰 2024-08-10 19:49:05

这确实是一个令人沮丧的问题,并且可以通过使用以下扩展方法类并调用 request.BetterGetResponse() 来解决。

//-----------------------------------------------------------------------
//
//     Copyright (c) 2011 Garrett Serack. All rights reserved.
//
//
//     The software is licensed under the Apache 2.0 License (the "License")
//     You may not use the software except in compliance with the License.
//
//-----------------------------------------------------------------------

namespace CoApp.Toolkit.Extensions {
    using System;
    using System.Net;

    public static class WebRequestExtensions {
        public static WebResponse BetterEndGetResponse(this WebRequest request, IAsyncResult asyncResult) {
            try {
                return request.EndGetResponse(asyncResult);
            }
            catch (WebException wex) {
                if( wex.Response != null ) {
                    return wex.Response;
                }
                throw;
            }
        }

        public static WebResponse BetterGetResponse(this WebRequest request) {
            try {
                return request.GetResponse();
            }
            catch (WebException wex) {
                if( wex.Response != null ) {
                    return wex.Response;
                }
                throw;
            }
        }
    }
}

您可以在我关于此主题的博客文章中阅读更多相关信息,网址为 http://fearthecowboy.com/2011/09/02/fixing-webrequests-desire -抛出异常而不是返回状态/

This is really a frustrating problem, and can be alternatively worked around by using the following extension method class and calling request.BetterGetResponse()

//-----------------------------------------------------------------------
//
//     Copyright (c) 2011 Garrett Serack. All rights reserved.
//
//
//     The software is licensed under the Apache 2.0 License (the "License")
//     You may not use the software except in compliance with the License.
//
//-----------------------------------------------------------------------

namespace CoApp.Toolkit.Extensions {
    using System;
    using System.Net;

    public static class WebRequestExtensions {
        public static WebResponse BetterEndGetResponse(this WebRequest request, IAsyncResult asyncResult) {
            try {
                return request.EndGetResponse(asyncResult);
            }
            catch (WebException wex) {
                if( wex.Response != null ) {
                    return wex.Response;
                }
                throw;
            }
        }

        public static WebResponse BetterGetResponse(this WebRequest request) {
            try {
                return request.GetResponse();
            }
            catch (WebException wex) {
                if( wex.Response != null ) {
                    return wex.Response;
                }
                throw;
            }
        }
    }
}

You read more about it in my blog post on this subject at http://fearthecowboy.com/2011/09/02/fixing-webrequests-desire-to-throw-exceptions-instead-of-returning-status/

云雾 2024-08-10 19:49:05

避免此 System.WebException 的方法是设置
允许自动重定向 属性设置为 false
这会禁用 WebRequest 的自动重定向逻辑。对于 304 重定向请求来说,它似乎被破坏了,因为它不是最严格意义上的真正的重定向。
当然,这意味着其他重定向请求 3xx 必须手动处理。

The way to avoid this System.WebException is to set
AllowAutoRedirect property to false.
This disables the automatic redirection logic of the WebRequest. It seems to be broken for 304 redirection requests, as it is not a real redirection in the strictest sense.
Of course that means that the other redirection requests 3xx have to be handled manually.

走野 2024-08-10 19:49:05

仅供参考,这是对 Anton Gogolev 的答案 的更新,该答案使用 C#6 (VS2015) 子句。使用调试器时就不那么烦人了,因为它删除了一个捕获点:

public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)
{
    try
    {
        return (HttpWebResponse) request.GetResponse();
    }
    catch (WebException ex)
        when (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null)
    {
        return (HttpWebResponse) ex.Response;
    }
}

Just as an FYI, this is an update to Anton Gogolev's answer that uses the C#6 (VS2015) when clause. It's a little less annoying when using a debugger as it removes one catchpoint:

public static HttpWebResponse GetHttpResponse(this HttpWebRequest request)
{
    try
    {
        return (HttpWebResponse) request.GetResponse();
    }
    catch (WebException ex)
        when (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null)
    {
        return (HttpWebResponse) ex.Response;
    }
}
自演自醉 2024-08-10 19:49:05

我也在代码中遇到了这个问题:

try
{
    ...
    var webResponse = req.GetResponse();
    ...
}
catch (WebException ex)
{
    Log.Error("Unknown error occured", ex);
    //throw; 
}

并且看起来,如果远程服务器返回 304 状态,则必须通过抛出此错误或返回自定义 304 将其传递给浏览器,以便浏览器可以返回缓存的响应。否则,您可能会从远程服务器得到空响应。

因此,在我的情况下,对于具有正确缓存处理的正常行为,它应该是这样的:

try
{
    ...
    var webResponse = req.GetResponse();
    ...
}
catch (WebException ex)
{
    if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotModified)
        throw;
    Log.Error("Unknown error occured", ex);
}

I also came across to this issue with code:

try
{
    ...
    var webResponse = req.GetResponse();
    ...
}
catch (WebException ex)
{
    Log.Error("Unknown error occured", ex);
    //throw; 
}

And it appears that if Remote Server returns 304 status it must be passed to Browser by throwing this error or returning custom 304 so the Browser could return cached response. Otherwise you will probably get empty Response from the Remote Server.

So in my case for normal behaviour with correct Cache handling it should be like:

try
{
    ...
    var webResponse = req.GetResponse();
    ...
}
catch (WebException ex)
{
    if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotModified)
        throw;
    Log.Error("Unknown error occured", ex);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文