Sending multipart/form-data with authorization header from react

Viewed 2214

I am trying to send a POST request with form data from a React frontend to a Go backend.

const upload = () => {
        let data = new FormData();
        data.append('file', file);
        data.append('namespace', namespace);
        const requestOptions = {
            headers: { 'Authorization': 'basic ' + props.getToken() },
            method: 'POST',
            body: data
        };
        fetch(`${process.env.REACT_APP_BACKEND_URL}/upload`, requestOptions)
            .then(
                response => alert(response.status)
            ).catch(
                error => console.log(error)
            );
    };

On the backend side, I am trying to access the data the following way:

func uploadHandler(w http.ResponseWriter, r *http.Request) {
    // Read content
    r.ParseMultipartForm(10 << 20)
    file, fileHeader, err := r.FormFile("file")
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(fileHeader)
    var buf bytes.Buffer
    io.Copy(&buf, file)
    yamlData := buf.Bytes()
    namespace := r.FormValue("namespace")
    ...
}

However, I am receiving the following error:

request Content-Type isn't multipart/form-data

Also, the fileHeader is nil.

The only possible solution I found was to remove the header as mentioned in this post, but encoding the authorization token in the POST body is of course not my preferred way of fixing this issue.

As the question was asked already and I wasn't clear about this one: Setting the headers to

headers: { 'Content-Type': 'multipart/form-data', 'Authorization': 'basic ' + props.getToken() }

leads to the same problem.

PS: React fetch seems to automatically generate a header such as the following:

multipart/form-data; boundary=----WebKitFormBoundarykm4IEyyauWp42XvA

When setting another header manually, the fetch API does not apply this header. A potential solution might be to combine the headers, however I have no idea how this could work.

PPS: Trying the same with axios leads to the same issue.

axios({
    method: 'POST',
    url: `${process.env.REACT_APP_BACKEND_URL}/upload`,
    data: data,
    headers: { 'Content-Type': 'multipart/form-data', 'Authorization': 'basic ' + props.getToken() }
    })
        .then(
            response => alert(response.status)
        ).catch(
            error => console.log(error)
        );
1 Answers

I think adding mode: "no-cors" to your requestOptions will help. There's something odd with this library I couldn't figured out and it's that even sending explicitly the Authorization header I can't see it in the backend, so you might need an extra configuration to be sure that header is sent.

I tested the back end and that definitely works as expected (tested with Postman sending Content-Type: multipart/form-data and an attached file

Related