0

I am trying to query an Amazon RDS database from a Firebase Node JS cloud function. I built the query and can successfully run the code locally using firebase functions:shell. However, when I deploy the function and call it from client-side js on my site I receive errors on both the client and server side.

Client-side:

Error: internal
Origin http://localhost:5000 is not allowed by Access-Control-Allow-Origin.
Fetch API cannot load https://us-central1-*****.cloudfunctions.net/query due to access control checks.
Failed to load resource: Origin http://localhost:5000 is not allowed by Access-Control-Allow-Origin.

Server-side:

Function execution took 60004 ms, finished with status: 'timeout'

I believe the issue has two parts:

  1. CORS
  2. pool.query() is async

I have looked at multiple questions for a CORS solution, here and here for example, but none of the solutions have worked for me. In regards to pool.query() being async I believe I am handling it correctly however neither the result nor an error is printed to the servers logs.

Below is all the relevant code from my projects.

Client-side:

var queryRDS = firebase.functions().httpsCallable('query');
queryRDS({
     query: document.getElementById("search-input").value
})
.then(function (result) {
     if (result) {
          console.log(result)
     }
})
.catch(function (error) {
     console.log(error);
});

Server-side:

const functions = require('firebase-functions');
const { Pool } = require('pg');

const pool = new Pool({
    user: 'postgres',
    host: '*****.*****.us-west-2.rds.amazonaws.com',
    database: '*****',
    password: '*****',
    port: 5432
})

exports.query = functions.https.onCall((data, context) => {
     // This is not my real query, I just changed it for the
     // simplicity of this question
     var query = "Select * FROM table"

     pool.query(query)
          .then(result_set => {
               console.log(result_set)
               return result_set
          }).catch(err => {
               console.log(err)
               return err
          })
})

I know everything works up until pool.query(), based on my logs it seems that the .then() or the .catch() are never reached and the returns never reach the client-side.

Update:

I increased the timeout of the Firebase Functions from 60s to 120s and changed my server function code by adding a return statment before pool.query():

return pool.query(query)
     .then(result_set => {
          console.log(result_set)
          return result_set
     }).catch(err => {
          console.log("Failed to execute query: " + err)
          return err
     })

I now get an error message reading Failed to execute query: Error: connect ETIMEDOUT **.***.***.***:5432 with the IP address being my AWS RDS database. It seems this might have been the underlying problem all along, but I am not sure why the RDS is giving me a timeout.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Bernard
  • 1,004
  • 1
  • 12
  • 21
  • I was able to connect to AWS RDS from Firebase function, probably because I had the RDS inbound rule set to all IP address (i.e. 0.0.0.0/0). – Fanchen Bao Dec 04 '21 at 05:52

1 Answers1

0

The CORS should be automatically handled by the onCall handler. The error message about CORS is likely to be inaccurate, and a result of the function timing out, as the server side error is showing.

That being said, according to the Cloud Functions Documentation on Function's Timeout, the default timeout for Cloud Functions is of 60 seconds, which translated to the ~60000 ms on your error message, and this means that 1 minute is not enough for your function to execute such query, which makes sense if your consider that the function is accessing an external provider, which is the Amazon RDS database.

In order to fix it you will have to redeploy your function with a flag for setting the function execution timeout, as follows:

gcloud functions deploy FUNCTION_NAME --timeout=TIMEOUT

The Value of TIMEOUT could be anything until 540, which is the maximum seconds that Cloud Functions allows before timeout (9 minutes).

NOTE: This could also be mitigated by deploying your function to the closest location possible to where your Amazon RDS database is located, you can check this link on what locations are available for Cloud Functions and you can use --region=REGION on the deploy command to specify region to be deployed.

Ralemos
  • 5,571
  • 2
  • 9
  • 18
  • I was not able to set the timeout using your provided command, I had to use this [answer](https://stackoverflow.com/a/43911779/5569399). However, this did not fix the issue. When I run the code locally it executes the function in 50ms. Uploading to Firebase Functions should not cause a slow down of over 100x! When I increased the timeout to 120s I do now get a return error from my pool saying `Error: connect ETIMEDOUT **.***.***.***:5432` – Bernard Aug 13 '20 at 17:02
  • Are you behind a proxy either on GCP or Amazon? It could also be a firewall blocking it on either side of the operations. – Ralemos Aug 14 '20 at 14:34