node js function called from a JavaScript code - node.js

So I have a node js code that updates and modifies a file content but I would like the data being inserted to come from a JavaScript code. How do I connect the two? Basically how do I have a function in node js that can be called from JavaScript?

Considering there's not much information to go off in the question, I am going to make a the assumption that you're trying to pass information from JS in a web browser to a node application.
The easiest and best documented way to do this would be to set up a simple web server using a package like expressJS and send data as a POST request using the fetch command in the browser.
Install express on the node application using the getting started guide
Write a http path where you can process the data
Start the node app
Make a call to the path we just created
Example backend code:
const express = require('express')
var bodyParser = require('body-parser')
const app = express()
const port = 3000
app.use(bodyParser);
app.post('/mypath', (req, res) => {
const myInputData = req.body.data;
//Do whatever you want with the data
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
Example front-end code:
var data = new FormData();
data.append('data', YOUR_DATA_VAR_HERE)
var options = {
method: 'POST',
body: data
}
fetch('http://localhost:3000/mypath',options)
.then(function(response){ console.log("Data was sent successfully") })
.catch(function(error) { console.log("There was an error sending data") })

Related

Node JS post API endpoint not recognized in front end

I'm trying to make a post request using appwrite SDK in Node JS express and Vue JS. The SDK requires me to create an api post request to create new storage bucket in appwrite. The DOCs for this particular request isn't explaining really how to create the api in node JS express. I'm really new to Node JS and I already succeeded at creating get request but whenever I create the post request I get 404 not found error.
Node JS express file (server.js):
In this file there is get users request API which works perfectly fine.
And there is create bucket post request which when being called in frontend it comes back with a 404
const express = require("express");
const path = require("path");
const app = express(),
bodyParser = require("body-parser");
port = 3080;
// Init SDK
const sdk = require("node-appwrite");
let client = new sdk.Client();
let users = new sdk.Users(client);
let storage = new sdk.Storage(client);
client
.setEndpoint("http://localhost/v1") // Your API Endpoint
.setProject("tailwinder") // Your project ID
.setKey(
"Secrer Key!"
); // Your secret API key
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, "../appwrite-app/build")));
//This get request works fine
//get user by ID
app.get("/v1/users/:id", (req, res) => {
let promise = users.get(req.params.id);
promise.then(
function (response) {
res.json(response);
},
function (error) {
console.log(error);
}
);
});
//This one isn't recognised in frontend
app.post("/v1/storage/buckets", function (req, res) {
let promise = storage.createBucket("bucket_id", "bucket_name", "file");
promise.then(
function (response) {
res.json(response);
},
function (error) {
console.log(error);
}
);
});
app.listen(port, () => {
console.log(`Server listening on the port::${port}`);
});
bucketsServices.js:
Here I'm using fetch post request to the api endpoint but it's not working.
export async function createBucket() {
const response = await fetch("/v1/storage/buckets", {
method: "POST",
});
return await response.json();
}
Addcomponent.vue:
Here I'm calling out the createBucket function from vue js file
bucketTesting() {
createBucket().then((response) => {
console.log(response);
});
},
The error which I assume it means that it's not reading my node js express post API:
bucketsService.js?993b:2 POST http://localhost:8080/v1/storage/buckets 404 (Not Found)
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
A screenshot of the same error:
Something is missing here and I can't really figure it out.
You are making request to localhost:8080 meanwhile your server is running at localhost:3080
I believe your vue is running at port 8080 that's why /v1/storage/buckets gets prefixed by localhost:8080
Try to provide full URL while making request
export async function createBucket() {
const response = await fetch("localhost:3080/v1/storage/buckets", {
method: "POST",
});
return await response.json();
}
Better way might be to add proxy to automatically redirect request to correct URL, but this should work for now. This article might help with how to setup proxy in vue

How to call external api's data from backend to frontend side?

