繁体   English   中英

在WP8上使用HttpClient处理HTTP 302

[英]Handling HTTP 302 with HttpClient on WP8

我为Windows Phone 8开发的应用程序遇到了一个非常复杂的问题。以下端点-http: //speedmeter3.internetprovsechny.cz :81/ ping/ -可用于测量已连接客户端的延迟。 结果存储为JSON字符串并返回。 但是,为了执行测量,使用了多个HTTP 302(已找到)重定向​​(始终返回相同的URL)。 结果可以在浏览器中正确返回,并且我已经看到许多方法可以解决Android上的类似问题,但是没有一种方法可以在Windows Phone上使用。 这是我应该返回字符串的简单代码片段:

HttpClientHandler handler = new HttpClientHandler();
handler.AllowAutoRedirect = true;     
HttpClient client = new HttpClient( handler );
string url = "http://speedmeter3.internetprovsechny.cz:81/ping/";
return await client.GetStringAsync( new Uri( url, UriKind.Absolute ) );

这段代码在GetStringAsync方法上挂了一段时间,并最终以异常终止:

System.Net.Http.HttpRequestException: Response status code does not indicate success: 302 (Found).
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at IPVSpeedmeter.Helpers.RestClient.<SendGetSafe>d__8.MoveNext()}    System.Exception {System.Net.Http.HttpRequestException}

只要有可能,任何能够提供解决方案的人都将获得赏金(三天后;-))。

谢谢你们

我猜想Win8的实现可能不会妨碍自动重定向。 这是我使用的重定向处理程序:

    public class GlobalRedirectHandler : DelegatingHandler {

    public GlobalRedirectHandler(HttpMessageHandler innerHandler) {
       InnerHandler = innerHandler;
    } 

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
        var tcs = new TaskCompletionSource<HttpResponseMessage>();

        base.SendAsync(request, cancellationToken)
            .ContinueWith(t => {
                HttpResponseMessage response;
                try {
                    response = t.Result;
                }
                catch (Exception e) {
                    response = new HttpResponseMessage(HttpStatusCode.ServiceUnavailable);
                    response.ReasonPhrase = e.Message;
                }
                if (response.StatusCode == HttpStatusCode.MovedPermanently
                    || response.StatusCode == HttpStatusCode.Moved
                    || response.StatusCode == HttpStatusCode.Redirect
                    || response.StatusCode == HttpStatusCode.Found
                    || response.StatusCode == HttpStatusCode.SeeOther
                    || response.StatusCode == HttpStatusCode.RedirectKeepVerb
                    || response.StatusCode == HttpStatusCode.TemporaryRedirect

                    || (int)response.StatusCode == 308) 
                {

                    var newRequest = CopyRequest(response.RequestMessage);

                    if (response.StatusCode == HttpStatusCode.Redirect 
                        || response.StatusCode == HttpStatusCode.Found
                        || response.StatusCode == HttpStatusCode.SeeOther)
                    {
                        newRequest.Content = null;
                        newRequest.Method = HttpMethod.Get;

                    }
                    newRequest.RequestUri = response.Headers.Location;

                    base.SendAsync(newRequest, cancellationToken)
                        .ContinueWith(t2 => tcs.SetResult(t2.Result));
                }
                else {
                    tcs.SetResult(response);
                }
            });

        return tcs.Task;
    }

    private static HttpRequestMessage CopyRequest(HttpRequestMessage oldRequest) {
        var newrequest = new HttpRequestMessage(oldRequest.Method, oldRequest.RequestUri);

        foreach (var header in oldRequest.Headers) {
            newrequest.Headers.TryAddWithoutValidation(header.Key, header.Value);
        }
        foreach (var property in oldRequest.Properties) {
            newrequest.Properties.Add(property);
        }
        if (oldRequest.Content != null) newrequest.Content = new StreamContent(oldRequest.Content.ReadAsStreamAsync().Result);
        return newrequest;
    }
}

我确实应该清理它以使用async / await语法。

我偶然发现了一个类似的问题,但与HttpClient无法从https重定向到http站点有关。 这似乎是设计使然请参阅GitHub问题 )。

但是,我要求http客户端遵循重定向,即使它们不安全,因此这是我要解决的一种解决方案,它与Darrel Miller非常相似。

public class RedirectHandler : DelegatingHandler
{
    private static readonly HttpStatusCode[] RedirectOn = {
        HttpStatusCode.MovedPermanently,
        HttpStatusCode.Found
    };

    public RedirectHandler(HttpMessageHandler innerHandler)
    {
        InnerHandler = innerHandler;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken)
            .ConfigureAwait(false);

        if (request.Method == HttpMethod.Get && RedirectOn.Contains(response.StatusCode))
        {
            request.RequestUri = response.Headers.Location;

            return await base.SendAsync(request, cancellationToken)
                .ConfigureAwait(false);
        }

        return response;
    }
}

可以由以下人员使用:

var client = new HttpClient(new RedirectHandler(new HttpClientHandler()))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM