http post request firebase cloud function - http

I want to make post request and send data into body in firebase cloud function.
as default, it is get request or post request?
var functions = require('firebase-functions');
exports.tryfunction= functions.https.onRequest((req, res) => {
console.log(req.body) // or it should be req.query
});
how do I know and decide what the method it is?

I just sharing simple code part. I'm using like this.
const functions = require('firebase-functions');
exports.postmethod = functions.https.onRequest((request, response) => {
if(request.method !== "POST"){
response.send(405, 'HTTP Method ' +request.method+' not allowed');
}
response.send(request.body);
});
I hope it will be helpful.

There is no default. The request method is whatever the client chose to send.
The req object in your callback is an express.js Request object. Use the linked documentation, you can see that the request method can be found by using req.method.

To specify the HTTP method that your Firebase Function accepts you need to use Express API as you'd normally do in a standard Express app.
You can pass a full Express app to an HTTP function as the argument for onRequest(). This way you can use Express' own API to restrict your Firebase function to a specific method. Here's an example:
const express = require('express');
const app = express();
// Add middleware to authenticate requests or whatever you want here
app.use(myMiddleware);
// build multiple CRUD interfaces:
app.get('/:id', (req, res) => res.send(Widgets.getById(req.params.id)));
app.post('/', (req, res) => res.send(Widgets.create()));
app.put('/:id', (req, res) => res.send(Widgets.update(req.params.id, req.body)));
app.delete('/:id', (req, res) => res.send(Widgets.delete(req.params.id)));
app.get('/', (req, res) => res.send(Widgets.list()));
// Expose Express API as a single Cloud Function:
exports.widgets = functions.https.onRequest(app);
Explanation of the above code:
We expose a Firebase function with endpoint /widgets with different handlers for different HTTP methods using Express' own API, e.g. app.post(..), app.get(..), etc. We then pass app as an argument to functions.https.onRequest(app);. That's it, you're done!
You can even add more paths if you wish, E.g. if we want an endpoint that accepts GET requests to an endpoint that looks like: /widgets/foo/bar, we simply add app.get('/foo/bar', (req, res => { ... });.
It's all taken directly from the official Firebase docs.
I'm surprised #Doug Stevenson didn't mention this in his answer.

Related

CORS error when making Axios calls to Cloudrun service from Firebase hosted app

This looks to be pretty obvious but I've been trying to figure it out for a couple of days now and still can't get it to work. Please, can someone point out what I'm missing.
I'm trying to make an axios call to my cloud run service from my firebase hosted SPA. To isolate the issue I followed the steps outlined in the [firebase tutorial for cloud run] (https://firebase.google.com/docs/hosting/cloud-run#node.js)
Step 4 of the tutorial talks about setting up rewrite to use the firebase domain as a proxy to your cloud run service. It says that the helloworld service would be reachable via
Your Firebase subdomains:
projectID.web.app/helloworld and projectID.firebaseapp.com/helloworld
So I follow the steps and deploy the service. Then I try to make an axios call to the service from the SPA like below
testHelloWorld () {
axios.get(`https://myProjectId.firebaseapp.com/helloworld`)
.then((data) => {
console.log(data)
})
.catch(ex => {
console.error(ex)
})
})
}
But then I get the CORS error
Access to XMLHttpRequest at 'https://myProjectId.firebaseapp.com/helloworld' from origin 'https://myFirabaseApp.firebaseapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This answer states that this should be possible so I'm not sure what I'm doing wrong.
N.B:
While debugging, I updated the node app from the tutorial to add cors support like below. Still didnt work.
const express = require('express');
const app = express();
const cors = require('cors'); //Imported and added this
app.use(cors()); // Used here
app.get('/', (req, res) => {
console.log('Hello world received a request.');
const target = process.env.TARGET || 'World';
res.send(`Hello ${target}!`);
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log('Hello world listening on port', port);
});
So the question here is, how do I make an Axios/AJAX call to my cloud run service using the firebase rewrite rule?
Please check if you have installed cors: npm install cors.
Please check if the 2 following options can solve your issue:
1= Use the following code :
app.use(cors({origin:true,credentials: true}));
2) If the previous didn't work, please use the following code:
app.get('/', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
console.log('Hello world received a request.');
}
Please let me know if it works for you.

How to use Telegraf (Telegram) in Firebase?

I'm trying use Telegraf library with Firebase Functions but it's not working as I expected.
I follow these this article and instructions as appear in webhooks (as appears for express example) and webhookcallback as appear in telegraf docs.
const Telegraf = require('telegraf')
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions')
// The Firebase Admin SDK to access the Firebase Realtime or Firestore Database.
const admin = require('firebase-admin')
// set telegraf and responses.
const BOT_TOKEN = 'my-telegram-bot-token'
const bot = new Telegraf(BOT_TOKEN)
bot.start((ctx) => ctx.reply("Start instructions"))
bot.help((ctx) => ctx.reply("This is help"))
bot.hears('hi', (ctx) => ctx.reply('Hola'))
bot.on('text', (ctx) => ctx.reply('Response to any text'))
bot.catch((err, ctx) => {
console.log(`Ooops, ecountered an error for ${ctx.updateType}`, err)
})
// initialize bot
bot.launch() // <-- (2)
//appends middleware
exports.ideas2coolBot = functions.https.onRequest(bot.webhookCallback(`/my-path`));
In firebase server I need add bot.launch() (2) to get worked, but it works just for max timeout set in Firebase Function. I need to recall Telegram "setWebhook" API to get work again and it works for the same time. It's like it's generate one function instance and shut down when time is over.
I noted the telegraf.launch() have options to start in poll or webhook mode but its not pretty clear for me how to use this options.
How should I use telegram.launch() to get worked in webhook mode in Firebase?
Edit:
When I used getWebhookInfo I get this result:
{
"ok": true,
"result": {
"url": "https://0dbee201.ngrok.io/test-app-project/us-central1/testAppFunction/bot",
"has_custom_certificate": false,
"pending_update_count": 7,
"last_error_date": 1573053003,
"last_error_message": "Read timeout expired",
"max_connections": 40
}
}
and console shows incoming conection but do nothing...
i functions: Beginning execution of "ideas2coolBot"
i functions: Finished "ideas2coolBot" in ~1s
Edit2:
I've been trying adding Express too...
app.use(bot.webhookCallback('/bot'))
app.get('/', (req, res) => {
res.send('Hello World from Firebase!')
})
exports.ideas2coolBot = functions.https.onRequest(app);
it's works '/' path but got nothing with '/bot'. POST to '/bot' not response.
By the way, I tried a express standalone version and works prefect, but using it with firebase doesn't respond ("Read timeout expired").
delete
bot.launch()
try add this
exports.YOURFUNCTIONNAME = functions.https.onRequest(
(req, res) => bot.handleUpdate(req.body, res)
)
then set ur webhook manually
https://api.telegram.org/bot{BOTTOKEN}/setWebhook?url={FIREBASE FUNCTION URL}'

