I am trying to call firebase function from my web app
I am getting
access-Control-Allow-Origin error
My code is from web:
var createNewUserAndEvent = firebase.functions().httpsCallable('createNewUserAndEvent');
const data= await createNewUserAndEvent(userData);
and from firebase function:
const functions = require("firebase-functions");
var admin = require("firebase-admin");
admin.initializeApp();
exports.createNewUserAndEvent = functions.https.onCall((data, context) => {
cors({ origin: true })(data, context, async () => {
if (!context.auth) {
Related
My app is successfully deployed on Heroku- it works when I have VSCode open and do npm run start manually, however when I close VSCode it is no longer able to successfully call any APIs on the backend and the console shows me a bunch of errors like the one in the title.
my console (ONLY happens when I close VSCode):
my code in the backend:
const PORT = 8000
const express = require('express')
const cors = require('cors')
const {TwitterApi} = require('twitter-api-v2')
const axios = require('axios')
const cheerio = require('cheerio')
require('dotenv').config()
const snoowrap = require('snoowrap')
const linkPreviewGenerator = require('link-preview-generator')
const spotify = require('spotify-web-api-node')
const fetch = require('node-fetch')
var request = require('request')
const app = express()
app.use(cors())
app.get('/', async (req, res) => {
const client = new TwitterApi(process.env.twt_bearer_token)
const trendsInternational = await client.v1.trendsByPlace(1);
const trendList = []
for (const {trends} of trendsInternational) {
for (const trend of trends) {
trendList.push({
name: trend.name,
url: trend.url
})
}
}
res.json(trendList)
})
app.get('/reddit', async (req, res) => {
const r = new snoowrap({
userAgent: process.env.user_agent,
clientId: process.env.client_id,
clientSecret: process.env.client_secret,
refreshToken: process.env.refresh_token
})
topPosts = []
;(await r.getHot()).forEach(post => {
topPosts.push({
title: post.title,
url: post.url
})
})
res.json(topPosts);
})
app.get('/news', async (req, res) => {
const news_url = 'https://www.theguardian.com/international'
axios(news_url)
.then(response => {
const html = response.data;
const $ = cheerio.load(html);
const articles = [];
const values = new Set();
$('.fc-item__title', html).each(function () { //<-- cannot be a function expression
const title = $(this).text().trim();
const url = $(this).find('a').attr('href');
if (!values.has(url)) {
values.add(url);
articles.push({
title,
url
});
}
})
res.json(articles)
}).catch(err => console.log(err))
})
app.listen(PORT, () => console.log(`Server is running on port ${PORT}`))```
Heroku runs on its own port, try setting port like this
const PORT = Number(process.env["PORT"]) || 8000
I need to call a Dialogflow V2 APIs, but to do this i need to generate a token.
I found many codes about how to do this, but doesn't work for me.
I'm doing an API to generate token and then pass the token to another API to call DialogFlow APIs.
Can anyone help me how to generate a token to call Dialogflow V2 APIs?
My API to generate token Code below:
const express = require('express');
const router = express.Router();
const googleAuth = require('google-oauth-jwt');
function generateAccessToken() {
return new Promise((resolve) => {
googleAuth.authenticate(
{
email: "<myemail>",
key: "<myprivatekey>",
scopes: "https://www.googleapis.com/auth2/v4/token",
},
(err, token) => {
resolve(token);
},
);
});
}
router.get('/token', async(req, res) => {
try {
let tok = await generateAccessToken();
return res.status(200).send({ Token: tok});
} catch(err) {
return res.status(500).send({ error: 'Erro ao gerar token'});
}
});
module.exports = app => app.use('/', router);
Dialogflow V2 no longer uses developer/client access tokens. You need to use your service account key file to access the API. You can follow this article to set up your service account. Once you have set up your service account, you can check the sample implementation of dialogflow using nodejs.
Install client library:
npm install #google-cloud/dialogflow
Code snippet from the github link:
const dialogflow = require('#google-cloud/dialogflow');
const uuid = require('uuid');
/**
* Send a query to the dialogflow agent, and return the query result.
* #param {string} projectId The project to be used
*/
async function runSample(projectId = 'your-project-id') {
// A unique identifier for the given session
const sessionId = uuid.v4();
// Create a new session
const sessionClient = new dialogflow.SessionsClient();
const sessionPath = sessionClient.projectAgentSessionPath(projectId, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: 'hello',
// The language used by the client (en-US)
languageCode: 'en-US',
},
},
};
// Send request and log result
const responses = await sessionClient.detectIntent(request);
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
}
Below the code worked for me returning Bearer Token:
const express = require('express');
const router = express.Router();
const googleAuth = require('google-oauth-jwt');
const {google} = require('googleapis');
const request = require('request');
async function generateAccessToken2() {
const jwtClient = new google.auth.JWT(
"<email serviceaccount>",
null,
"<Private Key>",["https://www.googleapis.com/auth/indexing","https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/dialogflow"],
null
);
let tok = "";
tok = jwtClient.authorize();
return tok;
};
As per the documentation you can specify the timeout for a function like so:
const runtimeOpts = {
timeoutSeconds: 300,
memory: '1GB'
}
exports.myStorageFunction = functions
.runWith(runtimeOpts)
.storage
.object()
.onFinalize((object) = > {
// do some complicated things that take a lot of memory and time
});
However, the following code fails to deploy, with error TypeError: functions.https.runWith is not a function:
const admin = require("firebase-admin");
const functions = require("firebase-functions");
admin.initializeApp();
exports.hello = functions.runWith({ timeoutSeconds: 540 }).https.onRequest(async (req, res) => {
res.send("hello");
});
What is wrong?
I am trying to integrate dialogflow with firebase using Webhook.
The response I receive is:
"webhookStatus": {
"code": 13,
"message": "Webhook call failed. Error: 500 Internal Server Error."
}
Webhook is: https://us-central1-miarduino-844c8.cloudfunctions.net/receiveAssistantRequests
Firebase rules are:
{
/* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
"rules": {
".read": true,
".write": true
}
}
index.js I have used is:
const functions = require('firebase-functions');
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
// response.send("Hello from Firebase!");
// });
const admin = require('firebase-admin');
admin.initializeApp();
const DialogflowApp = require('actions-on-google').DialogflowApp;
exports.receiveAssistantRequests = functions.https.onRequest((request, response) => {
const app = new DialogflowApp({ request: request, response: response });
function handlerRequest(app) {
const device = app.getArgument('devices');
const status = app.getArgument('status');
return admin.database().ref(`/automation/${device}/value`).set(status)
.then(snapshot => {
app.ask(`Ok, switching ${device} ${status}. Do you want to control anything else?`);
});
}
app.handleRequest(handlerRequest);
});
If I use soapUI for making the request to: https://us-central1-miarduino-844c8.cloudfunctions.net/receiveAssistantRequests
I get:
HTTP/1.1 500 Internal Server Error
Content-Type=text/plain; charset=utf-8
X-Content-Type-Options=nosniff
X-Cloud-Trace-Context=7327cb053558c4598e01b0218e61e5cf;o=1
Date=Thu, 08 Aug 2019 10:19:12 GMT
Server=Google Frontend
Content-Length=36
Alt-Svc=quic=":443"; ma=2592000; v="46,43,39"
Error: could not handle the request
Has anyone idea regarding how to solve this issue?
Not sure if the issue is located in Dialogflow or in Firebase
This might help you.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp({
databaseURL: "YOUR_DATABASE_URL"});
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({request,response});
console.log('dailog firebase admin'+agent);
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
}
How can I run HTTP functions and Realtime Database functions simultaneously
I see in the documentation here : Run functions locally how to run HTTP functions by the following command : firebase serve and for the Realtime Database functions : firebase functions:shell but it doesn't work for me.
And also when I deployed my functions with command firebase deploy --only functions it only deploy my HTTP function .
What is wrong with my approach ?
structure:
/functions
|--index.js
|--saveDetectedBeacons.js
|--generatePresence.js
|--package.json
index.js:
const functions = require('firebase-functions');
const admin = require("firebase-admin");
const saveDetectedBeaconsFunc = require('./saveDetectedBeacons');
const generatePresenceFunc = require('./generatePresence');
const serviceAccount = require("./serviceAccountKey");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://exampleDb.firebase.com"
});
const db = admin.database();
exports.saveDetectedBeaconsApi = functions.https.onRequest((request, response) => {
saveDetectedBeaconsFunc.handler(request,response,db)
});
exports.generatePresenceApi = functions.database.ref('/reports').onCreate((snapshot, context) => {
generatePresenceFunc.handler(snapshot, context, db)
});
saveDetectedBeacons.js:
exports.handler = function (request, response, db) {
// do something
};
generatePresence.js
exports.handler = function (snapshot, context, db) {
// do something
};