12

How can I properly simulate a cloud function locally so that it has all data as when being invoked on firebase servers? (e.g. the context.auth)

I am serving my project with firebase serve, it runs ok on http://localhost:5000/, however, my cloud functions are being called from https://us-central1-<my-app>.cloudfunctions.net/getUser. (The function is not even deployed.)

To avoid XY problem, I am trying to debug my function, but calling it from firebase shell results in context.auth being undefined, same when calling via postman from http://localhost:5000/<my-app>/us-central1/getUser.

This is my ./functions/src/index.ts file

import * as functions from 'firebase-functions'
import admin from 'firebase-admin'
import { inspect } from 'util'

admin.initializeApp()

export const getUser = functions.https.onCall((data, context) => {
  console.debug('== getUser called =========================================')
  console.log('getUser', inspect(data), inspect(context.auth))
  return admin.database().ref('userRights/admin').child(context.auth.uid).once('value', snapshot => {
    console.log(snapshot.val())
    if (snapshot.val() === true) {
      return 'OK'
      // return {status: 'OK'}
    } else {
      return 'NOK'
      // return {status: 'error', code: 401, message: 'Unauthorized'}
    }
  })
})

file ./firebase.functions.ts

import { functions } from '~/firebase'
export const getUser = functions.httpsCallable('getUser')

Consumer ./src/pages/AdminPanel/index.tsx

import { getUser } from '~/firebase.functions'
//...
getUser({myDataX: 'asd'}).then(response => console.debug('response', response))
Qwerty
  • 29,062
  • 22
  • 108
  • 136
  • I'm facing the same issue here. How did you get around that? Thanks. – cbdeveloper Mar 12 '19 at 11:29
  • @cbdev420 AFAIR I didn't. I just used exhaustive `console` statements (as above) and the logs in firebase console... – Qwerty Mar 12 '19 at 12:45
  • 1
    This worked for me: For locally you must call (after firebase.initializeApp): `firebase.functions().useFunctionsEmulator('http://localhost:5000')` [source. It's on the 2nd answer to the question on this link](https://stackoverflow.com/questions/50884534/how-to-test-functions-https-oncall-firebase-cloud-functions-locally) – cbdeveloper Mar 12 '19 at 15:57

4 Answers4

8

UPDATE - April/2021

As of April/2021, method useFunctionsEmulator has been deprecated. It is suggested to use method useEmulator(host, port) instead.


Original post:

By default, firebase serve sends queries to CLOUD function instead of localhost, but it is possible to change it to to point to localhost.

@gregbkr found a workaround for that at this github thread.

You basically add this after firebase initialization script (firebase/init.js) in html head.

<script>
   firebase.functions().useFunctionsEmulator("http://localhost:5001");
</script>

Make sure to REMOVE it when deploying to SERVER

blackgreen
  • 34,072
  • 23
  • 111
  • 129
GorvGoyl
  • 42,508
  • 29
  • 229
  • 225
5

There is currently no support for local testing of callable functions like this. The team is working on a way for you to specify the URL endpoint of a callable function so that you can redirect it to a different location for testing.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • 1
    Bummer! It's not just testing. This would be helpful while developing locally. – Gary Aug 30 '18 at 19:51
  • Why not have *firebase serve* configure the CORS to allow localhost when developing? It fails with... No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. – Gary Aug 30 '18 at 20:01
  • @Doug Stevenson, isn't there a way to specify the endpoint for ALL functions like in `firebase.initializeApp`? Thanks! – Nuthinking Sep 06 '18 at 07:35
  • Has anyone tried redirecting requests to localhost using `hosts` file? – Qwerty Mar 12 '19 at 12:48
0

Just found a workaround. using fiddlers AutoResponder to redirect the function call to the local served function.

step 1

copy the target url of the function from the client

step 1

step 2

copy the local served function url

enter image description here

step 3

active the auto respoder and use the following rules (the second rule is also importent to allow all outher requests

enter image description here

Shaytj
  • 71
  • 1
  • 5
0

That worked for me, thank you @GorvGoyl!

script src="/__/firebase/init.js?useEmulator=true"></script
MAZ
  • 643
  • 5
  • 18