我正在为我正在为Windows Phone 8开发的应用程序面临一个非常复杂的问题。以下端点 - http://speedmeter3.internetprovsechny.cz:81/ping/ - 可用于衡量连接客户端的延迟。结果存储为JSON字符串并返回。但是,要执行测量,使用了多个HTTP 302(Found)重定向(始终返回到相同的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}
任何能够为此提供解决方案的人都将获得赏金(三天之后;-))。
谢谢大家
答案 0 :(得分:3)
我猜测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语法。
答案 1 :(得分:0)
我偶然发现了一个类似的问题,但与HttpClient
没有从https
重定向到http
网站有关。这似乎是设计使然(See GitHub issue)。
但是,即使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()))