How to dynamically fetch JSON based on param in express - json

I'm new to node and express but trying to dynamically fetch JSON based on the user's language settings. I need to figure out how to serve up the params:
I was thinking to try and set the "lang" param to its own variable and return that, but I am reading on SO that this is not best practice: Use variable's value as variable in javascript
var express = require("express");
var english = require('./Data/english.json');
var spanish = require('./Data/spanish.json');
var app = express();
app.use(function (req, res, next) {
console.log('inside of app.use');
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-
With, Content-Type, Accept");
next();
});
app.get("/:lang", function (req, res, next) {
const lang = req.params.lang;
console.log(lang)
res.send(lang);
});
app.listen(5000, () => console.log('Listening on port 5000!'))
I would like to be able to dynamically return the appropriate json file ! Any thoughts much appreciated.

TL;DR
Use the fs module to read you JSON files
Call JSON.parse() to parse the raw JSON
Choose the file according to var lang = req.params.lang using some kind of logic (for example, 'spanish' -> './data/spanish.json')
Code
const fs = require('fs');
// Supported languages
const supportedLanguages = ['english', 'spanish'];
app.get("/:lang", function (req, res, next) {
const lang = req.params.lang;
if (supportedLanguages.indexOf(lang) === -1) {
res.status(400).send('Language not supported');
} else {
fs.readFile(`./Data/${lang}.json`, (err, data) => {
// If error send a 500 status
if (err) res.status(500).send(err);
// Else parse the JSON file and send it
else res.send(JSON.parse(data));
});
}
});

It's simple to return json data with express.
Just use res.json({key: value , key2: value2}) instead of res.send
In your case, you can
const language = req.params.lang;
res.json({lang: lang})
you will receive a JSON object instead of text

Related

ReferenceError when trying to use a variable in an EJS template file

I'm having a heap of trouble just trying to get an EJS template file to recognise a variable that stores the rows of an SQLite3 table query in a corresponding .js file. I get a ReferenceError for the variable I used in the EJS file when launching the server and trying to access that route.
For context it's a micro blog project where I'd like authors to have the ability to save draft articles in to a database and for the user to be able to come back and modify or publish them later.
Here's my 'author.js' file:
// Author Page
const express = require("express");
const router = express.Router();
const assert = require('assert');
/**
* #desc retrieves draft articles
*/
router.get("/author-home", (req, res, next) => {
//Use this pattern to retrieve data
//NB. it's better NOT to use arrow functions for callbacks with this library
global.db.all("SELECT * FROM draftArticles", function (err, rows) {
if (err) {
next(err); //send the error on to the error handler
} else {
res.json(rows);
}
});
});
/**
* #desc Renders the author page
*/
router.get("/author", (req, res) => {
res.render("author-home", data);
});
module.exports = router;
In my 'author-home.ejs' file, I'm trying to insert various article properties in a element like so:
<td><% data[0].article_title %> </td>
<td><% data[0].article_subtitle %> </td>
...etc.
Can anyone tell me what I'm doing wrong? I can also post the code for my 'index.js' file if that's helpful. Many thanks in advance
EDIT:
After some suggestions were sent and the scope issue of the 'data' variable was highlighted, I corrected my code in author.js (at least, I believe so) to the following:
// Author Page
const express = require("express");
const router = express.Router();
const assert = require('assert');
router.get('/author-home', (req, res, next) => {
global.db.all('SELECT * FROM draftArticles', function (err, rows) {
if (err) {
console.log("No data found.")
next(err); //send the error on to the error handler
return;
}
res.render('author-home', { data: rows });
});
});
module.exports = router;
However, I still receive a referenceError when trying to access data in my EJS file.
I also tried, as was suggested, to pass static data like so:
let dummyData = "This is test data";
router.get('/author-home', (req, res, next) => {
res.render('author-home', { data: dummyData });
});
Also receiving a referenceError.
This is because you have not defined "data". You need to define it if you want to send an array you can use
How can I pass an array to an ejs template in express?
your code should be like..
// Author Page
const express = require("express");
const router = express.Router();
const assert = require('assert');
router.get('/author-home', (req, res, next) => {
global.db.all('SELECT * FROM draftArticles', function(err, rows) {
if (err || !rows || !rows.length) {
console.log("No data found.")
// also try to log rows here to see what you are getting. does the "rows" have atricle_title etc attributes or not?
next(err || new Error("No Data found!")); //send the error on to the error handler
return;
}
res.render('author-home', {
data: rows
});
});
});
module.exports = router;

How parse JSON properties from request body in express server?

