如何使用fetch

时间:2017-04-19 15:50:28

标签: node.js curl fetch-api http-content-length isomorphic-fetch-api

这是一个正常的CURL示例:

curl -X POST \
  <url> \
  -H 'authorization: Bearer <token>' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -F file=@algorithm.jpg \
  -F userId=<userId>

我尝试使用isomorphic-fetch重现此请求。

我尝试过以下代码:

const formData = new FormData();
formData.append('file', file);
formData.append('userId', userId);

return fetch(`<url>`, {      
  method: 'POST',
  headers: {
    'Content-Length': file.length
    'Authorization: Bearer <authorization token>',
    'Content-Type': 'multipart/form-data'
  },
  body: formData
})`

我使用fs.readFileSync来生成传递给file的{​​{1}}。

上一个示例返回FormData HTTP状态代码(未授权),并显示一条错误消息,指出令牌中嵌入的401(通过标头发送)与通过的userId不匹配来自userId

所以我怀疑到达REST API的formData没有充分形成。

问题可能与FormData标题有关,但我没有找到更好的计算方法(如果我不使用Content-Length标题,我会得到一个Content-Length缺少HTTP状态代码411标头。)

由于Content-Length标题中的值不正确,可能会失败吗?

关于为何失败或如何更好地调试它的任何其他建议?

如果需要进一步的信息来澄清这个问题,请问问。

更新

我已尝试form-data模块,以便使用Content-Length

方法获取正确的Content-Length

但问题仍然存在(formData.getLengthSync()错误HTTP状态代码响应。)

2 个答案:

答案 0 :(得分:3)

如果您打开网络检查员,请运行此代码段,然后提交您应该看到Content-Length设置正确的表单:

const foo = document.getElementById('foo')
foo.addEventListener('submit', (e) => {
  e.preventDefault()
  const formData = new FormData(foo)
  formData.append('userId', 123)
  fetch('//example.com', {
    method: 'POST',
    body: formData
  })
})
<form id="foo">
  <input id="file" type="file" name="file"/><br><br>
  <button type="submit">Submit</button>
</form>

答案 1 :(得分:2)

我撞到了类似的墙,特别是在节点上使用isomorphic-fetch来发布一个多部分表单。我的关键是找到.getHeaders()。请注意,NPM description for form-data表明它“只是工作”没有这个,但似乎没有,至少在节点中没有(我认为浏览器会注入标题内容吗?)。

// image is a Buffer containing a PNG image
// auth is the authorization token

const form_data  = new FormData();
form_data.append("image", png, {
    filename: `image.png`,
    contentType: 'application/octet-stream',
    mimeType: 'application/octet-stream'
});

const headers = Object.assign({
    'Accept': 'application/json',
    'Authorization': auth,
}, form_data.getHeaders());

try {
    const image_res = await fetch(url, {
        method: 'POST',
        headers: headers,
        body: form_data
    });

    if (!image_res.ok) {
        const out = await image_res.json();
        console.dir(out);
        return;
    }
}
catch (e) {
    console.error(`Chart image generation exception: ${e}`);
}