c# - Xamarin Forms WebView 代理

标签 c# android xamarin proxy xamarin.forms

如何让 iOS 和 Android 强制所有 http/s 请求通过代理?本地化到应用程序,而不是整个操作系统?

我已经在 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,我也尝试过实现 WebClient 并覆盖 shouldoverrideurlloading 但 Xamarin 似乎对 HttpWebRequest 和 https 调用有问题,提示

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

最佳答案

不幸的是,覆盖 WebClient shouldInterceptRequest 有一些问题,例如拦截 html 以外的任何内容,但我设法通过这种方式解决了我的问题:

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;
    }
}

关于c# - Xamarin Forms WebView 代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44709920/

相关文章:

c# - 在现有 Xamarin.Forms 共享应用程序中实现 Prism

c# - 比较 List<string> 是否包含字符串 C#

c# - 具有特殊 F801 字符的 SQL Server nchar 和 .Net unicode

android - Mp android图表,带条形渐变背景的条形图

android - 创建 Stack Overflow 通知器

android - 与 GooglePlayServicesUtil 的奇怪对话

c# - 使用数据集的gridview分页

c# - Web API 返回 JSON 但不返回 Xml

ios - Xamarin 图像集不导入

ios - 如何将iOS 9.0 SDK与Xamarin关联来编译默认应用程序?