Flutter Web开发代理服务器插件web_dev_proxy_shelf的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter Web开发代理服务器插件web_dev_proxy_shelf的使用

一个实现了CORS和Cookie CORS的Web开发代理服务器,基于shelf_proxy。

特性

  • 在Web开发中修改响应头和Cookie以支持CORS

入门指南

步骤1

在Dart文件中定义目标主机和本地代理主机及端口,类似于:

class LocalProxyConfig {
  static String targetUrl = 'https://navi-api.xxx.tech';
  static const String localHost = 'localhost';
  static const int localPort = 8033;

  static const String localProxyUrlWeb = "http://$localHost:$localPort";
}

步骤2

在另一个Dart文件中定义主方法:

import 'package:web_dev_proxy/src/shelf_proxy_for_web_dev.dart';

import 'proxy_web_local_config.dart';

Future<void> main() async {
  await startLocalProxyServerForWebDebug(
      LocalProxyConfig.localHost,
      LocalProxyConfig.localPort,
      LocalProxyConfig.targetUrl,
      true);
}

步骤3

运行步骤2中的主方法

Proxying at http://localhost:8033 for https://navi-api.xxx.tech

步骤4

当平台为Web时,在项目中使用LocalProxyConfig.localProxyUrlWeb作为基本URL。

代理做了什么?

修改响应头以允许请求CORS

类似于在Web发布时使用Nginx进行操作。

// 修改响应头
// 有时后台写了Access-Control-Allow-Origin,那么server.defaultResponseHeaders的设置就会无效
// if("OPTIONS" == (clientResponse?.request?.method??"")){
Map<String, String> headers = clientResponse.headers;
// 不能同时多个
headers.remove('access-control-allow-origin');
headers.remove('access-control-allow-methods');
headers.remove('access-control-allow-headers');
headers.remove('access-control-expose-headers');
headers.remove('access-control-max-age');
headers.remove('access-control-allow-credentials');

// 你请求什么,就允许什么
// access-control-request-headers 这个是chrome加了,所以在request!.headers里取不到
// Request header field app-version is not allowed by Access-Control-Allow-Headers in preflight response.
// Map<String, String> reqeustHeaders = clientResponse!.request!.headers!;
String headerStr = clientResponse!.request!
    .headers['access-control-request-headers'].toString();
// 预检请求不会携带额外的header,所以下面拼接header没有鸟用, 要用access-control-request-headers取
// reqeustHeaders.forEach((key, value) { headerStr = headerStr+","+key; });
// access-control-request-headers

if (headerStr == "null") {
  headerStr = "*";
}
clientResponse.headers['Access-Control-Allow-Headers'] = headerStr;
// clientResponse.headers['Access-Control-Allow-Headers'] = "*";//预检请求里,['Access-Control-Allow-Credentials'] = 'true'时 不能用*
clientResponse.headers['Access-Control-Allow-Methods'] = "*";  // GET,POST,PUT,OPTIONS
clientResponse.headers['Access-Control-Expose-Headers'] = headerStr;
clientResponse.headers['Access-Control-Max-Age'] = '36000'; // 如果chrome开启了禁用缓存,那么每次都会发预检请求
clientResponse.headers['Access-Control-Allow-Credentials'] = 'true';
// 预检请求: 设置了-Allow-Credentials'] = 'true'时,两个限制:
// Access-Control-Allow-Origin'] 不能为 "*"  -Allow-Headers'] = "*"

// clientResponse.headers['Access-Control-Allow-Origin'] = "*";
String original = clientResponse!.request!.headers["Referer"].toString();
if(original == "null"){
  original = "*";
}
if (original.endsWith("/")) {
  original = original.substring(0, original.length - 1);
}
clientResponse.headers['Access-Control-Allow-Origin'] = original;
// The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
// The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

修改Set-Cookie头部

void transferCookies(http.StreamedResponse clientResponse, String localHost) {
  String? cookie = clientResponse.headers['set-cookie'];
  if (cookie == null || cookie.isEmpty) {
    return;
  }
  // 服务器要发送多个 cookie,则应该在同一响应中发送多个 Set-Cookie 标头。
  Cookie cookie2 = Cookie.fromSetCookieValue(cookie);
  cookie2.secure = true;
  cookie2.httpOnly = false;
  cookie2.domain = localHost;
  clientResponse.headers['set-cookie'] = cookie2.toString() + ";SameSite=None;";

  print("reset set-cookie header from $cookie to \n ${clientResponse.headers['set-cookie']}\n");
}

更多关于Flutter Web开发代理服务器插件web_dev_proxy_shelf的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter Web开发代理服务器插件web_dev_proxy_shelf的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter Web开发中,有时我们需要代理请求来避免跨域问题或进行本地开发调试。web_dev_proxy_shelf 是一个用于 Flutter Web 开发的代理服务器插件,它基于 shelf 框架,允许你在开发过程中轻松地代理请求。

安装 web_dev_proxy_shelf

首先,你需要在 pubspec.yaml 文件中添加 web_dev_proxy_shelf 依赖:

dev_dependencies:
  web_dev_proxy_shelf: ^0.1.0

然后运行 flutter pub get 来安装依赖。

使用 web_dev_proxy_shelf

  1. 创建代理服务器配置文件

    在你的 Flutter 项目根目录下创建一个 webdev_proxy.yaml 文件,用于配置代理规则。例如:

    proxies:
      - path: /api
        target: https://api.example.com

    在这个例子中,所有以 /api 开头的请求都会被代理到 https://api.example.com

  2. 启动 Flutter Web 开发服务器

    在终端中运行以下命令来启动 Flutter Web 开发服务器,并使用 web_dev_proxy_shelf 代理请求:

    flutter pub run web_dev_proxy_shelf

    这将启动一个本地服务器,并应用你在 webdev_proxy.yaml 中配置的代理规则。

  3. 访问你的 Flutter Web 应用

    启动服务器后,你可以通过 http://localhost:8080 访问你的 Flutter Web 应用。所有符合代理规则的请求都会被代理到指定的目标地址。

自定义端口和配置

你可以通过命令行参数来自定义端口和其他配置。例如:

flutter pub run web_dev_proxy_shelf --port=8081 --config=my_proxy_config.yaml
  • --port:指定服务器监听的端口,默认为 8080
  • --config:指定代理配置文件的路径,默认为 webdev_proxy.yaml

示例项目结构

一个典型的项目结构可能如下所示:

my_flutter_web_project/
├── lib/
   └── main.dart
├── web/
   └── index.html
├── pubspec.yaml
├── webdev_proxy.yaml
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!