NodeJS app works locally but not when deployed on firebase - node.js

I am trying to deploy a nodeJS app on firebase using this tutorial "https://www.youtube.com/watch?v=LOeioOKUKI8&t=437s", I followed exactly what was told and the app worked as intended locally using "firebase serve" but when I deployed it, POST and GET request stopped working i.e. client side code is unable to reach server side.
for example, on loading "appURL/temp" I'm getting "Content Security Policy: The page’s settings blocked the loading of a resource" error.
What I'm actually trying to do : to send JSON data from Client to server, process the data and return some result as response
What currently app does: takes input, sends it to the server on click and receive it back as response to the POST request
on Client Side (public/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script defer src="/__/firebase/7.14.6/firebase-app.js"></script>
<script defer src="/__/firebase/init.js"></script>
</head>
<body>
<h1>Home</h1>
<input type="text" id="ip">
<button onclick="send()">send</button>
<div id="text"></div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
let textDiv = document.getElementById("text")
function send(){
let ip = document.getElementById("ip").value;
axios.post('/home',ip)
.then( resp => {
textDiv.innerHTML = JSON.stringify(resp.data);
})
}
</script>
</body>
on Server Side (functions/index.js
const func = require('./add'); //this is just to wrap the string with brackets
const functions = require('firebase-functions');
const express = require('express');
const multer = require('multer');
const upload = multer();
const app = express();
app.get('/temp', (req, resp) => {
resp.send("GET Works");
console.log("GET");
})
app.post('/home', upload.single("data"), (req, res) => {
console.log(func.add(JSON.stringify(req.body)))
res.send(func.add(JSON.stringify(req.body)))
});
exports.app = functions.https.onRequest(app);
firebase.json
{
"hosting": {
"public": "public",
"rewrites":[{
"source": "**",
"function": "app"
}],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
Directory Structure
Versions
node : 13.6.0
express : 6.13.4
mutler : 6.13.4

Related

Access nonce value inside your index.html

I'm having prod.js module like this which I'm using to set content security policy
const helmet = require('helmet');
const compression = require('compression');
module.exports = function (app) {
app.use((req, res, next) => {
res.locals.cspNonce = crypto.randomBytes(16).toString("hex");
next();
});
app.use(
helmet.contentSecurityPolicy({
useDefaults: true,
directives: {
scriptSrc: [ "'self'", 'js.stripe.com', 'https://checkout.stripe.com', 'js.stripe.com', 'https://billing.stripe.com', ( request, response ) => `'nonce-${res.locals.cspNonce}'` ],
styleSrc: ["'unsafe-inline'"],
connectSrc:[" * 'self' https://checkout.stripe.com https://billing.stripe.com"],
frameSrc: ["'self' https://checkout.stripe.com https://billing.stripe.com https://js.stripe.com ;"],
imgSrc: [" 'self' blob: https://api.company.com/ data:"],
},
})
);
app.use(compression());
};
I want to access this nonce value created in index.html inside my react app. So that I can pass it to script tags like this
React app index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script
nonce={.........//Get the nonce value here............}
>
</script>
<title>Some title</title>
But I'm not able to figure out how to access nonce inside my Index.html.
P.S: I'm new to programming. Please let me know if you need any other info to help me with this case.
Adding additional info ----------
I'm invoking prod.js in my Index.js file inside my node project.
My Index.js looks like this
const express = require('express');
const https = require('https');
const path = require('path');
const app = express();
require('./startup/routes')(app);
require('./startup/db')();
require('./startup/config')();
require('./startup/validation')();
require('./startup/prod')(app);
Your nonce value will be resolved after you fetch it from your API.
Here is a simplistic example of implementation:
class MyApp {
constructor() {
this.nonce = "";
this.app_ready = false;
this.fetchNonce();
}
setNonce(value) {
this.nonce = value;
this.app_ready = true;
// Do what you have to do when your app is ready, mount your components, etc...
}
fetchNonce() {
fetch("https://url/to/your/api")
.then(response => {
this.setNonce(response.headers.key.to.your.value)
})
.catch(error => {/*Handle you app state in case of error...*/})
}
}

POST request not working in NodeJs app in Cpanel

I was creating a Node App using Express JS. There's a route which accepts a POST Request. The app works fine on localhost, but when I host on Cpanel Shared Hosting, I get the following error for POST request. GET works fine. Can anyone please help or guide where I went wrong?
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /v1/email</pre>
</body>
</html>
My Express JS code
var app = express();
var em =require('./mailjet')
var bodyParser = require('body-parser');
app.use(bodyParser.json())
app.get('/v1', function (req, res) {
return res.json('Hello World');
})
app.post('/v1/email', function (req, res) {
let {name, email, message}=req.body
if (!name || !email || !message){
return res.status(400).send({
'Message':'Bad Request'
})
}
em.request(name, email, message)
return res.status(200).send({
'Message':'Email Sent'
});
})
app.listen()

Node express 404 error status code in Firebase

I am getting an error status code 404 while calling a function locally in nodejs server through firebase serve command.
My schedule.js file
const scheduleOfScheduledQuiz = async (req, res) => {
try {
const data = await getScheduledData();
return res.status(200).json({
message: "Scheduled for today:- ",
data: data
})
} catch (error) {
console.log("erro", error);
return res.status(500).json({
message: "Something went wrong....!!!"
})
}
}
module.exports = {
scheduleOfScheduledQuiz
}
getScheduledData() is a function which gets some data from the firebase realtime database
My index.js file
const functions = require("firebase-functions");
const app = require("express")();
//path to scheduleOfScheduledQuiz() function file
const scheduleOfScheduledQuiz = require("./handlers/Quiz/Scheduled_Quiz/scheduler");
app.get("*/scheduled-quiz/schedule/", scheduleOfScheduledQuiz.scheduleOfScheduledQuiz);
exports.api = functions.runWith({
memory: '2GB',
timeoutSeconds: '60'
}).https.onRequest(app);
So the error what i am getting :-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /predicta-6e51d/us-central1/api/scheduled-quiz/schedule/%0A</pre>
</body>
</html>
with status code 404
My package.json file
Global node js version - 12
firebase node js version - 10
"express": "^4.17.1",
"firebase": "^7.15.0",
"firebase-functions": "^3.7.0",
I am running this function locally on my nodejs server through firebase serve command.
NOTE:- when i am trying to run the same function on some other file it is perfectly running but not in this file.
Please Help
Thank You

Nothing to geocode - Weather API - Nodejs

I am new to Nodejs and trying to use weather api.
When I test the link in browser, it gives me accurate answer
http://api.openweathermap.org/data/2.5/weather?q=karachi&appid=dcf486a78f2b8e898c4b1a464a1b31e1
while it keeps throwing error.
const express = require("express")
var logger = require("morgan")
var path = require("path")
var bodyParser = require("body-parser")
let requested = require('request');
var app=express()
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.set("views", path.resolve(__dirname,"views"))
app.set("view engine",'ejs')
app.use(logger("short"))
app.get("/",function(request,response)
{
response.render("homepage")
})
app.post('/', function(request, response) {
var urlOpenWeatherCurrent = 'http://api.openweathermap.org/data/2.5/weather?'
var queryObject = {
APPID: "dcf486a78f2b8e898c4b1a464a1b31e1",
city: request.body.cityName
}
console.log(queryObject)
requested({
url:urlOpenWeatherCurrent,
q: queryObject // In many tutorials they used 'qs' instead of 'q'. I don't know why.
}, function (err, response, body) {
// response.send('You sent the name ' + request.body.cityName + ".");
if(err){
console.log('error:', error);
} else {
console.log('body:', JSON.parse(body));
}
});
});
app.use(function(request,response)
{
response.status(404)
response.send("Error")
})
app.listen(3000,()=>console.log("Working"))
Error
{ APPID: 'dcf486a78f2b8e898c4b1a464a1b31e1', city: 'karachi' }
'Invalid API key. Please see http://openweathermap.org/faq#error401 for more info.'
If I change q to qs in nodejs, then
{ APPID: 'dcf486a78f2b8e898c4b1a464a1b31e1', city: 'karachi' }
body: { cod: '400', message: 'Nothing to geocode' }
Note that changing q to qs in raw html API link also gives
{"cod":"400","message":"Nothing to geocode"}
I believe from the response that I should use qs in nodejs, because at least this time it is not considering API key wrong. But in the API link, we have q and not qs. So how come qs makes sense? Besides, as far as I Understood, it is not properly concatenating the API strings together, resulting in the malfunctioning. But I don't know how to print the entire link in console to validate what I just said.
views/homepage.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form class="pure-form" action="/" method="POST">
<input type="name" placeholder="City name" name="cityName" autofocus required>
<input type="submit" valuue="Go">
</form>
</body>
</html>
embed the "q" and "api key" with open weather url like "http://api.openweathermap.org/data/2.5/weather?q=${city}&units=imperial&appid=${apiKey}"
also Check this link
https://codeburst.io/build-a-weather-website-in-30-minutes-with-node-js-express-openweather-a317f904897b

How to get text from iframe of Dialogflow Web Demo

I'm trying to extract the server-response text from the in iframe of Dialog Web Demo
Here's my code- Currently, the output is null:
<!DOCTYPE html>
<html lang=\"en\">
<head><meta name=\"viewport\" content=\"width=device-width, initial- scale=1, user-scalable=no\"/>
<title>Dialog</title>
</head>
<body>
<div align="center">
<iframe
id="dialog"
allow="microphone;"
width="350"
height="430"
src="https://console.dialogflow.com/api-client/demo/embedded/xxxxxxxxxxxxxxxxxxxxxxxxxxx">
</iframe>
</div>
<div align="center">
<script>
var dialogFrame = document.getElementById("dialog");
var dialogDocument = dialogFrame.contentWindow.document;
var dialogResponse = dialogDocument.getElementById("server-response");
document.write(dialogResponse);
</script>
</div>
</body>
</hmtl>
I'm expecting to extract text responded by Dialogflow, but the result is null.
Data cannot be retrieved from the HTML <iframe> element, which is only a display block. Data can be retrieved through API call; in Dialogflow, you get this data with Fulfillments.
Check below flow to deploy a Node app on App Engine, serving a Dialogflow Chat at the default endpoint, and posting fulfillment data at /fulfillment endpoint.
A) Configure fulfillment
Pay attention to the following:
URL: input your HTTPS Express POST endpoint (e.g. https://[PROJECT_ID].appspot.com/fulfillment)
leave all other fields blank
Domains: Enable webhook for all domains
Once created and saved, you still need to enable fulfillment for each Intent (and their follow-up if any) that you are using
B) Application
Create a Node App in App Engine from the console
Then deploy this app, replacing the <iframe> with yours:
app.yaml
runtime: nodejs8
package.json
{
"dependencies": {
"actions-on-google": "^2.5.0",
"dialogflow-fulfillment": "^0.5.0",
"express": "^4.16.4"
},
"scripts": {
"start": "node index.js"
}
}
index.js
'use strict';
const {WebhookClient} = require('dialogflow-fulfillment');
const express = require('express');
const bodyParser = require('body-parser');
var path = require('path');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
function WebhookProcessing(req, res) {
const agent = new WebhookClient({request: req, response: res});
console.log('Dialogflow Request headers: ' + JSON.stringify(req.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(req.body));
console.log(JSON.stringify(req.body.queryResult.queryText));
console.log(JSON.stringify(req.body.queryResult.fulfillmentText));
}
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname + '/index.html'));
});
app.post('/fulfillment', function (req, res) {
WebhookProcessing(req, res);
});
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}...`);
});
index.html
<!DOCTYPE html>
<html lang=\"en\">
<head><meta name=\"viewport\" content=\"width=device-width, initial- scale=1, user-scalable=no\"/>
<title>Dialog</title>
</head>
<body>
<div align="center">
<iframe
allow="microphone;"
width="350"
height="430"
src="https://console.dialogflow.com/api-client/demo/embedded/xxxxxxxxxxxxxxxxxxxxxxxxxxx">
</iframe>
</div>
</body>
</hmtl>
When user starts a conversation in the chat, the function WebhookProcessing outputs the logs of the body and header of each request (each message sent by user), and extracts and logs the values of both fields queryText (user's message) and fulfillmentText (Bot's reply).
Note that this is just an example of integration in App Engine, you could also consider deploying a Cloud Function, and if you work with a Firebase database, then you can use the inline editor and deploy the function from Dialogflow.

Resources