如果您的 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 参考。