2017-06-22 162 views
1

如何讓iOS和Android通過代理強制所有http/s請求?本地化到應用程序,而不是整個操作系統?Xamarin Forms WebView代理

我已經試過這爲Android,但它並不適用於https使用:

JavaSystem.setProperty("http.proxyHost", <your proxy host name>); 
JavaSystem.setProperty("http.proxyPort", <your proxy port>); 
JavaSystem.setProperty("https.proxyHost", <your proxy host name>); 
JavaSystem.setProperty("https.proxyPort", <your proxy port>); 

對於Android的我也試圖實現Web客戶端和壓倒一切的shouldoverrideurlloading但Xamarin似乎與HttpWebRequest和HTTPS調用問題,抱怨

Error: SecureChannelFailure (The authentication or decryption has failed.)" 
+0

你能解釋一下你的情況?如果你希望它被本地化爲應用程序而不是系統,那麼無論你打電話到哪裏,都可以編寫一個包裝函數? –

回答

0

我認爲一個簡單的方法來實現這個是使用RestSharp library

然後你可以用下面的代碼:

var client = new RestClient("http://example.com") 
client.Proxy = new WebProxy("http://proxy.example.com") 

如果您的請求到不同的服務器,我認爲你可以沒有域創建RestClient,然後使用RestRequest指定完整的請求URL。這客戶端可能是靜態的,或者是一個單身。

我希望這可以幫助你。

1

不幸的是壓倒一切的shouldInterceptRequest存在一些問題,如不是HTML攔截任何其他Web客戶端,但我設法解決我的問題是這樣的:

public class DawgWebViewClient: WebViewClient 
{ 
    private class DawgWebResourceResponse : WebResourceResponse 
    { 
     IWebResourceRequest baseRequest; 
     public DawgWebResourceResponse(IWebResourceRequest request) : base(null, null, null) 
     { 
      this.baseRequest = request; 
      this.LoadRequestAsync(); 
     } 

     ManualResetEvent responseDataWaiter = new ManualResetEvent(false); 
     ManualResetEvent metaDataWaiter = new ManualResetEvent(false); 
     private void LoadRequestAsync() 
     { 
      Task.Run(async() => 
      { 
       HttpClient client = new HttpClient(new ModernHttpClient.NativeMessageHandler()); 
       foreach(var header in this.baseRequest.RequestHeaders) 
       { 
        client.DefaultRequestHeaders.Add(header.Key, header.Value); 
       } 

       HttpResponseMessage response; 
       switch(this.baseRequest.Method) 
       { 
        case "GET": 
         response = await client.GetAsync(this.baseRequest.Url.ToString()); 
         break; 
        default: 
         response = null; 
         Debugger.Break(); 
         break; 
       } 

       string 
        mediaType = response.Content.Headers.ContentType?.MediaType ?? "*/*", 
        charSet = response.Content.Headers.ContentType?.CharSet ?? "UTF-8"; 

       this.MimeType = mediaType; 
       this._statusCode = (int)response.StatusCode; 
       this.ResponseHeaders = response.Headers.ToDictionary(y => y.Key, y => y.Value.FirstOrDefault()); 
       metaDataWaiter.Set(); 

       this.Data = await response.Content.ReadAsStreamAsync(); 

       responseDataWaiter.Set(); 
      }); 
     } 

     public override Stream Data 
     { 
      get { 
       this.responseDataWaiter.WaitOne(); 
       return base.Data; 
      } 
      set 
      { 
       base.Data = value; 
      } 
     } 

     public override IDictionary<string, string> ResponseHeaders 
     { 
      get 
      { 
       this.metaDataWaiter.WaitOne(); 
       return base.ResponseHeaders; 
      } 
      set 
      { 
       base.ResponseHeaders = value; 
      } 
     } 

     private int _statusCode = 0; 
     public override int StatusCode 
     { 
      get 
      { 
       this.metaDataWaiter.WaitOne(); 
       return this._statusCode; 
      } 
     } 
     public override string Encoding 
     { 
      get 
      { 
       this.metaDataWaiter.WaitOne(); 
       return base.Encoding; 
      } 
      set 
      { 
       base.Encoding = value; 
      } 
     } 

     public override string ReasonPhrase 
     { 
      get 
      { 
       this.metaDataWaiter.WaitOne(); 
       return base.ReasonPhrase; 
      } 
     } 

     public override string MimeType 
     { 
      get 
      { 
       this.metaDataWaiter.WaitOne(); 
       return base.MimeType; 
      } 
      set 
      { 
       base.MimeType = value; 
      } 
     } 
    } 

    public override WebResourceResponse ShouldInterceptRequest(Android.Webkit.WebView view, IWebResourceRequest request) 
    { 
     if(request.RequestHeaders["Accept"]?.Contains("text/html") == true) return new DawgWebResourceResponse(request); 
     return null; 
    } 
}