Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cloud Functions for Firebase triggering function on CORS preflight request

I have a cloud function that validates inputs from a form submission on my client. I'm using Cloud Functions for Firebase https triggers with cors express middleware.

Firebase Function

const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors')({origin: true});
const validateImageForm = require('./library/validate-image-form');

exports.apiValidateImageForm = functions.https.onRequest((req, res) => {

  cors(req, res, () => {

    validateImageForm(req.body.formInputs, req.body.imageStatus).then((data) => {
      res.status(200).send(data);
    });

  });

});

Client Call To Function

const validateImageFormFetchOptions = {
   headers: {
     'Accept': 'application/json',
     'Content-Type': 'application/json'
   },
   method: 'POST',
   body: JSON.stringify({
     formInputs: formInputs
   })
}

fetch('https://project-url.cloudfunctions.net/apiValidateImageForm', validateImageFormFetchOptions)
 .then(response => response.json())
 .then(serverErrors => {console.log(serverErrors)});

Issue

When I call this function from my client using a fetch request I see two apiValidateImageForm triggers in the functions logs. The first is a status 204 and I assume this comes from the cors preflight request that checks the origin. The final request is status 200. I just want one function trigger when I fetch the apiValidateImageForm function. I'm concerned that over time the preflight requests that output the status 204 will add unnecessary function calls to my project quota.

enter image description here

Question

Is it possible to prevent firebase from triggering a function call on the preflight request? If not then is there a way to prevent the preflight request and successfully pass data to the function.

like image 933
Celso Avatar asked Sep 22 '17 17:09

Celso


People also ask

Does firebase use HTTP requests?

Requests on your Firebase Hosting site can be proxied to specific HTTP functions. This also allows you to use your own custom domain with an HTTP function.

How do I enable Cors in Firebase?

You can enable CORS by installing cors library in your functions folder: npm i cors --save Here is an example of usage: const functions = require('firebase-functions'); const cors = require('cors'); exports.addMessage = functions.https.onRequest((req, res) => { cors() (req, res, () => { return res.json({status: 'ok'}); }); });

What is Cloud Functions for Firebase?

Please try again later. Cloud Functions for Firebase is a serverless framework that lets you automatically run backend code in response to events triggered by Firebase features and HTTPS requests. Your JavaScript or TypeScript code is stored in Google's cloud and runs in a managed environment.

What does the URL of a firebase project include?

The URL includes the following, in order: The region (or regions) to which you deployed your function. Some production functions may need to explictly set the locationto minimize network latency. Your Firebase project ID

What is the difference between Firebase CLI and cloud build?

The Firebase CLI creates a .zip archive of the function code, which is then uploaded to a Cloud Storage bucket (prefixed with gcf-sources) in your Firebase project. Cloud Build retrieves the function code and builds the function source.


1 Answers

To fix the duplicate requests 200 and 204 then change how you're client side fetch request. @sideshowbarker is right. The browser automatically does the CORS preflight OPTIONS request so this is not an issue in Cloud Functions for Firebase. This answer was helpful.

To fix the preflight I changed my code to the following:

Client Call To Function

Removed the headers from the fetch options completely rather than setting the content type as application/json. By default the fetch request content type is application/x-www-form-urlencoded; charset=UTF-8.

const validateImageFormFetchOptions = {
  method: 'POST',
  body: JSON.stringify({
   formInputs: formInputs
  })
}

fetch('https://project-url.cloudfunctions.net/apiValidateImageForm', validateImageFormFetchOptions)
  .then(response => response.json())
  .then(serverErrors => {console.log(serverErrors)});

Firebase Function

Explicitly parsed the request body because it is now received as a text string.

const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors')({origin: true});
const validateImageForm = require('./library/validate-image-form');

exports.apiValidateImageForm = functions.https.onRequest((req, res) => {
  cors(req, res, () => {
    const body = JSON.parse(req.body);
    validateImageForm(body.formInputs, body.imageStatus).then((data) => {
      res.status(200).send(data);
    });
  });
});
like image 146
Celso Avatar answered Nov 03 '22 01:11

Celso