2016/4/22

UWP - A redirect request will change a secure to a non-secure connection

該篇主要説明使用 Windows.Web.Http.HttpClient 遇到裏面的 Header 需要 Redirect 出現 A redirect request will change a secure to a non-secure connection 的解決方式。

情況是這樣的:

1. 今天在使用 HttpClient 打 API 的時候,遇到 SendRequestAsync 之後就會拿到如下圖的結果:   
  可以看到幾個關鍵的訊息:
  • Exception thrown: 'System.AggregateException' in mscorlib.ni.dll
  • The text associated with this error code could not be found. A redirect request will change a secure to a non-secure connection

    説明原本的 request 被 redirect 到另一個不安全的 URL 的地方(例如 https 導向 http)。

2. 仔細去查了相關的文獻發現HttpClient 預設是會自動 redirect 的:

所以給 HttpClient 一個自定的 HttpBaseProtocolFilter,如下:
private void HttpClient GetHttpClient()
{
    var httpFilter = new HttpBaseProtocolFilter();
    httpFilter.CacheControl.ReadBehavior = HttpCacheReadBehavior.MostRecent;
    httpFilter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.NoCache;
    // 關掉自動 redirect 的功能
    httpFilter.AllowAutoRedirect = false;
    return new HttpClient(httpFilter);
}

這個時候就可以發現 redirect 被放在 response 的 Header 里説明 Status Code 跟 redirect URL,如下圖:


發現它被倒入另一個 https 的 URL,這個跟 A redirect request will change a secure to a non-secure connection 好像沒有任何關係。

問題來了 Status Code = 302 (Found),明確的告訴 HttpClient 需要導向,但是目的 URL 是 HttpClient 不認識的 URL,所以就會一直出現錯誤

也許你會問,把要去的那個 URL 加入到 package.appxmanifest 的安全名單 <uap:ApplicationContentUriRules /> 可以嗎?答案: 一樣沒有辦法解決


3. 自行爲 HttpClient 開發遇到 Status Code = 320 的 redirect 任務:
public HttpCompletionOption CompletionOption { get; set; } = HttpCompletionOption.ResponseContentRead;

private void InvokeAPI()
{
   // 取得 HttpClient
   using (HttpClient client = GetHttpClient()) 
   {
       HttpRequestMessage request = new HttpRequestMessage();
    redirectMsg.RequestUri = new Uri("{Your API URL}");
       // 利用遞回的方式完成 redirect    
    var result = LoopRedirect(client, httpRequestMessage, timeout).Result;
   }
}

private async Task<HttpResponseMessage> LoopRedirect(HttpClient client, HttpRequestMessage httpRequestMessage, int timeout)
{
   var cancellationToken = (cancellationTokenSource == null ? CancellationToken.None : cancellationTokenSource.Token);
   var sendTask = client.SendRequestAsync(httpRequestMessage, CompletionOption).AsTask(cancellationToken);
   var response = sendTask.Result;
   if (response.StatusCode == Windows.Web.Http.HttpStatusCode.Found)
   {
       var redirectMsg = new HttpRequestMessage();
       redirectMsg.RequestUri = new Uri(response.Headers.Location.AbsoluteUri);
       return await LoopRedirect(client, redirectMsg, timeout);
   }
   else
   {
       return response;
   }
}

利用遞回的方式來完成 redirect 就可以解決 HttpClient 在自動 redirect 遇到的問題。

======
這個問題我在 8.1 (UAP) 的開發上是正常的,我不確定是不是新的 UWP 又做了什麽調整。
但是可以確定的是如果遇到 HttpClient 需要被 redirect 失敗時,還是手動自己做會比較安全。
建議把 http 都變成 https 吧!!

References:

沒有留言:

張貼留言