You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart http包POST响应缺失Postman中存在的Location等响应头问题

问题描述

核心问题:目前在Dart中发起POST请求时,无法获取到Postman调试同接口时返回的部分响应头,应用需要读取这些头的取值才能正常运行,需要找到获取Dart侧未返回、但Postman中存在的响应头的方法。
日常使用Dart/Flutter的http package基本可以满足所有开发需求,但近期遇到问题:该包在处理POST请求响应时,不会返回部分非标准响应头。当前发起的请求示例如下:

POST https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4/Patient?_format=json&_pretty=false
Headers: {"Content-Type": "application/fhir+json", "Authorization": "Bearer $BearerToken"}
Body: {"resourceType":"Patient","identifier":[{"type":{"coding":[{"system":"http://hl7.org/fhir/sid/us-ssn","code":"SB"}]
},"system":"urn:oid:2.16.840.1.113883.4.1","value":"444114567"}],"name":[{"use":"usual","text":"Derrick
Lin","family":"Lin","given":["Derrick"]}],"gender":"male","birthDate":"1973-06-03"}

该请求本身执行成功,返回201状态码,已在服务端确认Patient资源已成功创建,但Dart侧拿到的响应头仅包含以下字段:

{
  "cache-control": "no-cache,no-store", 
  "content-length": 0, 
  "content-type": "application/fhir+json; charset=utf-8", 
  "expires": -1, 
  "pragma": "no-cache"
}

发起请求前已做断点校验,确认所有请求参数完全正确;将完全相同的参数填入Postman发起请求,同样返回201状态码,但可以拿到完整的响应头如下:

{
  "Expires": -1, 
  "Location": "Patient/eoc0yXThvv5aQEdz-kjaSWQ3",
  "Allow-Control-Allow-Headers": "origin, authorization, accept, content-type, x-requested-with, Epic-User-ID, Epic-User-IDType, Epic-Client-ID, soapaction, Epic-MyChartUser-ID, Epic-MyChartUser-IDType",
  "Allow-Control-Allow-Methods": "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS",
  "Allow-Control-Allow-Origin": "*",
  "Allow-Control-Allow-Credentials": true,
  "cache-control": "no-cache,no-store", 
  "content-length": 0, 
  "content-type": "application/fhir+json; charset=utf-8", 
  "pragma": "no-cache"
}

需要在Dart中获取这些额外的响应头,尤其是Location头。

现有请求实现逻辑

请求构造流程:首先走OAuth2流程获取Bearer token,之后通过继承http.Client的自定义类调用POST方法,相关实现代码如下:

@override
  Future<http.Response> post(Uri url,
          {Map<String, String>? headers,
          Object? body,
          Encoding? encoding}) async =>
      await http.post(
        url,
        headers: await newHeaders(headers),
        body: body,
        encoding: encoding,
      );

  @override
  Future<Map<String, String>> newHeaders(Map<String, String>? headers) async {
    headers ??= <String, String>{};
    if (client?.credentials.accessToken != null) {
      headers['Authorization'] = 'Bearer ${client!.credentials.accessToken}';
    }
    headers.addAll(authHeaders ?? <String, String>{});
    return headers;
  }

当前请求确实执行成功,资源正常提交创建,返回201状态码,但始终无法拿到完整的响应头,需要定位问题是由请求构造方式错误、http包本身缺陷,还是Dart SDK的问题导致。

问题原因与解决方案

该问题与请求构造错误、http包缺陷、Dart SDK问题均无直接关系,核心原因分两类运行场景:

  • Flutter Web运行场景
    浏览器CORS同源策略默认仅暴露少量安全响应头给上层代码,你当前能拿到的cache-control、content-length、content-type、expires、pragma都在默认暴露白名单内。需要的Location头及其他自定义响应头不在默认暴露列表中,必须由服务端在响应中添加Access-Control-Expose-Headers字段,明确声明允许前端读取的头字段,浏览器才会将这些头传递给Dart层代码。
    Postman作为独立接口调试工具,不受浏览器CORS规则限制,因此可以拿到全部响应头。
    处理方式:联系接口提供方,在跨域响应中添加Access-Control-Expose-Headers配置,将Location及其他需要读取的头加入暴露列表,示例:
    Access-Control-Expose-Headers: Location, Allow-Control-Allow-Headers, Allow-Control-Allow-Methods, Allow-Control-Allow-Origin, Allow-Control-Allow-Credentials
    
  • 移动端/桌面端原生运行场景
    你当前自定义Client的写法不规范:重写post方法时直接调用了顶层http.post函数,该函数会内部创建独立的临时Client发送请求,不会继承自定义Client的完整处理逻辑,少数场景下会出现响应头解析不全的问题。
    处理方式:不要调用顶层http.post方法,改为通过父类send方法构造、发送请求,修正后的代码示例:
    @override
    Future<http.Response> post(Uri url,
        {Map<String, String>? headers,
        Object? body,
        Encoding? encoding}) async {
      final request = http.Request('POST', url);
      request.headers.addAll(await newHeaders(headers));
      if (body != null) {
        request.body = body is String ? body : jsonEncode(body);
      }
      if (encoding != null) {
        request.encoding = encoding;
      }
      final streamedResponse = await send(request);
      return http.Response.fromStream(streamedResponse);
    }
    
    注意http包的响应头是大小写不敏感的,读取时不需要严格匹配Postman中的字段大小写,直接通过response.headers['location']即可读取对应值。

内容的提问来源于stack exchange,提问作者Grey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 13:03:22