Search code examples
firebaseexpressgoogle-cloud-functionsfirebase-hosting

How can I using hosting rewirtes to connect between firebase hosting and cloud functions



New content for describing more specifically

I'm trying to use express and firebase function for advanced routing.

But I've got this error when I trying to get my firebase cloud function

TypeError: Cannot read property 'apply' of undefined at /Users/fredriccliver/Projects/firebase-test/functions/node_modules/express/lib/router/index.js:635:15 at next (/Users/fredriccliver/Projects/firebase-test/functions/node_modules/express/lib/router/index.js:260:14) at Function.handle (/Users/fredriccliver/Projects/firebase-test/functions/node_modules/express/lib/router/index.js:174:3) at router (/Users/fredriccliver/Projects/firebase-test/functions/node_modules/express/lib/router/index.js:47:12) at /usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:593:20 at /usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:568:19 at Generator.next () at /usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:8:71 at new Promise () at __awaiter (/usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:4:12)

/functions/index.js

const functions = require("firebase-functions")
const admin = require("firebase-admin")
const cors = require("cors")
const express = require("express")
const apiRoute = require("./api")

// admin.initializeApp(functions.config().firebase)

const app = express()
app.use(cors)

app.use("/api", apiRoute)

exports.api = functions.https.onRequest(apiRoute)

/functions/api.js

const router = require("express").Router()

router.get("/data", (req, res) => {
  res.send(`this is data`)
})

module.exports = router

Could anyone give me a clue to solve this problem?


Previous content

I'm trying to convert my node(with express) project into Firebase compatible one.

I add my API endpoint in /functions/index.js

const apiRoute = require("./routes/api")
exports.api = functions.https.onRequest(apiRoute)

And in my api.js

router.get("/", (req, res) => {
  res.send("api is running on")
})

router.get("/sentences", (req, res) => {
  res.send("hi")
})

So, my expectation was when I call localhost:5000/api or localhost:5000/api/sentences, I could get a response, but it doesn't work.

For that, I tried .onCall to submit my cloud function rather than using .onRequest.

But only POST request was accepted when I call functions.httpsCallable("endpoint").

So, I tried to use onRequest and rewrites in hosting in firebase.json

"hosting": {
    "public": "public",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "/api/**",
        "function": "api"
      }
    ]
  },

But, I just got this error:

TypeError: Cannot read property 'apply' of undefined at /Users/fredriccliver/Projects/Speech/functions/node_modules/express/lib/router/index.js:635:15 at next

How should I take the way to call my functions from frontend javascript?


Solution

  • I resolved after check a youtube clip and trying some more.

    summarised on my medium post. https://medium.com/@fredriccliver/how-to-use-an-express-router-within-the-cloud-function-developing-environment-cb64face4043

    functions/index.js

    const functions = require("firebase-functions")
    const express = require("express")
    const app = express()
    
    // my routings
    const apiRoute = require("./api")
    
    // add routes to the express app.
    app.use("/api", apiRoute)
    
    exports.api = functions.https.onRequest(app)
    

    functions/api.js

    const router = require("express").Router()
    
    router.get("/api/user/data", (req, res) => {
      res.send(`this is /api/user/data`)
    })
    
    router.get("/api/data", (req, res) => {
      res.send(`this is /api/data`)
    })
    
    router.get("/api/api", (req, res) => {
      res.send(`here is /api/api`)
    })
    
    router.get("/api", (req, res) => {
      res.send(`here is /api`)
    })
    
    router.get("/data", (req, res) => {
      res.send(`here is /data`)
    })
    
    router.get("/", (req, res) => {
      res.send(`here is /`)
    })
    
    module.exports = router
    

    /firebase.json

    
    {
      "hosting": {
        "public": "public",
        "ignore": [
          "firebase.json",
          "**/.*",
          "**/node_modules/**"
        ],
        "rewrites": [{
          "source": "/api/**",
          "function": "api"
        }]
      }
    }
    

    So, I could approach all endpoints