Google API 批量请求返回 411 Length-Required 错误

Google APIs Batch Requests returning 411 Length-Required Error

我正在尝试向 Gmail API 发出批量请求,如下所述:https://developers.google.com/gmail/api/guides/batch

我已经到了我的请求 URL、headers 和 body 的地步,并且 headers 包括一个(准确) Content-Length 属性。但是,当我向 Gmail 批处理请求端点发出 POST 请求时,响应是 [411 Length-Required][1] 响应,在 body 中返回一个 HTML文件说明:

411. That’s an error.

POST requests require a Content-length header. That’s all we know.

我的代码如下所示:

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:googleapis/gmail/v1.dart';
import 'package:http/http.dart' as http;

class GoogleClient {
  static const _SCOPES = const [GmailApi.GmailReadonlyScope];
  static GoogleSignIn _googleSignIn = GoogleSignIn(scopes: _SCOPES);
  static String _gmailUrl = 'https://www.googleapis.com/gmail/v1/users/';
  static String _batchGmailUrl = 'https://www.googleapis.com/batch/gmail/v1';
  final FirebaseAuth _auth = FirebaseAuth.instance;

  GoogleSignInAccount _user;

  Future<List<Message>> fetchEmailsBatch({List<String> gmailMessageIds}) async {
    await _ensureUserIsAuthenticated();

    final boundary = 'batch_email';

    var body = '--' + boundary + '\r\n';

    for (String id in gmailMessageIds) {
      final messageUrl = '/gmail/v1/users/' + _user.email + '/messages/' + id;

      body += 'Content-Type: application/http\r\n';
      body += 'Content-ID: email:' + id + '\r\n\r\n';
      body += 'GET ' + messageUrl + '\r\n\r\n';
      body += '--' + boundary + '\r\n';
    }

    final bodyAsBytes = utf8.encode(body);
    final headers = await _batchAuthHeaders(bodyAsBytes.length);

    final response = await http.post(_batchGmailUrl,
        headers: await _batchAuthHeaders(bodyAsBytes.length),
        body: bodyAsBytes);
  }

  Future<Map<String, String>> _batchAuthHeaders(int length) async {
    var headers = await _user.authHeaders;

    headers[HttpHeaders.contentLengthHeader] = length.toString();
    headers[HttpHeaders.contentTypeHeader] =
        'multipart/mixed; boundary=batch_email';
    headers[HttpHeaders.hostHeader] = 'www.googleapis.com';

    return headers;
  }

  Future<void> _ensureUserIsAuthenticated() async {
    if (_user == null) {
      await signIn();
    }
  }
}

如您所见,在批处理请求的 body 中进行的所有 sub-requests 都是 GET 请求,因此不在错误消息 I' 中我正在接收。我似乎找不到上面已链接的任何更广泛的文档,也找不到 GitHub 或 Whosebug 上已报告的任何其他类似问题。

如有任何帮助,我们将不胜感激 - 提前致谢!

[1]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/411#:~:text=The%20HyperText%20Transfer%20Protocol%20(HTTP,a%20defined%20Content%2DLength% 20 标题。

这是 Flutter 中报告的错误,此后已修复。在撰写本文时,它在版本中尚不可见,但希望它很快就会出现。

作为临时解决方法,您可以改用较低级别的 dart:io 调用。