I'm trying to weather Api app using node, express and Axios in backend part without using any framework like Angular or react.
I have 3 main file for my codes.
index.html
customer.js (for front end part)
server.js (for backend part)
My backend part like below;
const express = require('express');
const app = express();
const axios = require('axios').default;
API_KEY = "***";
const PORT =3000;
// app.use("/static", express.static(__dirname + '/customer'));
app.get('/', (req, res) =>{
axios
.get(`http://api.openweathermap.org/data/2.5/forecast?q=amsterdam&appid=${API_KEY}`)
.then(resp => {
let weatherDetail = resp.data;
console.log('a single country details: ', weatherDetail);
res.send(weatherDetail);
})
.catch(err => console.log(err));
});
app.listen(PORT, () => console.log(`My app listening on port ${PORT}! `));
When I write localhost:3000 on browser, I can see the weather api's data. However I want to see html file with functions in customer.js and api's data. Therefore I tried to write res.sendFile((__dirname + '/index.html')); inside app.get('/', (req, res)) function. However, in this situation I can see only html page without getting data from backend.
How can I call data getting from backend part in frontend part inside customer.js file?
My codes in customer.js like below (but I'm not sure if I use axios agan inside this file)
const apiCall = cityName => {
let apiKey = "***";
let apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=${apiKey}&units=metric`
axios
.get(apiUrl)
.then(getWeather)
.catch(err => {
console.log(err);
err.response.status === 404 ? alert(`The country ${cityName} doesn't exist.`) : alert('Server error! Sorry.');
});
};
apiCall(amsterdam)
function getWeather (response) {
let city = document.querySelector("#city");
city.innerHTML = response.data.name;
.
.
.
.
}
I would recommend to use a templating engine like handlebars or ejs.There are tons of examples for it, and sending data from backend to frontend becomes a piece of cake when using any templating engine. my personal favourite is handlebars because of its simple syntax.
It is advisable not to use document.querySelector if you're using Angular or React. React/Angular will have the browser repaint the DOM by making updates in the "root" div element of the index.html file whenever there is new data available to update.
Also, why do you want to send a HTML file? You could have a route in Node like below
route.get('/weather', (req, res) => {
// do your api call with axios to get weather data
res.json(weatherData);
});
from your front-end you could make an API call to '/weather' route and consume the JSON data
axios.get('baseUrl/weather').then(res=>{
console.log("weather data", res);
}).catch(...);
You could also fetch weather data directly from front-end like above.

In what file do we connect react front end folder files with back-end folder files with server.js and mysql database connection?

I have front-end folder files with react components and front-end css libraries.
In different folder, I have back-end files with server.js routing with mysql connection.
When I enter inputs on the screen, the inputs are not saved to mysql database.
Questions:
In what file, do I connect my front-end with back-end?
What statement should I use to connect my front-end with back-end?
To start Front-end, I used: npm start and To start Back-end, I used: nodemon server.js.
Question: When I connect front-end and back-end, what file should I open so that the front-end talks with the back-end -> both are starting?
Question 1 answer
You can do this a number of ways. I've done this with Serverjs and react in the
following manner.
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const port = 80085;
const app = express();
const token = 'impossiblylongimportanttokenhere';
let nextId = 7;
You'll need to import CORS, a Parser, Express for routing purposes.
Assuming you'll have a login you'll want a authenticator function. Please note this is just for development.
function authenticator(req, res, next) {
const { authorization } = req.headers;
if (authorization === token) {
next();
} else {
res.status(403).json({ error: 'User must be logged in to do that.' });
}
}
You'll probably want to replace that with something more secure once you're don with development.
with app as our router express has several CORS methods to get us started likepostget
Here's an example of one if we had an array called friends and if we wanted to find that friend by ID.
app.get('/api/friends/:id', authenticator, (req, res) => {
const friend = friends.find(f => f.id == req.params.id);
if (friend) {
res.status(200).json(friend);
} else {
res.status(404).send({ msg: 'Friend not found' });
}
});
The best part is that express has a method called listen that will start as soon as we hit NPM RUN on a cli that's parked in the same file location as server.js. Make sure to specify a port that your system isn't already using
app.listen(port, () => {
console.log(`server listening on port ${port}`);
});
Question 2
In order to get connect to Server.js on our side you'll want use axios to make a GET/POST etc. call to whatever route you've made in your server.js above in the example it would be
.post('/api/friends', this.state.addFriend)
The biggest thing is you'll want multiple terminals running in order to have both the backend and the front end running at the same time. Start with backend first.

How to show health status of node server on HTML

