如果您的 app 使用了 WebView,您可以通过以下方式拦截和转发请求:
shouldInterceptRequest
回调中,使用 OkHttp 发送请求。基于 OkHttp 请求结果构造原生 WebResourceResponse 响应。警告
对于没有在控制台添加的域名,HTTPDNS 服务端的解析会失败,您只能获得 Local DNS 服务器的解析结果。参见 添加需要解析的域名了解如何添加域名。
使用 shouldInterceptRequest
拦截请求。
注意
shouldInterceptRequest
不能拦截带有 body 的请求。如果您的请求带有 body,body 会丢失。shouldInterceptRequest
无法正常拦截请求。String targetUrl = "https://www.bytedance.com"; WebView webView = findViewById(R.id.webviewid); webView.setWebViewClient(new WebViewClient() { // API >= 21 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { String scheme = request.getUrl().getScheme().trim(); String method = request.getMethod(); Map<String, String> headerFields = request.getRequestHeaders(); String url = request.getUrl().toString(); Log.d(TAG, "intercept request for url: " + url); ... } return super.shouldInterceptRequest(view, request); } @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { // API < 21 时,shouldInterceptRequest 无法正常拦截请求 return super.shouldInterceptRequest(view, url); } );
在 shouldInterceptRequest
回调中,使用 OkHttp 转发请求。基于 OkHttp 请求结果构造原生 WebResourceResponse
响应。
// 使用 OkHttp 转发请求 // 无法拦截 body,拦截方案只能正常处理不带 body 的请求; if (method.equalsIgnoreCase("get")) { try { OkHttpClient okHttpClient = new OkHttpClient.Builder().dns(new Dns() { @Override public List<InetAddress> lookup(String hostname) throws UnknownHostException { long beforeResolve = System.currentTimeMillis(); // 获取解析结果 DnsResult dnsResult = HttpDns.getService().getHttpDnsResultForHostSyncBlock(hostname); if (dnsResult != null && (!dnsResult.ipv4List.isEmpty() || !dnsResult.ipv6List.isEmpty())) { StringBuilder dnsResultString = new StringBuilder("host : " + dnsResult.host + ", " + "getHttpDnsResultForHostSyncBlock cost : " + (System.currentTimeMillis() - beforeResolve) + ", " + "dns source : " + dnsResult.source + ", " + "ipv4 list : " + dnsResult.ipv4List + ", " + "ipv6 list : " + dnsResult.ipv6List + ", " + "dns result ttl: " + dnsResult.ttl + ", " + "dns request cost: " + dnsResult.rtt + ", " + "client ip: " + dnsResult.cip + "\n"); List<DnsTaskInfo> taskInfos = dnsResult.taskInfoList; for (DnsTaskInfo taskInfo : taskInfos) { dnsResultString.append(taskInfo.toJson()).append("\n"); } Log.e(TAG, "dns result " + dnsResultString); List<InetAddress> inetAddresses = new ArrayList<>(); Iterator<String> itV6 = dnsResult.ipv6List.iterator(); Iterator<String> itV4 = dnsResult.ipv4List.iterator(); while (itV6.hasNext() || itV4.hasNext()) { if (itV6.hasNext()) { inetAddresses.add(InetAddress.getByName(itV6.next())); } if (itV4.hasNext()) { inetAddresses.add(InetAddress.getByName(itV4.next())); } } return inetAddresses; } else { // 如果 HTTPDNS SDK 通过 HTTPDNS 服务端和 Local DNS 服务器的解析都失败了, // 您可以使用 OkHttp 提供的方法再次向 Local DNS 服务器发起查询请求。 return Dns.SYSTEM.lookup(hostname); } } }).build(); // 使用 OkHttp 创建请求 okhttp3.Request.Builder okRequestBuilder = new okhttp3.Request.Builder().url(url); if (headerFields != null) { for (Map.Entry<String, String> field : headerFields.entrySet()) { okRequestBuilder.header(field.getKey(), field.getValue()); } } Request okRequest = okRequestBuilder.build(); Response okResponse = okHttpClient.newCall(okRequest).execute(); String contentType = okResponse.header("Content-Type"); String mime = WebViewUtlis.getMime(contentType); String charset = WebViewUtlis.getCharset(contentType); int statusCode = okResponse.code(); String responseMessage = okResponse.message(); Log.d(TAG, "response code is " + statusCode + ", for url: " + url); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
使用 WebView.loadUrl 加载请求。
webView.loadUrl(targetUrl);
如果您需要了解 HTTPDNS Android SDK 的详细信息,参见 Android SDK 参考。