Search code examples
javascriptgatsbynetlifyjamstacknetlify-form

Netlify form fetching a GET instead of POST request on submit


I have a basic Netlify form (based on this guide) with name, email and message fields. With the following submit function:

const handleSubmit = event => {
    event.preventDefault();
    const data = {};
    const scopedForm = [...formState];

    let isValidForm = validateForm(scopedForm);
    setFormState([...scopedForm]);

    if (!isValidForm) return false;

    formInputs.forEach(input => data[input.name] = input.value);

    fetch(`/`, {
      method: `POST`,
      headers: {
        'Accept': `application/x-www-form-urlencoded;charset=UTF-8`,
        'Content-Type': `application/x-www-form-urlencoded`,
      },
      body: encode({
        'form-name': `Contact Form`,
        ...data,
      }),
    })
      .then(() => console.log(`OK`))
      .catch(error => alert(error));
  };

  const encode = data => {
    return Object.keys(data)
      .map(key => encodeURIComponent(key) + `=` + encodeURIComponent(data[key]))
      .join(`&`);
  };

Pretty simple, besides the validations, I create a data object and I fill it with a pair of data[input.name] = input.value. Everything works as expected locally, as well as in develop and build mode. I can see a POST request, however, in production, it turns into a GET:

Fetch request in production

I've tried changing the built-in fetch to axios but the result is the same. I don't know if I need to add some custom configuration in my server or how to bypass this.

My resulting HTML structure is:

<form name="Contact Form" method="POST" action="/" data-netlify="true" data-netlify-honeypot="bot-field" data-netlify-recaptcha="true">
   <div><label for="form-name"><input type="hidden" name="form-name" value="Contact Form"></label></div>
   <div><label for="bot-field"><input type="hidden" name="bot-field" value=""></label></div>
   <div><label for="name">Name:<input type="text" name="name" value="Chancellor Lawson"></label></div>
   <div><label for="email">Email:<input type="text" name="email" value="[email protected]"></label></div>
   <div><label for="message">Message:<textarea name="message">Ea quisquam ea vel e</textarea></label></div>
   <button type="submit">Send</button>
</form>

I have read a lot of similar issues, articles, and guides but none helped.


Solution

  • In order to close the issue, I will answer my own question, giving all the merits to Quentin. As he pointed out, the solution was removing the Accept header since it only was accepting application/x-www-form-urlencoded;charset=UTF-8 requests. So the header should look like:

      headers: {
        'Content-Type': `application/x-www-form-urlencoded`,
      },
    

    From MDN documentation:

    The Accept request HTTP header advertises which content types, expressed as MIME types, the client is able to understand. Using content negotiation, the server then selects one of the proposals, uses it and informs the client of its choice with the Content-Type response header. Browsers set adequate values for this header depending on the context where the request is done: when fetching a CSS stylesheet a different value is set for the request than when fetching an image, video, or script.