a web dev proxy server that has implement request cors and cookie cors, base on shelf_proxy

Features

  • Modify response headers and cookie for cors in web dev

Getting started

step1

Define your target host and local proxy host and port in a dart file ,just like :

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";

}

step2

define a main method in another dart file:

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);
}

step3

Run the main method in step2

Will print:

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

step4

use LocalProxyConfig.localProxyUrlWeb as your base url in project when platform is web.

what did we do in the proxy

modify headers to allow request cros

just like what you will do in nginx when release in web

// 修改响应头
  //有时后台写了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.

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");
}

Thanks

https://pub.dev/packages/shelf_proxy

跨域资源共享 CORS 详解

浏览器同源政策及其规避方法

Libraries

web_dev_proxy
Support for doing something awesome.