I'm using request-promise to request two JSON data files which exist locally in my local project directory folder.
ie:
However, I am getting a 500 internal server error, when trying to pass the data to the view and my node console outputs 'Error: Invalid URI "/"',
Please see below:
server.js
let express = require('express');
let app = express();
let path = require('path');
const rp = require("request-promise");
//STORE PATH for local JSON files on variables
let guest = require('./public/data/Companies');
let hotel = require('./public/data/Guests');
app.set("port", process.env.PORT || 5000);
//GET JSON
//Question: Is it okay to pass uri:guest
app.get('/data', function(req, res) {
Promise.all([rp({uri: guest, json: true}), rp({uri: hotel, json: true})]).then(function([hotels, guests]) {
//res.json({hotels, guests});
res.send({hotels, guests});
console.log(hotels, guests);
}).catch(function(err) {
console.log(err);
res.status(500).end();
});
});
//CATCHALL
app.get("/*", function(req,res){
let file = req.params[0] || "/views/index.html";
res.sendFile(path.join(__dirname, "/public/", file));
});
//SET PORT
app.listen(app.get("port"), function(){
console.log("Listening on port: " , app.get("port"));
});
then on client.js:
$(function() {
$.ajax({
type: "GET",
url: "/data",
success: function (res) {
console.log(res);
}
});
});
Why do you use request to get the data? Why don't you use the filesystem module from Node.js (fs) to get the data? When you call rp(), you should pass an absolute URI and not a local path.
To use it in your code, you need to "promisify" the readFile function:
let readFileAsAPromise = function(filename){
return new Promise(function(resolve, reject) {
fs.readFile(filename, (data, err) => {
if(err) reject(err);
resolve(data)
})
})
}
You can then you Promise.all.
Why aren't you simply returning the variables?
I mean:
app.get('/data', function(req, res) {
res.send({hotels, guests});
});
Related
I start learning Node.js and Express.js and I'm trying to create a simple API to list data from JSON file (using the GET method) and add a new user using the POST method.
the GET method works fine but the POST method does not work
when I request http://127.0.0.1:8080/listusers the API sends all users in a JSON file.
when I request http://127.0.0.1:8080/adduser the API has to add new User Info and send the new data back to the browser.
NOTE: I read all the questions on Stackoverflow about this problem but
non of them help me so I have to ask again.
the problem is when I request http://127.0.0.1:8080/adduser I get the following error
Cannot GET /adduser
here is the server.js:
var express = require('express');
var app = express();
var fs = require('fs');
var user = {
"user4" : {
"name" : "mounir",
"password" : "password4",
"profession" : "teacher",
"id": 4
}
};
app.post('/adduser', function (req, res) {
// First read existing users.
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
data = JSON.parse( data );
data["user4"] = user["user4"];
console.log( data );
res.end(JSON.stringify(data) );
});
});
app.get('/listusers', function (req, res) {
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
console.log(data);
res.end(data);
});
});
var server = app.listen(8080, function () {
var host = server.address().address;
var port = server.address().port;
console.log("listening at http://%s:%s", "0.0.0.0", port)
});
The answer is in the error. Cannot GET /adduser. Keyword GET! If you are making a post request, be sure you include the appropriate headers and that you are making a POST request, with a body, and not a GET request. For instance if you are using fetch:
const myInit = {
method: 'POST',
headers: myHeaders,
body: {
...
}
};
fetch("http://127.0.0.1:8080/adduser", myInit)
.then(res => {
...
});
How to get data from my function Data() instead of JSON PLACE HOLDER mock API using HTTPS/HTTP node module and how to make an endpoint of this get data HTTP/HTTPS module to utilize response in front end just like Angular?
My mock backen.js file:
const https = require('https');
https.get(Data.data, res => {
let data = [];
const headerDate = res.headers && res.headers.date ? res.headers.date : 'no response date';
console.log('Status Code:', res.statusCode);
console.log('Date in Response header:', headerDate);
res.on('data', chunk => {
data.push(chunk);
});
res.on('end', () => {
console.log('Response ended: ');
const users = JSON.parse(Buffer.concat(data).toString());
for(user of users) {
console.log(`Got user with id: ${user.id}, name: ${user.name}`);
}
});
}).on('error', err => {
console.log('Error: ', err.message);
});
function Data() {
var data = {};
........
return data;
}
Your time and help will be really appreciated. Thanks :)
Hurray! I got it using the following code and Express in node js. I simply call my custom method that creates data into an express "get" endpoint. When I hit the end point the response will be my custom method result.
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/data', (req, res) => {
res.send(
getDashboardData());
});
app.listen(3000, () => {
console.log('server is listening on port 3000');
});
function Data() {
var data = {};
..........
//console.log(JSON.stringify(data));
return JSON.stringify(data);
}
So, let's say i have /api/cat/fact.js directory.
I wanna to get JSON Data from catfact.ninja
The thing is, i can't use require() or request() package, because if i used require, it would saya Couldnt Found Module..., and if i used request one, instead of returning the JSON Data that you beable to sees in catfact.ninja, it return JSON about the api, like hostname, port, which is i don't need
/API/api/cat/fact.js:
const express = require('express');
const app = express.Router();
const request = require('request')
app.use('', (req, res) => {
const src = 'https://catfact.ninja/fact';
const facts = request({
uri: src,
hostname: 'catfact.ninja',
port: 443,
path: '/fact',
method: 'POST',
json: 'fact'
}, (error, response, body) => {
if (error) console.log(error)
console.log(body, '\n\n' + response.fact)
})
console.log(facts);
return res.jsonp(facts)
})
module.exports = app;
You are returning JSON in the wrong place. It should be returned inside of the callback function.
Here's the solution:
const express = require('express');
const request = require('request-promise')
const app = express();
app.use('', async (req, res) => {
const src = 'https://catfact.ninja/fact';
try {
const response = await request({
uri: src,
port: 443,
method: 'GET',
json: true
})
return res.jsonp(response)
} catch (err) {
return res.jsonp(err)
}
})
function startServer() {
const port = 3000
app.listen(port, () => {
console.info('Server is up on port ' + port)
})
app.on('error', (err) => {
console.error(err)
process.exit(1)
})
}
startServer()
TIP: I suggest using request-promise npm package instead of request package as it provides async-await approach, which is cleaner. Else, you can continue using callback function as second request() function parameter.
Client code:
var data = new FormData();
data.append(fileName, blob, 'test.html');
fetch('http://localhost:3000/', {
method: 'POST',
headers: {
},
body: data
}).then(
response => {
console.log(response)
}
).then(
success => {
console.log(success)
}
).catch(
error => {
console.log(error)
}
);
Server code:
router.post('/', urlencodedParser, function(req, res, next) {
const body = req.body;
console.log(body);
res.send(`You sent: ${body} to Express`);
});
I am sending a blob in the body of a post request. When I send it to the server I want the server to download the file from the body of the request. How can i download this file? Or is there a simpler way to upload from client?
If you can utilize an NPM package formidable, there appears to be a solution at: https://www.w3schools.com/nodejs/nodejs_uploadfiles.asp
Once you have the file received, you can use the fs module to save and store in server
May it can solve your problem.
const fs = require('fs');
let directory = '/temp/data'; // where you want to save data file
router.post('/', urlencodedParser, function(req, res, next) {
const body = req.body;
console.log(body);
fs.writeFile(directory, body, function(err) {
if(err) {
return console.log(err);
}
console.log("File has been saved");
});
res.send(`You sent: ${body} to Express`);
});
This solved my answer - https://attacomsian.com/blog/uploading-files-nodejs-express, which basically uses a middleware to do the upload.
This was basically like:
const x = 6;
console.log(x);
Error: value is f'd up
const x = 6;
magic.valueParse(x);
console.log(x);
6
Also, i would like to point out how bodyParser cannot be used for multipart data. It is mentioned on the official docs, but even responses I get seem to point to bodyParser. So I thought I'd re-iterate that.
So I am trying to send the data from the client to server and then at the server I am creating a new File and in the router I am sending back response to download that file.
But I could not achieve it. I am using AJAX call. Following is my code:
My Ajax call on clicking a button:
$.ajax({
type: 'POST',
url: '/createDownloadFile',
data: JSON Object,
}).done(() => {
window.open('/download');
});
In express.js:
app.post('/createDownloadFile', (req, res) => {
downloadFile.createDownloadFile(req);
res.send('SUCCESS');
});
downloadFile in a JS below:
const fs = require('fs');
const path = require('path');
module.exports.createDownloadFile = (request) => {
if (request) {
let filePath;
const userID = 'xyz';
filePath = path.join(__dirname, userID.concat('.txt'));
const dataToWrite = request.body;
fs.openSync(filePath, 'w', (err) => {
if (err) throw new Error('FILE_NOT_PRESENT');
});
fs.appendFileSync(filePath, JSON.stringify(dataToWrite, null, 4), (err) => {
if (err) throw new Error('FILE_WRITE_ERROR');
});
return filePath;
}
};
Also, in my router.js file:
router.get('/download', (req, res) => {
const filePath = makeDownloadFile.createDownloadFile(req);
res.download(filePath);
});
But seems like when I invoke the AJAX call it creates the file but unable to write in the file?
What I am missing?