I've set up a node server that passes requests to a utility class.
So far the POST request is hit but the mapping to the body property values are undefined. Bodyparser is also used in the post method to assist in the Json parse.
I stepped into the request and see that the body is populated and see that the property names are correct as shown in the paste below:
body: { '{\n\t"Email":"brian#gmail.com",\n\t"Dashboard_Name":"my dash 4",\n\t''},
But the below mapping to the values assinged via req.body.propertyname return undefined:
var p_email = req.body.Email;
var p_dashboardName = req.body.Dashboard_Name;
Question:
How can you parse JSON properties from request body in express server?
JSON object posted:
This is the JSON that I post to the server using Postman:
{
"Email":"brian#gmail.com",
"Dashboard_Name":"my dash 4"
}
Gist of the express server and associated utility method SaveUserProfile:
Express server -
var express = require('express');
var UserLDAP = require('./utilities/UserLDAP'); //utility file containing the POST method
var bodyParser = require('body-parser');
const url = require('url');
const app = express();
var sql = require('mssql');
const cors = require('cors');
const path = require('path');
sql.connect("********************************************************************")
.then((connection1) => {
sql.globalConnection = connection1;
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/OOO/SaveUserProfile', UserLDAP.SaveUserProfile)
app.listen(process.env.PORT || 4000 );
logger.info(`listening to port ${process.env.PORT}`);
}).catch((err) => {
res.status(500).send(err.message);
logger.error(err.message);
});
UserLDAP.js -
var sql = require('mssql');
var bodyParser = require('body-parser');
//Save User Profile
exports.SaveUserProfile = function(req, res) {
req.app.use(bodyParser.json());
req.app.use(bodyParser.urlencoded({ extended: true }));
var request = new sql.Request(sql.globalConnection);
console.log(req);
var p_email = req.body.Email;
var p_dashboardName = req.body.Dashboard_Name;
};
Turns out I had incorrect content-type set in Postman on the object being posted. Needed to be set as:
application/json; charset=UTF-8
Currently you have no way of knowing if a parser like body-parser.json has produced an error which seems the obvious place to start given the content is there but the result isn't.
I had a look at body-parser and found an issue that spoke to the problem of detecting a json error which I would expect to be good to know.
The developer suggested the following as one method.
app.use(errorFork(bodyParser.json(),
function (err, req, res, next) {
// do stuff with only body parser errors
}))
// this is an example; you can use any pattern you like.
function errorFork(middleware, errorHandler) {
middleware(req, res, function (err) {
if (err) {
return errorHandler(err, req, res, next)
}else{
return next()
}
})
}
It isn't a fix but it would give you more info. Something is going wrong with the parsing by what you have indicated the questin is what? The other thing I noticed about your pasted body content is that it isn't valid json (ignoring \n\t) you have a few rouge ' in there, worth checking. Try copying what is in body (raw) and put it through a json validator site like jsonlint.com just as a double check and see if body-parser is returning any errors.

Parsing JSON in Express without BodyParser

I'm trying to write a simple express server that takes incoming JSON (POST), parses the JSON and assigns to the request body. The catch is I cannot use bodyparser. Below is my server with a simple middleware function being passed to app.use
Problem: whenever I send dummy POST requests to my server with superagent (npm package that lets you send JSON via terminal) my server times out. I wrote an HTTP server in a similar fashion using req.on('data')...so I'm stumped. Any advice?
const express = require('express');
const app = express();
function jsonParser(req, res, next) {
res.writeHead(200, {'Content-Type:':'application/json'});
req.on('data', (data, err) => {
if (err) res.status(404).send({error: "invalid json"});
req.body = JSON.parse(data);
});
next();
};
app.use(jsonParser);
app.post('/', (req, res) => {
console.log('post request logging message...');
});
app.listen(3000, () => console.log('Server running on port 3000'));
I think the problem like to get rawBody in express.
Just like this:
app.use(function(req, res, next){
var data = "";
req.on('data', function(chunk){ data += chunk})
req.on('end', function(){
req.rawBody = data;
req.jsonBody = JSON.parse(data);
next();
})
})
And you need catch the error when parse the string to json and need to judge the Content-type of the Req.
Good luck.
another way that worked with me by collecting all chunks into an array and parsing the concatenated chunks.
app.use("/", (req, res, next)=>{
const body = [];
req.on("data", (chunk) => {
console.log(chunk);
body.push(chunk);
});
req.on("end", () => {
const parsedBody = Buffer.concat(body).toString();
const message = parsedBody.split('=')[1];
console.log(parsedBody);
console.log(message);
});
console.log(body);
});
To get access to req.body this worked for me:
app.use(express.json({extended: false}));
In Express v4.16.0 onwards:
app.use(express.json())

Make REST API on Meteor+React without other packages

For example, when the path is
/json/users/4
meteor app must return json something like
{
id: 4,
name: 'Alex'
}
I'm using reactrouter:react-router for client routing. I know about reactrouter:react-router-ssr, but how to use it to response raw json? And make it not conflicting with existing client routing?
I found the answer. Meteor's default Webapp package will help (doc):
WebApp.connectHandlers.use("/hello", function(req, res, next) {
res.writeHead(200);
res.end("Hello world from: " + Meteor.release);
});
I put this in server folder. Other routes will be rendered as they was.
So, there is more useful example (es6):
WebApp.connectHandlers.use("/payme", function(req, res, next) {
res.writeHead(200, {'Content-Type': 'application/json'});
if (req.method === 'POST') {
req.on('data', (chunk) => {
const body = chunk.toString();
if (body.length < 1e6) {
const params = body.split('&').reduce((result, item) => {
const [key, val] = item.split('=');
//do it for utf-8 values (I use it for cyrillic strings)
result[key] = unescape(decodeURI(val)).replace(/\+/g, ' ');
return result;
}, {}); //post method params
//do something and get resulting json
res.end(JSON.stringify(result));
} else
res.end(JSON.stringify({error: 'too big query'}));
});
} else
res.end(JSON.stringify({error: 'isnt post req'}));
});
req.query can be used to get GET params.

RESTify on Node.js POST body / json

I am in need of help. I am POSTing json data to my node server. The node server is using RESTify for its API. I am having trouble getting req.body.name from the body of the posted data.
The posted data contains a json body. In it i have keys such as name, date, address, email, etc.
I want to get the name out of the json body. I am trying to do req.body.name but it is not working.
I have also included server.use(restify.bodyParser()); and it is not working.
I am able to req.params.name and assign a value. But if I POST json data like: {'food': 'ice cream', 'drink' : 'coke'}, I am getting undefined. However, If I do req.body, I get the full json body posted. I want to be able to specifically get an item like 'drink' and have that show on console.log.
var restify = require('restify');
var server = restify.createServer({
name: 'Hello World!',
version: '1.0.0'
});
server.use(restify.acceptParser(server.acceptable));
server.use(restify.jsonp());
server.use(restify.bodyParser({ mapParams: false }));
server.post('/locations/:name', function(req, res, next){
var name_value = req.params.name;
res.contentType = 'json';
console.log(req.params.name_value);
console.log(req.body.test);
});
server.listen(8080, function () {
console.log('%s listening at %s', server.name, server.url);
});
If you want to use req.params, you should change:
server.use(restify.plugins.bodyParser({ mapParams: false }));
to use true:
server.use(restify.plugins.bodyParser({ mapParams: true }));
Have you tried using the standard JSON library to parse the body as a json object? Then, you should be able to grab whatever property you need.
var jsonBody = JSON.parse(req.body);
console.log(jsonBody.name);
In addition to below answer . The latest syntax in restify 5.0 has been change .
All the parser that you are looking for is inside restify.plugins instead of restify use restify.plugins.bodyParser
The method to use it is this.
const restify = require("restify");
global.server = restify.createServer();
server.use(restify.plugins.queryParser({
mapParams: true
}));
server.use(restify.plugins.bodyParser({
mapParams: true
}));
server.use(restify.plugins.acceptParser(server.acceptable));
var restify = require('restify')
const restifyBodyParser = require('restify-plugins').bodyParser;
function respond(req, res, next) {
console.log(req.body)
const randomParam = req.body.randomParam
res.send(randomParam);
next();
}
var server = restify.createServer();
server.use(restifyBodyParser());
server.post('/hello/:name', respond);
server.head('/hello/:name', respond);
server.listen(8080, function() {
console.log('%s listening at %s', server.name, server.url);
});
... Is what worked for me with restify version 8.3.2
you must use req.params with bodyParser active.
var restify = require('restify');
var server = restify.createServer({
name: 'helloworld'
});
server.use(restify.bodyParser());
server.post({path: '/hello/:name'}, function(req, res, next) {
console.log(req.params);
res.send('<p>Olá</p>');
});
server.get({path: '/hello/:name', name: 'GetFoo'}, function respond(req, res, next) {
res.send({
hello: req.params.name
});
return next();
});
server.listen(8080, function() {
console.log('listening: %s', server.url);
});