Apollo REST 数据源和 Imgur API - 使用表单数据不断收到 400 错误请求
Apollo REST Data Source and Imgur API - Keep getting 400 Bad Request using form data
我正在尝试实现 apollo-datasource-rest
以处理 URL 通过 Imgur 的 API 上传的图片(此处的文档:https://apidocs.imgur.com/)
我最初遇到 400
错误,显示为 We don't support that file type!
,并确定这是由于 apollo-datasource-rest
自动将 Content-Type
设置为 application/json
.使用 form-data
npm 包修复该问题后,我的代码如下所示:
class ImgurAPI extends RESTDataSource {
constructor() {
super();
this.baseURL = "https://api.imgur.com/3/";
}
willSendRequest(request) {
request.headers.set("Content-Type", "multipart/form-data");
request.headers.set(
"Authorization",
`Client-ID ${process.env.IMGUR_CLIENT_ID}`
);
console.log(request);
}
async uploadImageFromUrl(url) {
const formData = new FormData();
formData.append("image", url);
return this.post("upload", formData);
}
}
我现在不再收到 We don't support that file type!
错误,但我仍然收到状态文本 Bad Request
的 400
响应。上一个代码片段中的 console.log()
打印如下:
{
method: 'POST',
path: 'upload',
body: FormData {
_overheadLength: 104,
_valueLength: 80,
_valuesToMeasure: [],
writable: false,
readable: true,
dataSize: 0,
maxDataSize: 2097152,
pauseStreams: true,
_released: false,
_streams: [
'----------------------------594660553626244976225816\r\n' +
'Content-Disposition: form-data; name="image"\r\n' +
'\r\n',
'https://upload.wikimedia.org/wikipedia/commons/a/a0/Sunflower_as_gif_websafe.gif',
[Function: bound ]
],
_currentStream: null,
_insideLoop: false,
_pendingNext: false,
_boundary: '--------------------------594660553626244976225816'
},
params: URLSearchParams {},
headers: Headers {
[Symbol(map)]: [Object: null prototype] {
'Content-Type': [Array],
Authorization: [Array]
}
}
}
我在这里错过了什么? API 似乎正在接受我的表单数据,所以我认为另一个 headers 可能存在一些问题,但在 Postman 中似乎只需要几个 headers,其中大部分是计算出来的(例如 Content-Length
),所以我假设 apollo-datasource-rest
必须处理它。
在对 multipart/form-data
做了更多研究后,我发现 boundary
参数是强制性的,必须添加到服务器请求中的 Content-Type
值中能够解析有效载荷。此外,我无法手动将其设置为请求中的参数(至少不是以实际有效的方式)。 Postman 通常在发送请求时计算此字段,但 apollo-datasource-rest
不会自动处理。
将 Content-Type
更改为 application/x-www-form-urlencoded
并使用 url 编码字符串而不是 form-data
解决了问题。
这是更新后的代码:
willSendRequest(request) {
request.headers.set("Content-Type", `application/x-www-form-urlencoded`);
request.headers.set(
"Authorization",
`Client-ID ${process.env.IMGUR_CLIENT_ID}`
);
console.log(request);
}
async uploadImageFromUrl(url) {
const formData = `image=${url}&album=${process.env.IMGUR_ALBUM_DELETE_HASH}&type=url`;
return this.post("upload", formData);
}
我正在尝试实现 apollo-datasource-rest
以处理 URL 通过 Imgur 的 API 上传的图片(此处的文档:https://apidocs.imgur.com/)
我最初遇到 400
错误,显示为 We don't support that file type!
,并确定这是由于 apollo-datasource-rest
自动将 Content-Type
设置为 application/json
.使用 form-data
npm 包修复该问题后,我的代码如下所示:
class ImgurAPI extends RESTDataSource {
constructor() {
super();
this.baseURL = "https://api.imgur.com/3/";
}
willSendRequest(request) {
request.headers.set("Content-Type", "multipart/form-data");
request.headers.set(
"Authorization",
`Client-ID ${process.env.IMGUR_CLIENT_ID}`
);
console.log(request);
}
async uploadImageFromUrl(url) {
const formData = new FormData();
formData.append("image", url);
return this.post("upload", formData);
}
}
我现在不再收到 We don't support that file type!
错误,但我仍然收到状态文本 Bad Request
的 400
响应。上一个代码片段中的 console.log()
打印如下:
{
method: 'POST',
path: 'upload',
body: FormData {
_overheadLength: 104,
_valueLength: 80,
_valuesToMeasure: [],
writable: false,
readable: true,
dataSize: 0,
maxDataSize: 2097152,
pauseStreams: true,
_released: false,
_streams: [
'----------------------------594660553626244976225816\r\n' +
'Content-Disposition: form-data; name="image"\r\n' +
'\r\n',
'https://upload.wikimedia.org/wikipedia/commons/a/a0/Sunflower_as_gif_websafe.gif',
[Function: bound ]
],
_currentStream: null,
_insideLoop: false,
_pendingNext: false,
_boundary: '--------------------------594660553626244976225816'
},
params: URLSearchParams {},
headers: Headers {
[Symbol(map)]: [Object: null prototype] {
'Content-Type': [Array],
Authorization: [Array]
}
}
}
我在这里错过了什么? API 似乎正在接受我的表单数据,所以我认为另一个 headers 可能存在一些问题,但在 Postman 中似乎只需要几个 headers,其中大部分是计算出来的(例如 Content-Length
),所以我假设 apollo-datasource-rest
必须处理它。
在对 multipart/form-data
做了更多研究后,我发现 boundary
参数是强制性的,必须添加到服务器请求中的 Content-Type
值中能够解析有效载荷。此外,我无法手动将其设置为请求中的参数(至少不是以实际有效的方式)。 Postman 通常在发送请求时计算此字段,但 apollo-datasource-rest
不会自动处理。
将 Content-Type
更改为 application/x-www-form-urlencoded
并使用 url 编码字符串而不是 form-data
解决了问题。
这是更新后的代码:
willSendRequest(request) {
request.headers.set("Content-Type", `application/x-www-form-urlencoded`);
request.headers.set(
"Authorization",
`Client-ID ${process.env.IMGUR_CLIENT_ID}`
);
console.log(request);
}
async uploadImageFromUrl(url) {
const formData = `image=${url}&album=${process.env.IMGUR_ALBUM_DELETE_HASH}&type=url`;
return this.post("upload", formData);
}