Flutter SDK - Intercepting the network
Intercepting the network
Section titled Intercepting the networkCall patchNetwork() once, after starting the tracker:
import 'package:openreplay/openreplay.dart';
OpenReplay.instance.patchNetwork();
This installs an HttpOverrides, chaining to whatever was installed before, and captures every dart:io HttpClient call — which covers package:http’s IOClient and Dio’s default adapter. It is idempotent; unpatchNetwork() restores the previous overrides.
The tracker’s own ingest traffic is never captured: its HttpClient is constructed directly, bypassing the overrides.
Network options
Section titled Network optionsORNetworkOptions mirrors the web tracker’s network options:
capturePayload: boolRecords request and response bodies. Default:false— bodies are dropped unless you opt in.ignoreHeaders: List<String>Header names to drop, compared case-insensitively. Default:['cookie', 'set-cookie', 'authorization'].ignoreAllHeaders: boolDrops every header. (The web tracker expresses this asignoreHeaders: true; Dart has no such union type, so it is a separate flag.) Default:false.failuresOnly: boolRecords only responses outside the 2xx range. Default:false.sessionTokenHeader: String?When set, a header of this name carrying the session token is added to outgoing requests, so your backend logs can be correlated with the replay. Default:null.sanitizer: ORRequestResponse? Function(ORRequestResponse)?Last say over what is recorded. Default:null.
OpenReplay.instance.patchNetwork(const ORNetworkOptions(
capturePayload: true,
failuresOnly: true,
sessionTokenHeader: 'X-OpenReplay-Session',
));
Sanitizing the request
Section titled Sanitizing the requestThe sanitizer receives one ORRequestResponse per captured call and returns it — mutated as you like — or null to drop the call entirely.
OpenReplay.instance.patchNetwork(ORNetworkOptions(
capturePayload: true,
sanitizer: (record) {
if (record.url.contains('/internal/')) return null; // drop it
record.url = record.url.replaceAll(RegExp(r'token=[^&]+'), 'token=***');
record.requestHeaders.remove('x-api-key');
final body = record.requestBody;
if (body is Map) body.remove('password');
return record;
},
));
ORRequestResponse carries url, method, status, duration, requestHeaders, responseHeaders, requestBody and responseBody. Bodies are decoded when they parse as JSON, so the sanitizer gets an object rather than a string — matching the web tracker’s behaviour.
Recording calls manually
Section titled Recording calls manuallyA custom Dio adapter (or any client that bypasses HttpOverrides) needs its own interceptor:
OpenReplay.instance.networkRequest(
url: 'https://api.example.com/cart',
method: 'POST',
requestJson: '{"sku":"A1"}',
responseJson: '{"ok":true}',
status: 200,
duration: 132, // ms
);
GraphQL operations have their own message, for use with the OpenReplay gql plugins:
OpenReplay.instance.graphQL(
operationKind: 'query',
operationName: 'GetCart',
variables: '{"id":"42"}',
response: '{"data":{...}}',
duration: 87,
);
Have questions?
Section titled Have questions?If you have any questions about this process, feel free to reach out to us on our Slack or check out our Forum.