Unfortunately Flutter ignores any proxy settings on your device or simulator and this prevents the use of Charles Proxy to debug network I/O. Luckily, you can override HTTP requests using HttpOverrides
, such that all requests are routed through a app-defined proxy.
First, let's create a custom class CustomProxy
to store the the ip and port, and also provide easy to use enable() and disable() methods, in addition to toString() and fromString() helpers that will make it easy to store the info in shared preferences. (You will have an error first, we'll add CustomProxyHttpOverride
below.)
import 'dart:io';
import 'package:flutter/foundation.dart';
/// @todo move all of this to separate package!
/// A public-facing class
class CustomProxy {
/// A string representing an IP address for the proxy server
final String ipAddress;
/// The port number for the proxy server
/// Can be null if port is default.
final int port;
/// Initializer
CustomProxy({@required this.ipAddress, this.port});
/// Initializer from string
/// Note: Uses static method, rather than named init to allow final properties.
static CustomProxy fromString({@required String proxy}) {
// Check if valid
if(proxy == null || proxy == "") {
assert(false, "Proxy string passed to CustomProxy.fromString() is invalid.");
return null;
}
// Build and return
final proxyParts = proxy.split(":");
final _ipAddress = proxyParts[0];
final _port = proxyParts.length > 0 ? int.tryParse(proxyParts[1]) : null;
return CustomProxy(
ipAddress: _ipAddress,
port: _port,
);
}
/// Enable the proxy
void enable() {
HttpOverrides.global =
new CustomProxyHttpOverride.withProxy(this.toString());
}
/// Disable the proxy
void disable() {
HttpOverrides.global = null;
}
@override
String toString() {
String _proxy = this.ipAddress;
if (this.port != null) {
_proxy += ":" + this.port.toString();
}
return _proxy;
}
}
Next we need to create the class that will override HttpOverrides
. This is the class that will override our default HTTP requests and route them through the proxy:
/// This class overrides the global proxy settings.
class CustomProxyHttpOverride extends HttpOverrides {
/// The entire proxy server
/// Format: "localhost:8888"
String proxyString;
/// Initializer
CustomProxyHttpOverride.withProxy(String proxy) {
this.proxyString = proxy;
}
/// Override HTTP client creation
@override
HttpClient createHttpClient(SecurityContext context) {
return super.createHttpClient(context)
..findProxy = (uri) {
assert(this.proxyString != null && this.proxyString.isNotEmpty,
'You must set a valid proxy if you enable it!');
return "PROXY " + this.proxyString + ";";
}
..badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
}
}
Now that we have our base classes, enabling the proxy is clean and easy...let's put the following code in our main.dart
file:
// You can get the stored shared preferences here if you have an in-app settings panel to set up the proxy settings....
final proxy = new CustomProxy(ipAddress: "localhost", port: 8888);
proxy.enable();
runApp(MyApp());