0

i am trying to build a function/endpoint that receives some values, calculates them, and returns a pass/fail and a message, hopefully it works like this:

export const processLoanRequest = functions.https.onRequest(async (request, response) => {
  // Receive values
  // determine if values they pass a criteria
  // returns true (pass) or false (fail), as well as a message that says why
  })

I tried a few things to see if I could work with it off the bat, but I don't think I even came close, like this one:

export const processLoanRequest = functions.https.onRequest((request, response) => {
  console.log({ request, response });
  const obj = {
    name: 'the object',
    param: 'object param',
  };
  response.json(obj);
});

The function I wrote in my React app to post a request is copied from MDN Web Docs -- Using Fetch and looks like:

// Example POST method implementation:
  async function postData(url = '', data = {}) {
    // Default options are marked with *
    const response = await fetch(url, {
      method: 'POST',
      mode: 'no-cors',
      cache: 'no-cache',
      credentials: 'same-origin',
      headers: {
        'Content-Type': 'application/json',
      },
      redirect: 'follow',
      referrerPolicy: 'no-referrer',
      body: JSON.stringify(data),
    });
    return response.json();
  }

  const handleSubmit = values => {
    console.log(values);
    // postLoanInfo(values).then(data => console.log(data));
    postData(
      'https://us-central1-autoloan-24e0d.cloudfunctions.net/processLoanRequest',
      { ...values }
    )
      .then(data => {
        console.log(data); // JSON data parsed by `data.json()` call
      })
      .catch(err => console.log(err));
  };

With those I always ended up with an error message that says:

SyntaxError: Unexpected end of input
    at LoanForm.js:35
    at s (runtime.js:63)
    at Generator._invoke (runtime.js:293)
    at Generator.next (runtime.js:118)
    at r (asyncToGenerator.js:3)
    at u (asyncToGenerator.js:25)

From the catch(err...), and line 35 is return response.json(); in postData(..). What happens to the body when the request is posted? How is it received at the end point and how do I access it from there?

The values object looks like:

{purchasePrice: 12000, autoMake: "kia", autoModel: "soul", yearlyIncome: 50000, creditScore: 680}

Thanks!

Update: Turns out that I had to implement Rafael's solution below, as well as response.set('Access-Control-Allow-Headers', 'Content-Type'); to get it to work. I am not very experienced so I did not think to look under the network tab in the dev tools, which gave indicated what had to change.

Update2: response.set('Access-Control-Allow-Headers', 'Content-Type'); is only needed if you're posting a request that has headers (i.e. has a body that contains values). It isn't necessary for the above example since I'm not posting anything and I'm only getting the value of obj in return.

Patrick
  • 17
  • 2
  • 5
  • 1
    The error you're getting means that the response body is not valid JSON -- most likely, you're getting back an empty body due to some other error. Off the bat, I'd guess a CORS problem (see: https://stackoverflow.com/questions/45696999/fetch-unexpected-end-of-input). You can open Chrome/Firefox's network inspector on your React site to monitor the API call as it's made to get more info on what's happening. – Robert Nubel Nov 26 '20 at 05:52

1 Answers1

0

Answering as Community Wiki as this is based on @RobertNubel's comment.

The error you are getting means that the response body is not valid JSON, which is likely to be caused by some other error in the background. You can open the browser's network inspector on your React site to monitor the API call as it's made to get more info on what's happening.

As you can see on this community question, this issue is likely to be caused by lack of CORS configuration on your response at the cloud function, in order to fix that, all you have to do is add a couple of extra lines to your functions as follows:

export const processLoanRequest = functions.https.onRequest((request, response) => {
  console.log({ request, response });
  const obj = {
    name: 'the object',
    param: 'object param',
  };
  response.set('Access-Control-Allow-Origin', "*")
  response.set('Access-Control-Allow-Methods', 'GET, POST')
  response.set('Access-Control-Allow-Headers', 'Content-Type')
  response.json(obj);
});
Ralemos
  • 5,571
  • 2
  • 9
  • 18
  • Thanks! Along with those, it turns out I needed to add `response.set('Access-Control-Allow-Headers', 'Content-Type');` to make it work. – Patrick Nov 28 '20 at 23:03
  • Good to know @Patrick, I have edited that into the answer also. – Ralemos Nov 30 '20 at 10:29
  • I forgot that `response.set('Access-Control-Allow-Headers', 'Content-Type');` is only required if you are posting a request with Headers. – Patrick Dec 01 '20 at 07:38