Skip to content

RTDB function - unable to use DataSnapshots .ref when a path component starts with refs #1055

@rhodgkins

Description

@rhodgkins

If you've got a Firebase RTDB path component that starts with refs you won't be able to use .ref of the provided DataSnapshot that's passed into the function.

Bit of a fun one this is...

Related issues

[REQUIRED] Version info

node: 14.17.4
firebase-functions: 3.18.1
firebase-tools: 10.1.0
firebase-admin: 10.0.2

[REQUIRED] Test case

Deploy the below function:

const functions = require('firebase-functions') exports.pathUnableToUseRef = functions.database.ref('childStartsWithRef/{id}').onWrite(async (change, context) => { functions.logger.debug(`Change at on child of childStartsWithRef: change.after.key='${change.after.key  }', context.params.id='${context.params.id}'`, { context }) functions.logger.debug(`change.after.ref.toString(): ${change.after.ref.toString()}`) })

[REQUIRED] Steps to reproduce

Deploy the above function and then run:

firebase database:set "/childStartsWithRef/ref" --data '"foobar"'

After checking the function logs, you can see this executes the function successfully:

Function execution started Change at on child of childStartsWithRef: change.after.key='ref', context.params.id='ref' change.after.ref.toString(): https://my-project.firebaseio.com/childStartsWithRef/ref Function execution took 6 ms, finished with status: 'ok' 

However, when running:
firebase database:set "/childStartsWithRef/refs" --data '"foobar"'

This causes the function execution to fail.

[REQUIRED] Expected behavior

For the .ref access to work and the following to be outputted on the second execution:

Function execution started Change at on child of childStartsWithRef: change.after.key='refs', context.params.id='refs' change.after.ref.toString(): https://my-project.firebaseio.com/childStartsWithRef/refs Function execution took 6 ms, finished with status: 'ok' 

[REQUIRED] Actual behavior

Second execution of function fails:

Function execution started Change at on child of childStartsWithRef: change.after.key='null', context.params.id='refs' [2022-03-09T15:03:33.858Z] @firebase/database: FIREBASE FATAL ERROR: Cannot parse Firebase url. Please use https://<YOUR FIREBASE>.firebaseio.com Function execution took 93 ms, finished with status: 'error' 

Note also that the .key of the DataSnapshot is null.

Were you able to successfully deploy your functions?

Yes.

Extra info

Pretty sure its because of the regex to extract the instance and path from the resource:

const resourceRegex = `projects/([^/]+)/instances/([a-zA-Z0-9\-^/]+)/refs(/.+)?`;

const resource = 'projects/_/instances/my-database/refs/childStartsWithRef/refs' const resourceRegex = `projects/([^/]+)/instances/([a-zA-Z0-9\-^/]+)/refs(/.+)?`; const match = resource.match(new RegExp(resourceRegex)); console.log(match)

Outputs:

[ 'projects/_/instances/my-database/refs/childStartsWithRef/refs', '_', 'my-database/refs/childStartsWithRef', undefined, index: 0, input: 'projects/_/instances/my-database/refs/childStartsWithRef/refs', groups: undefined ] 

But changing the instance path component regex to being non-greedy (([a-zA-Z0-9\-^/]+?)) does fix things - I'm not saying this is the best fix, but certainly fixes the example case:

const resource = 'projects/_/instances/my-database/refs/childStartsWithRef/refs' const resourceRegex = `projects/([^/]+)/instances/([a-zA-Z0-9\-^/]+?)/refs(/.+)?`; const match = resource.match(new RegExp(resourceRegex)); console.log(match)

Outputs:

[ 'projects/_/instances/my-database/refs/childStartsWithRef/refs', '_', 'my-database', '/childStartsWithRef/refs', index: 0, input: 'projects/_/instances/my-database/refs/childStartsWithRef/refs', groups: undefined ] 

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions