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
调用。
我正在尝试向 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
调用。