I am fairly new to the express framework. I couldn't find the documentation for application.post() method in the express API reference. Can someone provide a few examples of all the possible parameters I can put in the function? I've read a couple sites with the following example, what does the first parameter mean?
I know the second parameter is the callback function, but what exactly do we put in the first parameter?
app.post('/', function(req, res){
Also, let's say we want the users to post(send data to our server) ID numbers with a certain format([{id:134123, url:www.qwer.com},{id:131211,url:www.asdf.com}]). We then want to extract the ID's and retrieves the data with those ID's from somewhere in our server. How would we write the app.post method that allows us to manipulate the input of an array of objects, so that we only use those object's ID(key) to retrieve the necessary info regardless of other keys in the objects. Given the description of the task, do we have to use app.get() method? If so, how would we write the app.get() function?
Thanks a lot for your inputs.
1. app.get('/', function(req, res){
This is telling express to listen for requests to / and run the function when it sees one.
The first argument is a pattern to match. Sometimes a literal URL fragment like '/' or '/privacy', you can also do substitutions as shown below. You can also match regexes if necessary as described here.
All the internal parts of Express follow the function(req, res, next) pattern. An incoming request starts at the top of the middleware chain (e.g. bodyParser) and gets passed along until something sends a response, or express gets to the end of the chain and 404's.
You usually put your app.router at the bottom of the chain. Once Express gets there it starts matching the request against all the app.get('path'..., app.post('path'... etc, in the order which they were set up.
Variable substitution:
// this would match:
// /questions/18087696/express-framework-app-post-and-app-get
app.get('/questions/:id/:slug', function(req, res, next){
db.fetch(req.params.id, function(err, question){
console.log('Fetched question: '+req.params.slug');
res.locals.question = question;
res.render('question-view');
});
});
next():
If you defined your handling functions as function(req, res, next){} you can call next() to yield, passing the request back into the middleware chain. You might do this for e.g. a catchall route:
app.all('*', function(req, res, next){
if(req.secure !== true) {
res.redirect('https://'+req.host+req.originalUrl);
} else {
next();
};
});
Again, order matters, you'll have to put this above the other routing functions if you want it to run before those.
I haven't POSTed json before but #PeterLyon's solution looks fine to me for that.
TJ annoyingly documents this as app.VERB(path, [callback...], callback in the express docs, so search the express docs for that. I'm not going to copy/paste them here. It's his unfriendly way of saying that app.get, app.post, app.put, etc all have the same function signature, and there are one of these methods for each supported method from HTTP.
To get your posted JSON data, use the bodyParser middleware:
app.post('/yourPath', express.bodyParser(), function (req, res) {
//req.body is your array of objects now:
// [{id:134123, url:'www.qwer.com'},{id:131211,url:'www.asdf.com'}]
});
Related
I'm trying to wrap my head around my implementation of express.router() not triggering of the middleware function assigned to it.
I wrote a pretty big app and trying to add a few more endpoints to my path, but for some reason the 9th route gets loaded but does not trigger the function.
app.js
server.use(cors());
server.use(function (req, res, next) {
next();
});
server.use("/", express.static("./assets"));
server.use("/api", api);
server.use("/debug", debug);
server.use("/config", config);
server.use("/control", control);
server.use("/tools", files);
And this is where I declared my routes with the respective functions.
router.get("/teams", onGetTeams);
router.get("/players", onGetPlayers);
router.get("/achievements", getTop3);
router.get("/xpression", onXprPayload);
router.get("/snapshot", onRequestSnapshot);
router.get("/round-timeline", onRequestTimelinePayload);
router.get("/:half", onRequestHalf);
router.get("/dashboard-message", onSetDashboardMessage);
router.get("/get-match-odds", getTeamOdds);
function getTeamOdds(req, res) {
console.log("Sent odds");
res.json(odds);
res.end();
}
When I make the request for the last route, the function does not get executed, and I get back a 200 response.
Is there something big I'm missing?
Thank you !
Your route definition here:
router.get("/:half", onRequestHalf);
is a wildcard route that matches ALL routes so none of the routes after it will get called unless that specific route calls next() to continue routing.
Top level wildcard routes are problematic for this reason. I would suggest avoiding them. There are temporary work-arounds like moving their definition to be the last top level route definition, but they can still be limiting for defining future routes because they are so greedy.
My recommendation would be to not make it a top level route:
router.get("/half/:half", onRequestHalf);
So, it won't conflict with the other top level routes and it essentially has it's own URL scope all to itself.
I'm trying to wrap my head around my implementation of express.router() not triggering of the middleware function assigned to it.
I wrote a pretty big app and trying to add a few more endpoints to my path, but for some reason the 9th route gets loaded but does not trigger the function.
app.js
server.use(cors());
server.use(function (req, res, next) {
next();
});
server.use("/", express.static("./assets"));
server.use("/api", api);
server.use("/debug", debug);
server.use("/config", config);
server.use("/control", control);
server.use("/tools", files);
And this is where I declared my routes with the respective functions.
router.get("/teams", onGetTeams);
router.get("/players", onGetPlayers);
router.get("/achievements", getTop3);
router.get("/xpression", onXprPayload);
router.get("/snapshot", onRequestSnapshot);
router.get("/round-timeline", onRequestTimelinePayload);
router.get("/:half", onRequestHalf);
router.get("/dashboard-message", onSetDashboardMessage);
router.get("/get-match-odds", getTeamOdds);
function getTeamOdds(req, res) {
console.log("Sent odds");
res.json(odds);
res.end();
}
When I make the request for the last route, the function does not get executed, and I get back a 200 response.
Is there something big I'm missing?
Thank you !
Your route definition here:
router.get("/:half", onRequestHalf);
is a wildcard route that matches ALL routes so none of the routes after it will get called unless that specific route calls next() to continue routing.
Top level wildcard routes are problematic for this reason. I would suggest avoiding them. There are temporary work-arounds like moving their definition to be the last top level route definition, but they can still be limiting for defining future routes because they are so greedy.
My recommendation would be to not make it a top level route:
router.get("/half/:half", onRequestHalf);
So, it won't conflict with the other top level routes and it essentially has it's own URL scope all to itself.
I am new to node and express, trying to explore things. I made two middlewares both with their specified mount path, the MIDDLEWARE 2 is getting called even when the request is not for it.
The code written by me:
// middleware 1
app.use('/demo',function(req, res, next){
console.log("MIDDLEWARE 1 CALLED");
next();
});
// middleware 2
app.use('/', function(req, res, next){
console.log("MIDDLEWARE 2 CALLED");
next();
});
app.get('/demo',function(req, res){
console.log("Hello, How are you?");
});
And now in the browser, I type: localhost:8000/demo
In console I am getting this:
MIDDLEWARE 1 CALLED
MIDDLEWARE 2 CALLED
Hello, How are you?
My question is when I specify the path in request as /demo why does the second middleware gets called?However, when I type this: localhost:8000, it works as expected Only middleware 2 is called.
Where am I wrong in the first case?
Thanks in advance for any help you are able to provide.
Express' app.use will apply to every request with a path that starts with your entered path. Meaning app.use('/demo', ...) will apply to every route that starts with /demo, and app.use('/', ...) will apply to every route that starts with /, which obviously is every route.
If you only want to have it on the exact / path, maybe app.all('/', ...) could solve your issue as it only applies to the exact match but still for all HTTP methods.
I am new to Express and Mongoose. I am currently working on my first project, that is not a tutorial, and I has run into a problem.
I have multiple routes, they are defined in the index.js like this:
app.use('/api/client',require('./routes/client'));
app.use('/api/host',require('./routes/host'));
In the routes, there are multiple verbs that work, like PUT and POST.
Here is the problematic route (I am trying to do more that what is presented here, but what is presented here, does not work as well):
router.get('/ama/:id', function (req, res, next) {
Ama.findById(req.params.id).then(function(Ama){
res.send(Ama);
});
});
This should work, right? It should return the document in the database, with that id. And I have checked if the document excists, probably around a 100 times.
Now, if I simplify the route greatly, removing the id, and make a simple response, the route works:
router.get('/ama', function (req, res, next) {
res.send({type:"GET"});
});
It's so wierd, that as soon as i add the parameter, i get a:
<pre>Cannot GET /api/host/ama</pre>
in Postman.
Any ideas? Mongod is running, my other routes are working.
It looks like you're trying to retrieve this URL:
/api/host/ama?id=SOMEID
However, you have a route declared for URL's that look like this:
/api/host/ama/SOMEID
In other words, the id is part of the path of the URL, and not passed as a query string parameter (that's what /:id means: it's a placeholder for a part of the URL that the route should match).
So either change the request-URL by adding the id to the path (/api/host/ama/58e395a8c6aaca2560089ce7), or rewrite your route handler to something like this:
router.get('/ama', function (req, res, next) {
Ama.findById(req.query.id).then(function(Ama){
res.send(Ama);
});
});
However, I would advise using the former (making the id part of the URL).
There are two problems here:
router.get('/ama/:id', function (req, res, next) {
Ama.findById(req.params.id).then(function(Ama){
res.send(Ama);
})
res.send(req.params.id)*/
});
First of all, res.send(req.params.id) will run before the res.send(Ama); and it will probably send the entire response. You are missing the .exec() method call (see the answer by Cédric De Dycker for details). The res.send() can only be reliably used once. Maybe you want res.write() instead if you want to wrte multiple things. Also you don't handle the promise rejection so you don't handle database errors. To know why you should always handle the promise rejections see this answer: Should I refrain from handling Promise rejection asynchronously?
The parameter should work fine but it seems you missed to add .exec to your query
Ama.findById(req.params.id).exec().then(function(Ama){
res.send(Ama);
})
Currently working on a nodejs express server. And I think I'm doing something in an inefficient way. I have this route set up
app.get('/admin/scanTable/:table', require('./AUTH/ValidateCookie.js'), require('./AUTH/verifyURI.js'), require('./ROUTES/render.js'));
so the url here is /admin/scanTable/:table. I know I can get the whole path with req.route.path. I know I can use req.params.table to collect the table parameter. But the thing I don't know how to get is the first part of the path, in this case admin. I know I could get it by looking for / symbols and slicing the parts I need from req.route.path but I figure with all these functionalities that express has, there's probably a better way of doing this.
I know I can use
app.use('/admin', function(req, res, next){console.log('admin called'), next();});
to check if this part of the uri was called to then execute some code, but it's not really what I want. Can anyone tell me the easiest way to find this? At the moment I have attached a variable to req.string whenever app.use('/admin' is called it will attach the string admin to this variable which then makes it available to all other functions that are called. But even this feels like overkill. Any Ideas?
Both options you describe are valid and straightforward:
Using a regex on req.route.path, a la /^admin/.test(req.route.path)
Using middleware to attach a new property to the req object, a la
app.use('/admin', function(req, res, next){ req.adminRoute = true; next();});
or if you need to do this same thing for all admin routes, do it once:
var adminRouter = require("express").Router();
router.get("/scanTable/:table", require("./AUTH/ValidateCookie.js"), ...);
router.use(function (req, res, next) { req.adminRoute = true; next(); }));
app.use("/admin", adminRouter);
I don't know the context of your application, but I would consider using the last example, and putting anything else that's specific to /admin routes as middleware also.