I am trying to deploy a simple cloud function on firebase, together with a ajax front-end call of that function. The front-end call sends a .pdf file to the cloud function, that further process it. Both FE and BE were tested on firebase:emulators and were working as expected. The biggest problem is that I am not sure how to debug this problem, because even if the console throws a CORS error, it is probably something else. The last log from the firebase cloud functions console says
Function execution took 29 ms, finished with status code: 404
while in the console, the error is
Access to XMLHttpRequest at 'https://us-central1-paperfire-ada3a.cloudfunctions.net/api/upload' from origin 'https://paperfire-ada3a.web.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Cors is set up using the express library in the backend. Here is the backend code:
const axios = require('axios');
const cors = require('cors')
const admin = require('firebase-admin');
const { getStorage, ref, uploadBytes, getDownloadURL } = require('firebase-admin/storage');
const express = require('express');
const pdfParse = require('pdf-parse');
const { OpenAI } = require("openai");
const openai = new OpenAI({apiKey:'api-key'});
const app = express();
var serviceAccount = require("./paperfire-ada3a-firebase-adminsdk-k5cno-361bebbe1e.json");
const MAX_FILE_SIZE = 16 * 1024 * 1024; // 16 MB
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://paperfire-ada3a-default-rtdb.europe-west1.firebasedatabase.app",
storageBucket: 'gs://paperfire-ada3a.appspot.com'
});
// Automatically allow cross-origin requests
app.use(cors({ origin: true }));
// Handling preflight requests
app.options('*', cors());
app.get('/', (req, res) => {
res.send('Welcome to the PDF processing API. Use the /upload endpoint to upload files.');
});
app.post('/upload', async (req, res) => {
...
});
const runtimeOpts = {
timeoutSeconds: 300, // Set timeout to 5 minutes
memory: '1GB' // Adjust memory based on your function's needs
};
exports.api = functions.runWith(runtimeOpts).https.onRequest(app);
And here is the front-end call to the /upload route:
firebase.auth().currentUser.getIdToken(true).then(function(idToken) {
var form = $('#uploadForm')[0];
var formData = new FormData(form);
// Perform the AJAX request
$.ajax({
type: 'POST',
url: 'https://us-central1-paperfire-ada3a.cloudfunctions.net/api/upload',
data: formData,
contentType: false, // This is required for FormData with file upload
processData: false, // Also required for FormData with file upload
headers: {
'Authorization': 'Bearer ' + idToken // Include the ID token in the request headers
},
success: function(response) {
console.log(response.extractedText)
if(response.audioUrl) {
...
The main question here is what is wrong with my cloud function and how do I figure it out for other cases in the future? The console and the log doesn't seem to help too much, while the emulator environment is not able to fill all the test cases. Thank you very much, I appreciate any help!
As @John Hanley mentioned in the comments, the issue was not with my cors setup. The function was never reaching my cloud function due to Google Frontend blocking my request. The only way I was able to solve this issue was to access my cloud function from the Google Cloud console and set the permissions for Cloud functions Invoker to allUsers
. This is a temporal solution and maybe other answers will provide more context, but the problem is solved for now. I still have to figure out a way to set this variable for production, because it is a security risk.