Express middleware not having an effect - javascript

I have the following code:
var express = require('express');
var app = express();
app.use(express.bodyParser());
app.use(express.cookieParser());
var port = Number(process.env.PORT || 5000);
app.get('/test/:id', function(req, res) {
res.send(req.params);
});
app.listen(port);
console.log("Listening on port " + port);
When I hit http://localhost:5000/test/12345 in my browser, I see:
[]
But I'm expecting to see the populated req.params object with id: 12345. Any idea what I'm doing wrong?
Thanks.

Checked and saw that req.params is actually an associative array, which is almost similar to object but not quite. Not sure why express defined it as such. The only benefit it gets is the added length property for an array. And res.send will try to JSON.stringify your output, which in turn will see that it's an array and only take care of indexes which are numeric. Hence the empty [] as return value.
You can validate this by doing -
var myParams = {};
Object.keys(req.params).forEach(function(key){
myParams[key] = req.params[key];
});
res.send(myParams);
You can also see that JSON.stringify only cares about numeric index by defining your route as such -
app.get('/test/:0', function(req, res) {
res.send(req.params);
});

The response object will be named after your id. If you check it in your browser's traffic you can see a file called 12345. Though you can check that your server gets the id by logging it on the server side.
app.get('/test/:id', function(req, res) {
console.log(req.params);
res.send(req.params);
});
If you want to pass variables to a view you might want to use the res.render(...) function where you can pass in arguments.
To get the 123451 send the res.send(req.params.id);.

The reason why you are not getting anything using res.send(req.params) is because req.params is an instance of Array and default mechanism tries to covet an array into string which is giving you [].
What you could do to see all params is as follows:
app.get('/test/:id', function(req, res) {
res.send(require('util').inspect(req.params));
});
That will give you output like (using this URL http://localhost:5000/test/12345):
[ id: '12345' ]
That approach will also work with routes having more parameters e.g. the following code snippet and that request http://localhost:5000/test/name/234
app.get('/test/:name/:id', function(req, res) {
res.send(require('util').inspect(req.params));
});
will give you:
[ name: 'name', id: '234' ]
Alternatively, if you would like to get JSON formatted output of a JavaScript object, you can use res.json. But note that json will also generate [] if you perform res.json(req.params) as it will render req.params array in a standard way.
I hope that will help.
Note that as of 9th April 2014 (Express version 4.0.0) req.params is an object instead of an array so you should not have similar issues with v4.0.0 and your code should work as expected.
app.get('/test/:id', function(req, res) {
res.send(req.params);
});

The problem isn't your middleware. Neither bodyParser nor cookieParser provide the named url parameter parsing. That being said, your code looks correct to me. Are you absolutely certain you restarted your node server after making the code change?

Related

GET request with parameter dosn't hiting desired route NODE js

The Problem occurs while sending GET or any request with parameters in the URL.
for example my
index.js
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/:name", function (req, res) {
let name = req.params.name;
console.log("Hello " + name + " from /:name");
res.send("Hello " + name + " from /:name");
});
app.get("/", function (req, res) {
console.log("Hello world from /");
res.send("Hello world from /");
});
app.listen(3000, () => {
console.log("Server is running on port " + 3000)
});
For http://localhost:3000/ it's working perfectly fine.
the Problem is occurring when we try to hit /:name route
when we use URL http://localhost:3000/?name=NODE it is going to the same route as above. in /
But the crazy part is when we put http://localhost:3000/NODE which is simply a new different route that is not implemented.
It is getting the response from :/name which doesn't make any sense.
is it a BUG or I am doing something wrong or is it something new I am not aware of?
I am currently using Windows11,
this problem also occurs in my friend's PC who uses Ubuntu
When you define route as
/:name
That's called path parameter and it's used like this :
GET /yourname
And that's why this works :
GET /NODE
What you"re using to call the endpoint (?name=xxx) is called query parameter, you can get that name from '/' endpoint like this :
let name = req.query.name;
I think you're almost there, but /:name does not match /?name=, but it does match /NODE.
This is exactly what's expected to happen. If this surprised you, go re-read the documentation because it should be pretty clear on this.
I think I am confused between query parameters and params.
Let:
given this URL http://www.localhost:3000/NODE?a=Debasish&b=Biswas
We will have:
req.query
{
a: 'Debasish',
b: 'Biswas'
}
req.params
{
param1: 'NODE'
}
Here I am sending a query but want to receive params. That is where I go wrong.
For better understanding check :
Node.js: Difference between req.query[] and req.params

Request to API based on URL/

