how to call a firebase sample cloud function from unity? - firebase

The sample function that firebae creates is this below. Now i want to call it from unity. added and configured firebase in unity already.
/**
* Responds to any HTTP request.
*
* #param {!express:Request} req HTTP request context.
* #param {!express:Response} res HTTP response context.
*/
exports.helloWorld = (req, res) => {
let message = req.query.message || req.body.message || 'Hello World!';
res.status(200).send(message);
};
now i am not sure that to call a function do i need authentication? if yes how should i call the function?
i used this code to call the function. My function name is testunity and i have posted the code snipped of cloud function above.
System.Threading.Tasks.Task<string> Start()
{
FirebaseFunctions functions = FirebaseFunctions.GetInstance(projectId);
Debug.Log("Calling");
var function = functions.GetHttpsCallable("testunity");
return function.CallAsync("helloWorld").ContinueWith((task) => {
return (string)task.Result.Data;
});
}

Your client is using a callable type function, but your backend is not. If you want to use a callable function from the client, you will need to implement a callable function on the backend (not an HTTP function has you have now). See the documentation for details:
https://firebase.google.com/docs/functions/callable
Your callable function will look more like this:
exports.testunity = functions.https.onCall((data, context) => {
// ...
});

Related

Accessing Google Cloud Function from Vercel Serverless Function

I am seeking the best manner in which this should be done.
I have a https based GCF Function such as:
// google function
exports.someFunction = async (req, res) => {
try {
...
// some logic and access
res.status(200).send(data)
}
catch(error) {
res.status(400).send(error.message)
}
}
The API serverless function in Next.js is using axios. Is that the recommended method?
// next.js pages/api/call-google-func.js
async function handler(req, res) {
try {
const url = '....' //https://gcp-zone-project-xx834.cloudfunctions.net/someFunc
const res = await axios.get(url)
const resdata = res.data
res.status(200).send(resdata)
}
catch(error) {
res.status(400).send(error)
}
}
The problem with this method is that the GCF must have public access. How can we set up to access the GCF from Next.js by passing credentials as environment variables. Thanks
I think for this situation where a Vercel Serverless Function must communicate with the outside world, a Google Cloud Function, you'd want to create a JWT token on Vercel's side to pass to Google's side which you would then need to verify. I think Exchanging a self-signed JWT for a Google-signed ID token would be what you need.
Since either side doesn't know about the other, Google's IAM normal cloud privileges for allowing GCG<>GCF communication wouldn't apply here.

Firebase cloud function onCall not working after changing region

