2

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)
        );
2
  • So, why don't you just set the Content-Type header? Commented Oct 29, 2020 at 11:13
  • Thank you for your help, @Peter. Unfortunately, setting the header headers: { 'Content-Type': 'multipart/form-data', 'Authorization': 'basic ' + props.getToken() } leads to exactly the same problem. Commented Oct 29, 2020 at 11:25

1 Answer 1

0

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

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for your help, Andres. I can reproduce the behavior as the Authorization header is not sent to the backend in this case, unfortunately.
The Fetch documentation states that mode: "no-cors" does not allow Authorization headers.
What I saw is if leaving mode as default (cors) won't send automatically the Content-type header which forces you to send explicitly the Content-Type header making sure you send an appropriate boundary. (Something like: Content-Type: multipart/form-data; boundary="a boundary") I have tried different combinations to achieve the behaviour you want, but no luck

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.