I have two servers. One is server1 running on port 8080 and another one is main app server which is running on 8081. Now i want to showcase the health status of server1 on UI(HTML) which is running on main app server(8081).I want to display the these elements on HTML.
1.Status code of server one.
2.Server is UP Or Down.
3.Response of the server one.
This is my nodejs code.
const express = require('express');
const http = require('http');
const fs = require('fs');
const bodyParser = require('body-parser');
const router = express.Router();
const path = require('path');
const ejs = require('ejs');
const app = express();
const server1 = express();
server1.get('/health', function (req, res, next) {
res.json({health: true});
res.status(200).end();
});
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.get('/', (req,res) => {
res.render('index');
console.log('server two')
})
server1.listen(8080);
app.listen(8081);
Ajax part:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
document.getElementById("#demo1").innerHTML = xmlhttp.responseText;
}
else if (xmlhttp.status == 400) {
alert('There was an error 400');
}
else {
document.getElementById('demo1').innerHTML = 'something else other than 200 was returned';
}
}
};
xmlhttp.open("GET", "http://localhost:8080/health", true);
xmlhttp.send();
HTML:
<div id="demo1"></div>
What should i exactly do to display the health status of server1 on UI.
I've wrote and published a Node App with a React front-end that does exactly this. It's purely open source and free to use.
It allows you to define a list of websites, webapps, API endpoints and servers to monitor in JSON.
The React front-end provides a dashboard showing state of each asset. The backend will periodically call each 'asset' in your list and record state and response time and also broadcast the results to any connected client via Sockets.io.
Feel free to install as an NPM package, or go onto GitHub and clone the repo.
I understand you might not want an out of the box solution, so feel free to take a look at my code to help you in building your own solution.
NPM Link
GIT HUB Link
Running example on Heroku
You could create a specific route that will be called on a specific setInterval() by your front-end javascript. This route could return a JSON with an errors array if there are any. Something along the lines of:
app.get('/health-check', (req,res) => {
// check database connectivity and any other staff you want here
// add any errors in an array
if (errors.length > 0) {
return res.status(500).json({health: false, errors: errors});
}
return res.status(200).send({health: true});
});
Be careful as there may exist errors that you don't want to show to your user. This will depend on the type of application etc.
Then make an AJAX call from your front-end JS code within a setInterval() function. The implementation of this will depend of the library/framework you use if you do but using jquery for example would be like:
const healthTimer = setInterval(() => {
$.ajax({
url: "[your server url]/health-check",
type: "GET",
success: function(xml, textStatus, xhr) {
// get the server status here if everything is ok
$('div.server-health span.success').text(`Server Status: ${xhr.status}`);
$('div.server-health span.error').text('');
console.log('RESPONSE CODE:', xhr.status);
},
error: function (request, status, error) {
// handle the error rendering here
$('div.server-health span.error').text(`Server Status: ${status}`);
$('div.server-health span.success').text('');
alert(request.responseText);
}
});
}, 15000); // send the request every 15 seconds
Inside your html file you can have a <div> to show the server health:
<div class="server-health">
<span class="error"></span>
<span class="success"></span>
</div>

res.download(NodeJS) not triggering a download on the browser

I've been struggling with this for a while and can't seem to find an answer, I'm developing a website with a budgeting option, I'm sending an object from the client to the server, and that server is using PDFKit to create a PDF version of the budget, once it's created I want to actually send back that PDF to the client and trigger a download, this is what I've done
Client-side code:
let data = {
nombre: this.state.name,
email: this.state.email,
telefono: this.state.phone,
carrito: this.props.budget.cart,
subTotal: this.props.budget.subTotal,
IVA: this.props.budget.tax,
total: this.props.budget.subTotal + this.props.budget.tax
}
axios({
method: 'post',
url: 'http://localhost:1337/api/budget',
data: data
})
.then((response) => {
console.log('This is the response', response);
window.open('/download')
})
.catch((error) => {
alert(error);
})
So that data goes to my server-side code perfectly and it looks like this
const pdf = require('pdfkit');
const fs = require('fs');
const path = require('path');
exports.makePDFBudget = (req, res) => {
let myDoc = new pdf;
myDoc.pipe(fs.createWriteStream(`PDFkit/budget.pdf`));
myDoc.font('Times-Roman')
.fontSize(12)
.text(`${req.body.name} ${req.body.phone} ${req.body.email} ${req.body.cart} ${req.body.subTotal} ${req.body.total} ${req.body.tax}`);
myDoc.end()
}
That's creating my PDF, what I want now is that once it's created and the response is sent back to the client, the client opens a new window with the URL "/download" which is set to download that PDF, but that's not happening for some reason, it opens up the new window but the download never starts and it throws absolutely no error I'm my Node console or browser console
this is how I send my file to the client
const fs = require('fs');
const path = require('path');
exports.downloadPDFBudget = (req, res) => {
res.download(__dirname + 'budget.pdf', 'budget.pdf');
}
And this is how my server index looks like
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
const api = express.Router();
const { makePDFBudget } = require('./PDFkit/makePDFBudget.js');
const { downloadPDFBudget } = require('./PDFkit/downloadPDFBudget.js')
app.use(express.static(__dirname + '/../public'));
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json({extended: true}));
api.route('/budget')
.post(makePDFBudget)
api.route('/download')
.get(downloadPDFBudget)
app.use('/api', api);
const port = 1337;
app.listen(port);
console.log('Listening on port ', port);
module.exports = app;
I just solved it, the port in which I was running my client obviously was different from the one I was running my server, so I had to open a window to my server's port to trigger the download, I realized this because I threw a console log on the function that was supposed to do the res.download it wasn't showing up. Thanks!
I guess the main problem here:
res.download(__dirname + 'budget.jpg', 'budget.pdf');
Make a correct file name. Your file is pdf, not jpg.
At this code res.end(Buffer.from('budget.pdf')) you sending string, not file content. But headers like you want to send a file.
The last. Your application designed like you will have only one user. Could you add userId to file names? Or use DB for storing data and generate pdf on request without storing a file to the file system.

Resources