I'm attempting to make a request to an API to get a users' avatar. This is the code I have, however it's returning a "player is not defined" error.
app.get(`/api/avatar/${player}`, function(req, res) {
res.redirect(`http://cdn.simulping.com/v1/users/${player}/avatar`);
});
Essentially, if the URL is /api/avatar/3925 it would send them to http://cdn.simulping.com/v1/users/3925/avatar.
Assuming you're using Express.JS for the routing, the correct way for doing that is:
app.get('/api/avatar/:id', function(req, res) {
res.redirect(`http://cdn.simulping.com/v1/users/${req.params.id}/avatar`);
})
Assuming you are using Express routing, then you would need to utilise route parameters.
The Express documentation provides:
Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the req.params object, with the name of the route parameter specified in the path as their respective keys.
In this case:
Route path: /api/avatar/:player
Request URL: http://localhost:3000/api/avatar/3925
req.params: { "player": "3925" }
The working code:
app.get('/api/avatar/:player', function(req, res) {
res.redirect(`http://cdn.simulping.com/v1/users/${req.params.player}/avatar`);
});
You can read more about it in the Route Parameters section of the Express Routing Guide.

Object prototype not working in Node.JS

I have a bit of an issue when i try to create an object prototype in my node/express app.
I first start by creating the prototype like so:
Object.prototype.printObject = function () {
return console.log(this);
}
Now the issue is when I call this function. For instance when i call the function like this:
let request = {1:2}
request.printObject();
*//Logs {1:2}*
No error occurs. Yet when I call the function like this:
let request = req.body
request.printObject();
My program crashes with error: TypeError: request.printObject is not a function
Does anyone have any clue as to why this occurs?
if you require('body-parser')? or req.body is undefined,you should do this first
var bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
You have added the 'printObject' method on the prototype of Object. So if req.body is an Object, you should be able to call the method.
Try checking the type of req.body using console.log(typeof req.body) to verify that it is an Object.
If it is not, you should use the node module 'body-parser' to populate req.body with the parsed body content.
For example, parts of your server code might look like this:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json()); // Data is being sent to the server in JSON format
app.post('/my/endpoint', function(req, res){
req.body.printObject();
});
The 'body-parser' module supports other formats as well. I used JSON as an example. You can find everything they support here: https://www.npmjs.com/package/body-parser
Insteat of trying to prototype any Object, you could create a middleware function like so:
app.use(function (req, res, next) {
console.log('req');
//you could also add any function to req,even so thats not a common thing to do
req.printObject = function { ... }
next();
});
Probably the problem with your approach is, that you add the function to the Object prototype after the request object was created.(EDIT: This is wrong, see comments)

Is this the right behavior to expect from the new Express 4 Router?

I have recently started a new app with Express 4.0, and I really liked the new express.Router() thing.
Something that got me stuck for quite some time was the following behavior:
var app = require('express')(),
router = express.Router();
router.get('/me', function(req, res, next) {
if(someBoolean) {
return next(); //here I expect to get a 404 error from express!
}
res.json({name: 'yourName'});
});
router.get('/:user_id', function() {
//any code here!
});
app.use('/users', router);
I always used next() (in Express 3.x) to either call the next middleware or to force a 404 from the server.
Since /users/me and /users/45 are totally different routes and are not mounted in a way that one should come after another, I wonder why I get code in /users/:user_id evaluated after calling next() in /users/me.
Am I doing something wrong or things are supposed to work different in Express 4.0?
This is working as expected. In Express 4 all middleware/routes are executed in the order that they are added to your app, so the path for your second router.get() is tested and matches because :user_id could be any kind of token, numeric or otherwise (basically any character that isn't /).
You can fix this at least in a couple of different ways:
Don't call next() in your first router.get()
Use a RegExp instead of a string to ensure that user_id only matches a numeric value. For example: router.get(/^\/(\d+)$/, function() {. However then you have to access the param via regexp group index instead of by a name: var user_id = req.params[0].

Process.domain undefined in Node 0.10

I'm getting around to using domains and am trying a couple of Express domain middleware packages:
https://github.com/brianc/node-domain-middleware
https://github.com/baryshev/connect-domain
According to the usage docs on the first one I should have access to process.domain but it is undefined.
I am basically doing this in my app.js
var express = require('express'),
domains = require('express-domain-middleware');
var app = exports.app = express();
app.use(domains);
And in a controller:
exports.index = function(req, res, next) {
console.log(process.domain); //undefined
};
What gives?
You might want to check (using console.log or breakpoints) to make sure this line is happening before your index method is getting called:
express.use(domain);
I don't know how your app is structured but order of app.use is usually the case.
Your app.get('/someurl', yourcontroller.index) should come after app.use(domain).
Ok - it's due to a Mongo call in my middleware. Evidently all database calls have to be wrapped.
var d = domain.create();
d.run(function () {
client.query('...', d.intercept(function (rows) {
// ... use rows (note, first arguments error was "intercepted" by the domain)
}));
});
Reference: https://github.com/felixge/node-mysql/issues/308

Categories

Resources