Firebase callable + express?

With functions.https.onRequest(app); it was possible to use express right away.
I'm wondering if it's possible to use functions.https.onCall(...) together with express in the same way?
onCall(...) seem to have a different signature but maybe there is still a way to keep using express while working with onCall(...) functions?
No, it's not possible. Callable functions force your endpoint to use a certain path, a certain type of input (JSON via POST) and a certain type of output (also JSON). Express wouldn't really help you out, given the constraints of how callables work. You can read about all the callable protocol details in the documentation. You can see that callables abstract away all of the details of the request and response, which you would normally work with when using Express.
What does work however is using onRequest and calling that... then you can use express like normal and have the simplicity of firebase callable on the client side...
then you can do your authorization like normal. For example with the following middleware:
export const createFirebaseAuth = () => (req: express.Request, res: express.Response, next: express.NextFunction) => {
console.log('Time: ', Date.now());
const token = req.header('Authorization');
if (!token) {
res.status(400);
res.send('Authtoken must be sent with a request');
return;
}
admin
.auth()
.verifyIdToken(token.replace('Bearer ', ''))
.then((v) => {
req.user = v;
next();
})
.catch((error) => {
res.status(401);
res.send(error.message);
res.end();
});
}

Cloud Functions for Firebase with custom HTTP path

Is there a way of defining the HTTP path (after the first '/') to access a Cloud Function for Firebase?
What I'm tying to achieve is to create a rest-like path system to access the functions.
I have a GitHub with my project if there is any doubts.
The cloudfunctions.net domain will route all traffic beginning with a function name to that function. So, for example, you could do this with a standard Express app:
var functions = require('firebase-functions');
var express = require('express');
var app = express();
app.post('/bar', (req, res) => {
res.end('bar');
});
app.get('/foo', (req, res) => {
res.end('foo');
});
exports.myFunc = functions.https.onRequest(app);
The above will allow you to make requests to /myFunc/foo and /myFunc/bar and handle them separately. One thing to note is that currently if you pass an Express app there will be an error if you try to access your function at /myFunc, instead needing to make your request to /myFunc/ (with a trailing slash).

How Firebase Cloud functions handle HTTP post method?

I have created Firebase Cloud Functions app,
I created function with https.onRequest.
and get data with req.body but there is not data there.
Can Firebase Cloud Functions can handle HTTP POST method?
This is my sample code:-
var functions = require('firebase-functions');
exports.testPost = functions.https.onRequest((req, res) => {
console.log(req.body);
});
I tested by postman with POST method but didn't show result in Firebase log.
Functions built on Firebase can also use Express.js routers for handling GET/POST/PUT/DELETE, etc... is fully supported by Google, and is the recommended way to implement these types of functions.
More documentation can be found here:
https://firebase.google.com/docs/functions/http-events
Here's a working example built on Node.js
const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors');
const app = express();
// Automatically allow cross-origin requests
app.use(cors({ origin: true }));
app.get('/hello', (req, res) => {
res.end("Received GET request!");
});
app.post('/hello', (req, res) => {
res.end("Received POST request!");
});
// Expose Express API as a single Cloud Function:
exports.widgets = functions.https.onRequest(app);
Then, run firebase deploy, and that should compile your code and create the new "widgets" function. Note: You can rename widgets to anything you want. Ultimately, it will generate a URL for calling the function.
I am planning to do the same thing. What I reckon the approach should be is to check the request.method in the function body. A probable approach can be:
if (request.method != "POST") {
respond.status(400).send("I am not happy");
return;
}
// handle the post request
Here's some reference to the details regarding what the request object holds: https://firebase.google.com/docs/functions/http-events
Firebase functions support GET, POST, PUT, DELETE, and OPTIONS method, and you can check what kind of methods that trigger your function.
// Check for POST request
if(request.method !== "POST"){
res.status(400).send('Please send a POST request');
return;
}
Then to get data from POST request (for example JSON type) will be in the header of your request.
const postData = request.body;
// for instance
const format = req.body.format;
// query string params
let format = req.query.format;
Maybe your project hasn't been setup to communicate with your firebase database. Try the following from your terminal:
npm install -g firebase-tools
Then inside your project folder, run the following and login using your credentials
firebase login
Then
firebase init functions
This will create a folder with index.js, package.json and node_modules
If you are using Postman correctly the rest of your code should work.

Resources