const express = require('express');
const app = express();
app.use('/', anyroute);
// in anyroute file
router.route('/:id').get(controlFunction)
controlFunction(req, res, res)=> {
// Here we can get the "id" from the variable with req.param.id
}
but I want to use the "id" before getting into this controller function. Like this
modifyFunction(userId)=> {
// Do something with the userId
}
router.route('/:id').get(modifyFunction(id), controlFunction)
Is it possible in express and javascript to retrieve the 'id' from url and use in modifyFunction(id) before getting into the request.
In an express middleware req and res variables are transferred from one middleware to next. But I created a function function(type, id) which returns a middleware function(req, res, next). in this function(type, id) type parameter will be passed manually and id from URL.
router
.route('/all-contacts/:id')
.get(authController.isLoggedIn, viewController.getAxiosConfig('contactNameEmail', id), viewController.getAllContact);
exports.getAxiosConfig = (type, id) => {
return (req, res, next) => {
const config = axiosConfig(type, id);
const accessToken = req.cookies.access_token;
const tokenArray = config.headers.Authorization.split(' ');
tokenArray.splice(1, 1, accessToken);
const newToken = tokenArray.join(' ');
config.headers.Authorization = newToken;
req.config = config;
next();
};
};
exports.getAllContact = catchAsync(async (req, res, next) => {
// const token = req.cookies.access_token;
// console.log(token);
// const config = axiosConfig('contactNameEmail');
req.config.method = 'GET';
// const tokenArray = config.headers.Authorization.split(' ');
// tokenArray.splice(1, 1, token);
// const newToken = tokenArray.join(' ');
// config.headers.Authorization = newToken;
const contacts = await axios(req.config);
console.log(req.config);
const { data } = contacts;
res.status(200).render('contactList', {
title: 'All contacts',
data
});
});
You can access the ID in the middleware, which is called before the route handler.
Related
I tried using Async-Await in NodeJs RESTful API but I seem to get an error I cannot resolve.
Here is my db.js:
const User = require('../models/User'),
user = {};
user.findUserByUsername = async function (username) => {
try {
const user = await User.findOne({username});
if (user)
return {data: user, status: 200};
return {message: `Cannot find user with username: ${username}`, status: 404};
} catch (err) {
return err;
}
};
module.exports = user;
And here is my api.js:
const express = require('express'),
router = express.Router(),
user = require('../db/db');
router.get('/user', async (req, res, next) => {
const user = await user.findUserByUsername(req.query.username);
// ^
// Cannot access 'user' before initialization
if (!user.status)
return next(user);
res.status(user.status);
res.doc = user.status === 404 ? user.message : user.data;
next();
});
module.exports = router;
When making a HTTP request, my server is crashing at that point. Where is my mistake?
You're mixing your variable names up. You have user as an import, but you also have user as a variable you're trying to assign to as a result of findUserByUsername.
Use different variable names, and follow the capitalization convention for this sort of database lookup:
const express = require('express'),
router = express.Router(),
User = require('../db/db');
router.get('/user', async (req, res, next) => {
const user = await User.findUserByUsername(req.query.username);
I am practicing my knowledge in Express.js .
I have one recipe router with the code below:
const express = require("express");
const router = express.Router();
const Recipe = require("../models/recipe.model");
const createRecipeItem = async recipeData => {
await Recipe.init();
const doc = Recipe(recipeData);
await doc.save();
};
router.post("/", async (req, res, next) => {
try {
await createRecipeItem(req.body);
} catch (err) {
next(err);
}
res.status(201).send(req.body);
});
module.exports = router;
I have another supply router, the code is below:
const express = require("express");
const router = express.Router();
const Supply = require("../models/supply.model");
const createSupplyItem = async supplyData => {
await Supply.init();
const doc = Supply(supplyData);
await doc.save();
};
const updateItem = async (name, itemData) => {
const result = await Supply.findOneAndUpdate({ name }, itemData, {
new: true
});
return result;
};
router.post("/", async (req, res, next) => {
try {
await createSupplyItem(req.body);
} catch (err) {
next(err);
}
const respObj = {};
respObj.name = req.body.name;
respObj.qty = req.body.qty;
res.status(201).send(respObj);
});
router.patch("/:name", async (req, res, next) => {
const updatedItem = await updateItem(req.params.name, req.body);
const response = {};
response.name = updatedItem.name;
response.qty = updatedItem.qty;
res.status(200).send(response);
});
module.exports = router;
I wrote tests for the two routers using supertest
Inside my app.js my code is written like this:
const supplyRouter = require("./routes/supply.route");
const recipeRouter = require("./routes/recipe.route");
app.use("/recipes", recipeRouter);
app.use("/supplies", supplyRouter);
when the code is written like this:
app.use("/recipes", recipeRouter);
app.use("/supplies", supplyRouter);
All my test passed. However, when I change the order of when I call app.use() the test would fail.
app.use("/supplies", supplyRouter);
app.use("/recipes", recipeRouter);
The test would fail with the error Cannot set headers after they are sent to the client for the POST /supplies method. I have no clear understanding why this happens. Appreciate any insight. Thank you!
I cannot pass my test correctly because I didn't have proper understanding of the flow of the code.
router.post("/", async (req, res, next) => {
try {
await createSupplyItem(req.body);
} catch (err) {
next(err);
}
const respObj = {};
respObj.name = req.body.name;
respObj.qty = req.body.qty;
res.status(201).send(respObj);
});
For the above code, when there is an error, express will run two paths of the code namely the path inside the catch block and the last line of the code
res.status(201).send(respObj);
Because it is trying to run two paths, I received the error Cannot set headers after they are sent to the client.
The correct code is written below.
router.post("/", async (req, res, next) => {
try {
await createSupplyItem(req.body);
const respObj = {};
respObj.name = req.body.name;
respObj.qty = req.body.qty;
res.status(201).send(respObj);
} catch (err) {
if (err.name === "ValidationError") {
err.statusCode = 400;
} else if (err.name === "MongoError") {
err.statusCode = 400;
}
next(err);
}
});
I'm trying to access the body of the request in a middleware in order to perform it only if a specific field has changed (ereasing pictures only if new pictures got uploaded), but I'm not able to access the body.
I've tried to install and configure cors as well as reconfiguring body-parser in the route-specific file, as well as shuffling around the code, but nothing has helped (this is what was suggested in other questions).
const express = require('express');
const router = express.Router();
const bodyParser = require('body-parser');
const multer = require('multer');
const glob = require('glob');
const fs = require('fs');
const _ = require('lodash');
const urlencodedParser = bodyParser.urlencoded({ extended: false });
//MIDDLEWARE
router.use("/immobili/:_id/edit", urlencodedParser, function (req, res, next) {
console.log(req.body);
const requestedId = req.params._id;
Immobile.findOne({ _id: requestedId }, (err, immobile) => {
if (err) return console.error(err);
immobile.immagini = [];
cancellaFoto(immobile);
if (this.cancellato) {
return setTimeout(next, 1000);
} else {
return console.log("Aborted");
}
});
});
//EDIT PUT ROUTE
router.put("/immobili/:_id/edit", upload.array('immaginePrincipale', 30), function (req, res) {
const requestedId = req.params._id;
const dati = req.body;
const proprietaImmagini = req.files;
const immagini = proprietaImmagini.map(function (immagine) {
//console.log(immagine.path);
return immagine.path;
});
let vetrina;
req.body.vetrina === 'on' ? vetrina = true : vetrina = false;
Immobile.findOneAndUpdate({ _id: requestedId }, {
numeroScheda: dati.numeroScheda,
//[... ALL DATA ... ]
immagini: immagini,
}, function (err, updatedImmobile) {
if (err) return console.error(err);
res.redirect("/immobili/" + req.body.categoria + "/" + _.toLower(req.body.localita) + "/" + requestedId);
});
});
This is the form I'm using to send the data:
<form action="/immobili/<%= immobile._id %>/edit?_method=PUT" method="POST"
enctype="multipart/form-data">
//[ ... FORM INPUTS ... ]
<input type="file" name="immaginePrincipale" multiple="multiple" id="immaginePrincipale"></input>
<input type="submit" value="Pubblica">
</form>
I would expect to access the body of the request in the middleware but I get only an empty object in return.
For example I have this URL: http://localhost/chat.html?channel=talk
How can I get the value of parameter channel in Node.js?
I want to store the value of channel in a variable.
I changed server.get to this:
server.get("/channel", (req, res) => {
let query = url.parse(req.url, true).query;
console.log(req.query.channel);
let rueckgabe = {
channel: req.query.channel
};
res.send(JSON.stringify(rueckgabe));
});
Now I'm expecting an output of the value of channel on my console but nothing appears.
This is the full code of index.js:
//Server erstellen
const express = require("express");
let server = express();
server.use(express.static("public"));
//Socket.io
const http = require("http");
let httpServer = http.Server(server);
const socketIo = require("socket.io");
let io = socketIo(httpServer);
//Eventlistener bei Verbindungsaufbau
io.on("connection", (socket) => {
console.log(socket.id);
socket.on("chatnachricht", eingabe => {
io.emit("nachricht", eingabe);
});
});
let stdIn = process.openStdin();
stdIn.addListener("data", (eingabe) => {
io.emit("nachricht", eingabe.toString());
});
server.get("/channel", (req, res) => {
let query = url.parse(req.url, true).query;
console.log(query);
let rueckgabe = {
channel: query.channel
};
//res.send(JSON.stringify(rueckgabe));
res.send(JSON.stringify(rueckgabe));
});
httpServer.listen(80, () => {
console.log("Server läuft");
});
SOLUTION
This code works so far but with limitations:
//Server erstellen
const express = require("express");
let server = express();
server.use(express.static("public"));
const http = require("http");
let httpServer = http.Server(server);
const socketIo = require("socket.io");
let io = socketIo(httpServer);
var router = express.Router();
const url = require("url");
var path = require('path');
//Eventlistener bei Verbindungsaufbau
io.on("connection", (socket) => {
console.log(socket.id);
socket.on("chatnachricht", eingabe => {
io.emit("nachricht", eingabe);
});
});
/*
let stdIn = process.openStdin();
stdIn.addListener("data", (eingabe) => {
io.emit("nachricht", eingabe.toString());
});
*/
server.get("/chat", (req, res) => {
let query = url.parse(req.url, true).query;
console.log(query.channel);
let rueckgabe = {
channel: query.channel
};
res.sendFile('chat.html', { root: path.join(__dirname, 'public/') });
//res.send(JSON.stringify(rueckgabe));
});
httpServer.listen(80, () => {
console.log("Server läuft");
});
Now it works with server.get() but I can't use both res.sendFile('chat.html', { root: path.join(__dirname, 'public/') }); and res.send(JSON.stringify(rueckgabe));. How can I use both?
It looks like you're using the Express framework for Node.
From the docs, query string params may be accessed via req.query:
server.get("/channel", (req, res) => {
let id = req.query.id; // where "id" is a paramter on the query string
}
And if you need the full URL of the request:
server.get("/channel", (req, res) => {
let fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
}
Well you mentioned for this url http://localhost/chat.html?channel=talk you're not seeing the channel parameter in the server. That's because you aren't hitting the endpoint that you've defined.
Copy of your code from above
server.get("/channel", (req, res) => {
let query = url.parse(req.url, true).query;
console.log(req.query.channel);
let rueckgabe = {
channel: req.query.channel
};
res.send(JSON.stringify(rueckgabe));
});
You're setting the /channel url here. With this configuration if you want to get the query parameter you need to call http://localhost:{portnumber}/channel?channel=somerandomvalue
If you want to have the /chat url change your configuration like this:
server.get("/chat", (req, res) => {
let query = url.parse(req.url, true).query;
console.log(req.query.channel);
let rueckgabe = {
channel: req.query.channel
};
res.send(JSON.stringify(rueckgabe));
});
and call into http://localhost:{portnumber}/chat?channel=somerandomvalue
If you want to serve a static html while using the url name as the same file name you can do something like this:
var router = express.Router();
var path = require('path');
router.get('/chat', function(req, res) {
// where chat.html is in the public directory
console.log(req.query.channel);
res.sendFile('chat.html', { root: path.join(__dirname, '../public/') });
});
I want to write my test classes for server app. I need to refactor my routers to controller arch.
I return functions on controller's return value. But on my router I see Error. Do you have any idea? Which point am I passing?
Controller:
const express = require('express');
const controller = (Project) => {
const projectMidlleware = require('../middleware/v1/projectMiddleware')(Project)
const put = (req, res, next) => {
projectMidlleware.create(req.query.name, (project) => {
res.status(200).send(project.api_key);
next();
});
}
const findProject = (req, res, next) => {
const apikey = req.headers["s-apikey"] || req.query.apikey || req.body.apikey;
projectMidlleware.findByApikey(apikey, (err, project) => {
if (err) {
next({
message: err.message,
code: 500
});
return;
}
req.body.project = project;
next();
});
}
return {
put,
findProject
}
}
module.exports = controller;
Router:
const express = require("express");
const router = express.Router();
const projectController = require('../../controllers/projectController');
const profileController = require('../../controllers/profileController');
//return profiles for project
router.get("/",
projectController.findProject(),
profileController.get()
);
module.exports = router;
const projectController = require('../../controllers/projectController')();
You have a function that returns an object with methods but you don't call the function and the methods exist on the returned object, not the function itself. This pattern is fairly common in node but I would actually do this for clarity:
const projectController = require('../../controllers/projectController');
const controller = projectController();
and then use that.