proxy_getter 1.2.0 copy "proxy_getter: ^1.2.0" to clipboard
proxy_getter: ^1.2.0 copied to clipboard

A Flutter FFI plugin project for reading system proxy settings.

example/lib/main.dart

import 'dart:io';

import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/material.dart';
import 'package:proxy_getter/proxy_getter.dart';

const String kCoverUrl =
    'https://coverartarchive.org/release/690eda44-dae6-45c3-9b75-30c524df11e5/front';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final proxy = await getSystemProxy();
  HttpOverrides.global = _SystemProxyHttpOverrides(proxy);
  runApp(MyApp(proxy: proxy));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key, required this.proxy});

  final SystemProxy proxy;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF243B53)),
        useMaterial3: true,
      ),
      home: ProxyTestPage(proxy: proxy),
    );
  }
}

class ProxyTestPage extends StatefulWidget {
  const ProxyTestPage({super.key, required this.proxy});

  final SystemProxy proxy;

  @override
  State<ProxyTestPage> createState() => _ProxyTestPageState();
}

class _ProxyTestPageState extends State<ProxyTestPage> {
  final Dio _dio = Dio();
  late SystemProxy _currentProxy;
  String _dioStatus = 'Idle';
  String _dioDetails = '';
  bool _loading = false;
  int _imageVersion = 0;

  @override
  void initState() {
    super.initState();
    _currentProxy = widget.proxy;
    _updateDioProxy(_currentProxy);
    _loadImageByDio();
  }

  void _updateDioProxy(SystemProxy proxy) {
    _dio.httpClientAdapter = IOHttpClientAdapter(
      createHttpClient: () {
        final client = HttpClient();
        client.findProxy = (uri) {
          if (!proxy.enable || proxy.host.isEmpty || proxy.port <= 0) {
            return 'DIRECT';
          }
          return 'PROXY ${proxy.host}:${proxy.port}';
        };
        return client;
      },
    );
  }

  Future<void> _handleRefresh() async {
    setState(() {
      _loading = true;
    });

    try {
      // 1. Refresh proxy status
      final newProxy = await getSystemProxy();
      HttpOverrides.global = _SystemProxyHttpOverrides(newProxy);
      _updateDioProxy(newProxy);
      
      // 2. Clear image cache to force reload
      PaintingBinding.instance.imageCache.clear();
      PaintingBinding.instance.imageCache.clearLiveImages();

      setState(() {
        _currentProxy = newProxy;
        _imageVersion++;
      });

      // 3. Reload Dio request
      await _loadImageByDio();
    } catch (e) {
      debugPrint('Refresh failed: $e');
    } finally {
      if (mounted) {
        setState(() {
          _loading = false;
        });
      }
    }
  }

  Future<void> _loadImageByDio() async {
    setState(() {
      _loading = true;
      _dioStatus = 'Loading';
      _dioDetails = '';
    });

    try {
      final response = await _dio.get<List<int>>(
        kCoverUrl,
        options: Options(responseType: ResponseType.bytes),
      );
      final bytes = response.data?.length ?? 0;
      final contentType = response.headers.value('content-type') ?? 'unknown';

      if (!mounted) return;
      setState(() {
        _dioStatus = 'Success';
        _dioDetails = 'Bytes: $bytes\nContent-Type: $contentType';
      });
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _dioStatus = 'Failed';
        _dioDetails = e.toString();
      });
    } finally {
      if (mounted) {
        setState(() {
          _loading = false;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final proxy = _currentProxy;
    return Scaffold(
      appBar: AppBar(
        title: const Text('Proxy Getter Test'),
        actions: [
          IconButton(
            onPressed: _loading ? null : _handleRefresh,
            icon: const Icon(Icons.refresh),
            tooltip: 'Refresh All',
          ),
        ],
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _InfoCard(
            title: 'System Proxy',
            child: Text(
              [
                'Enabled: ${proxy.enable}',
                'Host: ${proxy.host}',
                'Port: ${proxy.port}',
                'Bypass: ${proxy.bypass}',
              ].join('\n'),
            ),
          ),
          const SizedBox(height: 16),
          _InfoCard(
            title: 'Dio Request',
            child: Text(
              'Status: $_dioStatus\n\n$_dioDetails',
            ),
          ),
          const SizedBox(height: 16),
          _InfoCard(
            title: 'Image.network',
            child: ClipRRect(
              borderRadius: BorderRadius.circular(16),
              child: Image.network(
                kCoverUrl,
                key: ValueKey('image_$_imageVersion'),
                fit: BoxFit.cover,
                loadingBuilder: (context, child, loadingProgress) {
                  if (loadingProgress == null) return child;
                  return SizedBox(
                    height: 260,
                    child: Center(
                      child: CircularProgressIndicator(
                        value: loadingProgress.expectedTotalBytes == null
                            ? null
                            : loadingProgress.cumulativeBytesLoaded /
                                loadingProgress.expectedTotalBytes!,
                      ),
                    ),
                  );
                },
                errorBuilder: (context, error, stackTrace) {
                  return SizedBox(
                    height: 260,
                    child: Center(
                      child: Text(
                        'Image load failed:\n$error',
                        textAlign: TextAlign.center,
                      ),
                    ),
                  );
                },
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _InfoCard extends StatelessWidget {
  const _InfoCard({required this.title, required this.child});

  final String title;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return DecoratedBox(
      decoration: BoxDecoration(
        color: Theme.of(context).colorScheme.surface,
        borderRadius: BorderRadius.circular(20),
        boxShadow: const [
          BoxShadow(
            blurRadius: 24,
            offset: Offset(0, 10),
            color: Color(0x22000000),
          ),
        ],
      ),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              title,
              style: Theme.of(context).textTheme.titleMedium?.copyWith(
                    fontWeight: FontWeight.w700,
                  ),
            ),
            const SizedBox(height: 12),
            child,
          ],
        ),
      ),
    );
  }
}

class _SystemProxyHttpOverrides extends HttpOverrides {
  _SystemProxyHttpOverrides(this.proxy);

  final SystemProxy proxy;

  @override
  HttpClient createHttpClient(SecurityContext? context) {
    final client = super.createHttpClient(context);
    client.findProxy = (uri) {
      if (!proxy.enable || proxy.host.isEmpty || proxy.port <= 0) {
        return 'DIRECT';
      }
      return 'PROXY ${proxy.host}:${proxy.port}';
    };
    return client;
  }
}
1
likes
150
points
140
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter FFI plugin project for reading system proxy settings.

Repository (GitHub)
View/report issues

License

Apache-2.0 (license)

Dependencies

flutter, flutter_rust_bridge, plugin_platform_interface

More

Packages that depend on proxy_getter

Packages that implement proxy_getter