I am trying to write a small API logger as an Express middleware. The logger collects various pieces of information from the req and res, then saves a JSON file to disk that can be read later.
This is my current function to store the logs.
function store(req, res, next) {
init();
const log = {
request_url: req.hostname,
request_body: req.body,
request_method: req.method,
request_headers: req.headers,
api_endpoint: req.baseUrl,
timestamp: moment().format('x')
};
res.on('finish', () => {
log.response_body = res.body;
log.response_status = res.statusCode;
global.enoch_logs.push(log);
fs.writeFile(`./logs/${ moment().format('x') }.json`, JSON.stringify(log), (err) => (err) ? console.log(err) : null);
});
next();
}
The problem is that res.body is always empty. I have tried a few different methods to capture the response body but nothing seems to work.
Where am I going wrong?
Related
I would like to get the data from session variable (req.user.username) then use it for posting. I'm using passportjs as authentication. I'm using router. Here is my code:
router.use('/login', passport.authenticate("local-register", async (err, user, info) => {
if (err) {
return next('Error');
}
if (!user) {
return next('Error');
}
req.user = user;
return req.login(user, (error: Error) => {
if (error) {
return next('Error');
}
return req.session.save((erro: Error) => {
if (erro) {
return next('Error');
}
return next();
});
});
})(req, res, next);)
router.get('/', async (req, res) => {
console.log(req.user.username) // working just fine
});
router.post('/upload', async (req, res) => {
const uploaderName = req.user.username // I'm getting undefined
const upload = await database.query('INSERT INTO user WHERE username=$1', [uploaderName])
console.log(uploaderName);
})
So I finally found the answer to the question. For those who will encounter the problem in the future. You just add the session middleware AGAIN on the top of the routes. If your routes are separated to the main server file.
/src/routes/routes.ts -> add again the middleware on top.
const app = router();
app.use(sessions) // -> right here you need to add the middleware again to //access the req.user session variable
app.get('/', async (req, res) => {
console.log(req.user.username) // working just fine
});
app.post('/upload', async (req, res) => {
const uploaderName = req.user.username // I'm getting undefined
const upload = await database.query('INSERT INTO user WHERE username=$1', [uploaderName])
console.log(uploaderName);
})
I have the following endpoint:
app.get('/users/:id', async (req, res) => {
const _id = req.params.id;
try {
const user = await User.findById(_id);
if(!user) {
res.status(404).send();
}
res.send(user);
} catch (e) {
res.status(500).send(e);
}});
When I make the request with a valid user ID, the server sends back the user, no problem with that.
The problem is when I try to find a user with a ID which doesnt exist in the database. The server should response with a 404 Error but instead it sends back a Error 500 and I dont understand why!
Could anyone help me please?
Thank you in advance!
One nice way to handle the errors is to create an express error middleware, this allows you to put all of your error handling in one place so that you dont have to write it more than once.
With express when you use async routes handlers if a promise rejects the error will automatically be passed to the next error middleware.
// First register all of your routes
app.get('/user/:id', async (req, res) => {
const user = await User.findById(req.params.id);
if(!user) return res.status(404).send();
res.send(user);
})
// Then register you error middleware
app.use((err, req, res, next) => {
console.error(err.message)
// if mongoose validation error respond with 400
if(err.message.toLowerCase().includes('validation failed'))
return res.sendStatus(400)
// if moongoose failed because of duplicate key
if(err.message.toLowerCase().includes('duplicate key'))
return res.sendStatus(409)
// if mongoose failed to cast object id
if(err.message.toLowerCase().includes('objectid failed'))
return res.sendStatus(404)
res.sendStatus(500)
})
Thank you for your answers.
I have solved it adding the following to the user model schema:
_id: {type: String}
And adding a return before sending the 404 error:
app.get('/users/:id', async (req, res) => {
const _id = req.params.id;
try {
const user = await User.findById(_id);
if (!user) {
return res.status(404).send();
}
res.send(user);
} catch (error) {
res.status(400).send(error);
}});
I have an application Javascript file that is showing an error in the console section of VS Studio Code, it keeps saying: app.js: The parser expected to find a '}' to match the '{' token here. and the console will not compile.
Based on my code, would you be able to tell me where I need to close in my braces? I think I might be confused.
Here is my app.js code:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
//specify where to find the schema
const Item = require('./models/item')
// connect and display the status
mongoose.connect('mongodb://localhost:27017/items', { useNewUrlParser: true })
.then(() => { console.log("connected"); })
.catch(() => { console.log("error connecting"); });
// use the following code on any request that matches the specified mount path
app.use((req, res, next) => {
console.log('This line is always called');
res.setHeader('Access-Control-Allow-Origin', '*'); //can connect from any host
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, OPTIONS'); //allowable methods
res.setHeader('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept');
next();
});
app.get('/items', (req, res, next) => {
//call mongoose method find (MongoDB db.Students.find())
Item.find()
//if data is returned, send data as a response
.then(data => res.status(200).json(data))
//if error, send internal server error
.catch(err => {
console.log('Error: ${err}');
res.status(500).json(err);
});
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
// serve incoming post requests to /items
app.post('/items', (req, res, next) => {
const items = req.body;
console.log(items.itemName + " " + items.servings);
//sent an acknowledgment back to caller
res.status(201).json('Post successful');
});
//to use this middleware in other parts of the application
module.exports=app;
Your app.get('/items' function is not closed. Try this.
app.get('/items', (req, res, next) => {
//call mongoose method find (MongoDB db.Students.find())
Item.find()
//if data is returned, send data as a response
.then(data => res.status(200).json(data))
//if error, send internal server error
.catch(err => {
console.log('Error: ${err}');
res.status(500).json(err);
});
});
But in the future, please just use an IDE of some sorts. Even just dumping your code into JSFiddle will highlight this for you.
i am new to node.js and want to create api for getting data and update that data on frontend,please give me solution for this,i am getting data from this code but unable to update data.I am using react js for frontend.
var express = require("express");
var app = express();
var oracledb = require('oracledb');
var dbconfig= require('./dbconfig')
(async function () {
let connection
try {
connection = await oracledb.getConnection({
user: 'dbconfig.user',
password: 'dbconfig.password',
connectString: 'dbconfig.connectstring'
});
var result = await connection.execute('select * from
PROPERTY.app_booklet_challan_detail', []);
console.log("Successfully connected to Oracle!")
console.log(result)
} catch (err) {
console.log("Error: ", err);
} finally {
if (connection) {
try {
await connection.close()
} catch (err) {
console.log("Error when executing the database connection: ", err);
}
}
}
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
next();
});
app.get('/list', (req, res, next) => {
res.send(result);
next()
});
app.put('/list/update', (req, res, next) => {
let STATUS=res.data
connection.execute('UPDATE PROPERTY.app_booklet_challan_detail SET STATUS= ? WHERE
BOOKLETID= ? ', [STATUS])
res.send(STATUS)
next()
})
app.listen(3001, function () {
console.log("Started on PORT 3001");
})
})()
Your question is a little broad to answer with code, but I've written an entire series on this topic: https://jsao.io/2018/03/creating-a-rest-api-with-node-js-and-oracle-database/
Note there are links to a GitHub repo with the code from each module.
Once you finish with the series you should be able to take things in the direction that makes the most sense for your project.
I'm using xml2js with node.js to retrieve data from an API, but I would only like the code to run when the "/testpage" route is activated, which would then assign the api response to a variable and pass it along to a script on testpage.ejs where the end goal is to print the object/variable contents to the console.
The problem I'm facing is that I'm getting the "undefined" browser console response with the above code.
If I place the code outside of the route, have the response assigned to a variable and then pass that variable to the testpage script, then it works fine.
At this point I'm assuming it could be an asynchronous issue, but I'm not sure, or even how to tackle it if so.
// Node.js
const requestPromise = require('request-promise'),
xml2js = require('xml2js').parseString,
express = require("express"),
app = express();
const port = 3200,
apiURL = 'https://api.exampleapi.com';
app.set("view engine", "ejs");
app.use('/public', express.static(__dirname + "/public"));
app.get("/testpage", function(req, res){
var myApiObject; // To store api response
requestPromise.post(apiURL, (error, response, body) => {
if(error){
console.log(error);
return error;
}
}).then( (body) => {
xml2js(body, (err, result) => {
if(err){
console.log(err);
} else {
myApiObject = result;
return result;
}
});
});
res.render("testpage", {myApiObject: myApiObject});
});
app.listen(process.env.PORT || port, function(){
console.log("Server is running...");
});
<!--testpage.ejs-->
<html>
<head>
<title>
</title>
</head>
<body>
<p>This is the testpage</p>
<script>
var myObj =<%-JSON.stringify(myApiObject)%>
console.log(myObj);
</script>
</body>
Any ideas on what I'm doing wrong?
You need to render your page after the response from API call is received. Change your code like this:
requestPromise.post(apiURL, (error, response, body) => {
if(error){
console.log(error);
return error;
}
}).then( (body) => {
xml2js(body, (err, result) => {
if(err){
console.log(err);
} else {
res.render("testpage", {myApiObject: result});
return result;
}
});
});