You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter iOS端如何拦截WebView的所有请求?

解决Flutter WebView跨平台捕获所有HTTP请求的思路

思路一:利用flutter_inappwebview的onLoadResource事件

这个事件在iOS和Android平台都会触发,每次WebView加载资源(包括页面、图片、脚本、XHR、Fetch请求等)时都会回调,能直接获取请求的URL和头信息,完全满足跨平台获取请求数据的需求。

示例代码:

InAppWebView(
  initialUrlRequest: URLRequest(url: Uri.parse("https://example.com")),
  onLoadResource: (controller, request) async {
    // 获取请求URL
    String requestUrl = request.url.toString();
    // 获取请求头
    Map<String, String> requestHeaders = request.headers;
    
    // 处理获取到的请求信息
    print("请求URL: $requestUrl");
    print("请求头: $requestHeaders");
  },
)

注意:该事件在资源加载完成后触发,若需要在请求发送前拦截,此方法不适用,但仅用于获取请求URL和头信息时完全可行。

思路二:重写JS请求方法实现持续监听

如果需要在请求发送前捕获信息,可以通过重写XMLHttpRequest和Fetch的原型方法,让每次请求都将信息传递给Flutter端。关键是确保重写代码在页面脚本执行前生效,且页面跳转/刷新后依然有效。

实现步骤:

  1. 创建JS拦截文件(比如assets/request_interceptor.js):
// 重写XMLHttpRequest
(function() {
  const originalOpen = XMLHttpRequest.prototype.open;
  XMLHttpRequest.prototype.open = function(method, url) {
    this._requestInfo = {
      method: method,
      url: url,
      headers: {}
    };
    originalOpen.apply(this, arguments);
  };

  const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
  XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
    if (this._requestInfo) {
      this._requestInfo.headers[header] = value;
    }
    originalSetRequestHeader.apply(this, arguments);
  };

  const originalSend = XMLHttpRequest.prototype.send;
  XMLHttpRequest.prototype.send = function() {
    if (window.flutter_inappwebview) {
      window.flutter_inappwebview.callHandler('onRequestCaptured', this._requestInfo);
    }
    originalSend.apply(this, arguments);
  };
})();

// 重写Fetch
(function() {
  const originalFetch = window.fetch;
  window.fetch = function(url, options) {
    const requestInfo = {
      method: options?.method || 'GET',
      url: typeof url === 'string' ? url : url.toString(),
      headers: options?.headers ? Object.fromEntries(options.headers.entries()) : {}
    };
    if (window.flutter_inappwebview) {
      window.flutter_inappwebview.callHandler('onRequestCaptured', requestInfo);
    }
    return originalFetch.apply(this, arguments);
  };
})();
  1. 在Flutter中配置注入并监听回调:
InAppWebView(
  initialUrlRequest: URLRequest(url: Uri.parse("https://example.com")),
  initialSettings: InAppWebViewSettings(
    javaScriptEnabled: true,
    // 确保JS在页面内容加载前注入执行
    injectedJavaScriptBeforeContentLoaded: await rootBundle.loadString('assets/request_interceptor.js'),
  ),
  onWebViewCreated: (controller) {
    // 注册JS调用的Flutter回调
    controller.addJavaScriptHandler(
      handlerName: 'onRequestCaptured',
      callback: (args) {
        Map<String, dynamic> requestInfo = args[0];
        String url = requestInfo['url'];
        Map<String, dynamic> headers = requestInfo['headers'];
        print("捕获到请求:URL=$url,Headers=$headers");
      },
    );
  },
)

该方案能覆盖XMLHttpRequest和Fetch请求,且页面跳转后新页面的请求依然会被捕获。

思路三:自定义原生扩展(复杂场景)

如果上述方法无法满足需求(比如需要拦截WebView原生发起的所有请求),可以针对双平台分别实现原生拦截:

  • iOS端:使用WKNavigationDelegate的webView(_:decidePolicyFor:decisionHandler:)方法,在请求发送前获取URL和头信息,通过MethodChannel传递给Flutter。
  • Android端:继续使用shouldInterceptRequest方法保持原有逻辑。
    这种方式需要编写原生代码,但能实现最全面的请求拦截能力。

内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:32:13