Flutter Web 跨域请求踩坑笔记

3,211 阅读1分钟

解决方案:Proxy + CORS

为了节省大家的时间,废话不多说直接上代码

1.首先我们需要在 pubspec.yaml 引入 shelf_proxy:

dev_dependencies:
  shelf_proxy: ^1.0.0

2.在lib目录创建 proxy.dart

import 'dart:io';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_proxy/shelf_proxy.dart';


final String target = 'http://api.test.com/'; // api地址
final String imgTarget = 'https://img.test.com/'; // 图片地址

void configServer(HttpServer server) {
  // 这里设置请求策略,允许所有
  server.defaultResponseHeaders.add('Access-Control-Allow-Origin', '*');
  server.defaultResponseHeaders.add('Access-Control-Allow-Credentials', true);
  server.defaultResponseHeaders.add('Access-Control-Allow-Methods', '*');
  server.defaultResponseHeaders.add('Access-Control-Allow-Headers', '*');
  server.defaultResponseHeaders.add('Access-Control-Max-Age', '3600');
}

void main() async {
  var reqHandle = proxyHandler(target);
  var imgHandle = proxyHandler(imgTarget);

  /// 绑定本地端口,4500,转发到真正的服务器中
  var server = await shelf_io.serve(reqHandle, 'localhost', 4500);
  var imgServer = await shelf_io.serve(imgHandle, 'localhost', 4501);

  configServer(server);
  configServer(imgServer);

  print('Api Serving at http://${server.address.host}:${server.port}');
  print('Img Serving at http://${imgServer.address.host}:${imgServer.port}');
}

  1. 运行代理服务器 dart proxy.dart

  2. 设置请求的BaseUrl为 http://localhost:4500 , 图片的BaseUrl为 http://localhost:4501

  3. 在web/index.html的<head></head>标签内添加 <meta name="referrer" content="never"> 防止图片403

  4. 测试

ajax.dart

import 'package:dio/dio.dart';
import 'request_interceptor.dart';
import 'log_interceptor.dart';

class Ajax {
  final String baseUrl = '';

  late Dio _dio;

  Ajax._init() {
    init();
  }

  static final Ajax _ajax = Ajax._init();

  factory Ajax() {
    return _ajax;
  }

  void init({bool debug = false}) async {
    var _options = BaseOptions(
      baseUrl: debug ? 'http://localhost:4500' : 'https://api.test.com',
      contentType: Headers.formUrlEncodedContentType,
      receiveTimeout: 10 * 1000,
      connectTimeout: 10 * 1000,
    );

    _dio = Dio(_options);

    _dio.interceptors.add(RequestInterceptor());
    _dio.interceptors.add(MyLogInterceptor());
  }

  Future<Response<T>> send<T>(
    String path, {
    String method = 'GET',
    data,
    Map<String, dynamic>? queryParameters,
    CancelToken? cancelToken,
    Options? options,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) {
    return _dio.request(
      path,
      options: Options(method: method),
      queryParameters: queryParameters,
      data: data,
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
      cancelToken: cancelToken,
    );
  }
}

main.dart

void main() {
  Ajax().init(debug: true);
  
  Ajax().send('/api/test', method: 'POST', data: data)
  .then((res) {})
  .catch((e) {})
  
  runApp(MyApp());
}