I built few cloud functions like this one:
const addRoom = functions.https.onCall((data, context) => {
It works perfectly but I wanted to change region to europe-west. I followed this stackoverflow: firebase deploy to custom region (eu-central1)
const addRoom = functions.region('europe-west1').https.onCall((data, context) => {
It looks working fine for all functions (triggers) except onCall functions. I got this error when calling addRoom function on client side :
firebase.functions().httpsCallable("addRoom")(data)
Access to fetch at
'https://us-central1-myproject.cloudfunctions.net/addRoom' from origin
'http://localhost:4200/new-room' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
Redirect is not allowed for a preflight request.
At this moment I use default region for onCall functions but is there a way to correct that or is that an error from firebase ?
On the client side, you should specify the desired region at initialization and call the function as follows:
var functions = firebase.app().functions('europe-west1');
....
functions.httpsCallable("addRoom")(data)
See https://firebase.google.com/docs/functions/locations#http_and_client_callable_functions
for angular application you should provide the region like this in app module
providers: [
{ provide: REGION, useValue: 'europe-west3' }
]
and call the function like this:
constructor(private aff: AngularFireFunctions) {}
sendMail(data: { ... }): Promise<any> {
return this.aff.httpsCallable('function_name')(data).pipe(first()).toPromise()
}

What is the difference between publish / subscribe and method ? where/when we use method and publish / subscribe?

Today I try to work on meteor and getting an issue to get data from the server page..
I try to search it on google and meteor side but there is two way to get data publish / subscribe and Method
Have a below code, I didn't know how to write it on meteor server-side and get that data in client-side
function (x)
{
var y =2
var z = y*x
return z;
}
Now I want to call this method in client side
With publish/subscribe you keep track on datas collected.
https://docs.meteor.com/api/pubsub.html
According to the documentation:
Methods are remote functions that Meteor clients can invoke with
Meteor.call.
So, to answer the last question: to call your function from client side, you have to use "Meteor.call('yourMethodName', optionalCallBacks);"
EDIT:
Ok, as suggested in the comments, here an example, with your function.
In the server side, lets say on a file called "methods.js" or somethings:
import { Meteor } from 'meteor/meteor';
Meteor.methods({
myMethod(x) {
const y = 2;
const z = y * x;
return z;
}
});
then in client side, you could call this mehod, like:
Meteor.call('myMethod', x, (error, result) => {
// OPTIONAL CALLBACK RESULT
console.log(error, result);
});
Arguments here, are respectivelly, name of the method, variable named x, callback.
What is the difference between publish / subscribe and method ? where/when we use method and publish / subscribe?
So if you want a logic you don't need pub/sub.
Methods are for logic pub/sub for data handling.
Important note:
If you need to work with data from meteor's collection on the method you need to take into account this if method is executed on the server side it has access to all data (collections).
If the method is executed on the client side it has access only to published data.
On the other hand, according to your example, you don't need any data, so I'll skip it.
I strongly suggest using validated methods:
https://github.com/meteor/validated-method
Now let's go to examples
Imagine you have a method
export const calculate = new ValidatedMethod({
name: 'logic.calculate', // methods are usually named like this
validate: new SimpleSchema({ // use SimpleSchema to autovalidate parameters
x: {
type: Number
}
}).validator(),
run({ x }) {
const y = 2;
return y*x;
}
});
Things to note:
1. The file should be imported on the server somewhere.
2. You need to use validation
Now call it on the client
Meteor.call('logic.calculate', { x }, (error, result) => {
if (error) {
do something
}
console.log(result);
});
Also, you can import the method directly and call it like this:
import { calculate } from '../../api/logic/methods';// use real method path here
calculate.call({ x }, (error, result) => {
if (error) {
do something
}
console.log(result);
});
Note that for validated methods argument is an object
In meteor, we can create a meteor method and can pass data to client side by Meteor.call('methodName', 'param') . But in case of async operation we need to use future. Take a look on below example :
Future = Npm.require('fibers/future');
Meteor.methods({
foo: function() {
const future = new Future();
someAsyncCall(foo, function bar(error, result) {
if (error) future.throw(error);
future.return(result);
});
// Execution is paused until callback arrives
const ret = future.wait(); // Wait on future not Future
return ret;
}
});

How to call GCP Datastore from GCP Cloud Function?

Here's the starter code provided with a new GCP Cloud Function:
/**
* Responds to any HTTP request that can provide a "message" field in the body.
*
* #param {!Object} req Cloud Function request context.
* #param {!Object} res Cloud Function response context.
*/
exports.helloWorld = function helloWorld(req, res) {
// Example input: {"message": "Hello!"}
if (req.body.message === undefined) {
// This is an error case, as "message" is required.
res.status(400).send('No message defined!');
} else {
// Everything is okay.
console.log(req.body.message);
res.status(200).send('Success: ' + req.body.message);
}
};
... and the package.json:
{
"name": "sample-http",
"version": "0.0.1"
}
Looking for a basic example of calling DataStore from here.
I'm not a Node.js user, but based on the documentation I think one convenient way would be to use the Node.js Cloud Datastore Client Library. The example from that page:
// Imports the Google Cloud client library
const Datastore = require('#google-cloud/datastore');
// Your Google Cloud Platform project ID
const projectId = 'YOUR_PROJECT_ID';
// Instantiates a client
const datastore = Datastore({
projectId: projectId
});
// The kind for the new entity
const kind = 'Task';
// The name/ID for the new entity
const name = 'sampletask1';
// The Cloud Datastore key for the new entity
const taskKey = datastore.key([kind, name]);
// Prepares the new entity
const task = {
key: taskKey,
data: {
description: 'Buy milk'
}
};
// Saves the entity
datastore.save(task)
.then(() => {
console.log(`Saved ${task.key.name}: ${task.data.description}`);
})
.catch((err) => {
console.error('ERROR:', err);
});
But you may want to take a look at Client Libraries Explained as well, as it describes or points to detailed pages about other options as well, some of which one might find preferable.
you need to include the DataStore dependency in the package.json
{
"name": "sample-http",
"dependencies": {
"#google-cloud/datastore": "1.3.4"
},
"version": "0.0.1"
}

How can I execute a callback on a meteor method that does async calls?

My client is making a call to the server.
Meteor.call('someRequest', params, onAllDoneCallback);
that is processed by (server code)
Meteor.methods({
'someRequest': function(params, cb) {
anAsyncFunction(params, cb);
return true;
},
});
I'd like the onAllDoneCallback to be triggered on the client side once the anAsyncFunction has finished and triggers its own callback.
However, in Meteor it seems that the second argument of someRequest is ignored and that the onAllDoneCallback is triggered with what someRequest returns, which here is true and which is called before that anAsyncFunction has finished.
In my case I'm more concerned about the timing issue (I'm using it to tell the client that the processing is finished, and not just that the request is well received) but other will probably want to call the callback with arguments from anAsyncFunction
What you are doing now is passing a function to the server. If that does work, it's very insecure. What you want to do is create a future and then use it to manage the asynchronous function. Here is an example:
let Future = Npm.require('fibers/future');
Meteor.methods({
someRequest: function (someArg) {
// for security reasons, make sure you check the type of arguments.
check(someArg, String);
// future is an async handler.
let future = new Future();
// this is a function for a generic node style callback [ie, function (err, res)]
let resolver = future.resolver();
// run your function and pass it the future resolver
// the future will be resolved when the callback happens.
anAsyncFunction(someArg, resolver);
// this meteor method will not end until future has been resolved.
return future.wait();
}
});
Alternatively, Meteor provides a wrapAsync that provides similar functionality of wrapping async functions in futures so they can run in meteor methods. That is:
let wrappedAsyncFunction = Meteor.wrapAsync(anAsyncFunction /** second argument is `this` binding*/);
return wrappedAsyncFunction();
adapting this answer: Meteor: Proper use of Meteor.wrapAsync on server
You have to use Meteor's wrapAsync api, which takes a function that accepts a callback as its last argument, the callback being like function(error, result){}. So it will look like:
Meteor.methods({
'someRequest': function(params){
var wrap = Meteor.wrapAsync(anAsyncFunction);
return wrap(params);
},
});

Resources