jimmywarting / FormData

HTML5 `FormData` polyfill for Browsers and nodejs
MIT License
360 stars 102 forks source link

How to send a form with additional headers in node.js with fetch #140

Closed GrosSacASac closed 2 years ago

GrosSacASac commented 2 years ago

uploadFile.js

import "../source/patchNode/fetch.js";
import "../source/patchNode/File_Blob.js";
import "../source/patchNode/FormData.js";
import fs from "node:fs";

const fd = new FormData()

// fd.append('myfiles', fs.createReadStream('./tests/uploadFile.js')); //form-data
fd.append('myfiles', new File(['./tests/uploadFile.js'], 'uploadFile.js')); // formdata-polyfill

// user/upload/folder
fetch(
    'http://localhost:8999/aaa/u/test',
    {
        method: 'POST',
        body: fd,
        headers: {
            'Host': 'localhost:8999',
            'Referer': 'http://localhost:8999/aaa/u',
            'Cookie': 'l=6c93178e06bb537d2c036872c40147a86c96',
            // ...fd.getHeaders(), // only in form-data
        }
    },
).then(response => {
    if (!response.ok) {
        console.log(response)
        console.log("not ok")
    }
    return response.text();
}).then(text => {
    console.log(text);
}).catch(console.error)

patchNode/FormData.js

if (!globalThis.FormData) {
    globalThis.FormData = (await import("formdata-polyfill/esm.min.js")).FormData;
    // globalThis.FormData = (await import("form-data")).default;
    console.log(globalThis.FormData);
}

I make a simple POST request with a FormData When I use formdata-polyfill library with fetch and use additional headers, the most important header with Content-Type and boundary gets lost. (replaced by text/plain)

When I use form-data library I can access getHeaders { 'content-type': 'multipart/form-data; boundary=--------------------------971495223106834682165883' } and with ...append it to my headers before making the fetch.

How to send a form with additional headers in node.js with fetch

    "node-fetch": "^2.6.6",
    "fetch-blob": "^3.1.3",
    "form-data": "^4.0.0",
    "formdata-polyfill": "^4.0.10",
GrosSacASac commented 2 years ago

Solution was to use node-fetch 3.1.0

jimmywarting commented 2 years ago

tip, if you want to have same FormData dependency as node-fetch without additional imports in packages json then you could do:

import {Response} from 'node-fetch'

const FormData = (await new Response(new URLSearchParams).formData()).constructor
const Blob = (await new Response().blob()).constructor

// Hack to get the same file class:
const fd = new FormData(); fd.set('x', new Blob())
const File = fd.get('x').constructor