Node.Js express it always redircts to root - node.js

Untill yester day, It works very well. however, at this morning I run this project by using npm start, It doesn't work.
The code is below:
router.get('/manage', (req, res) => {
if (res.data.manager != 1) { res.redirect('/'); return; }
res.db.getTeamUrlPairs((teams) => {
res.render("manageTeam", {
teams: teams ,
data: res.data
})
})
})
When I connect to /manage, it just redirect to '/' although res.data.manager was 1.
So, I tried to change the circumstance such as routing url, inner code.
But, I changed it to:
router.get('/manage', (req, res) => {
res.send('hello');
})
It doesn't work. I mean, the change not reflected. I've restarted my computer, close my vscode, stop and re-run npm. it always just redirect to root.
What can I do for this?
Ps. Other routings are working well... what the hell is going on.

Note the differences between app.get() and app.use() methods:
app.get(<registered_path>, <middleware>) is triggered only on GET requests that have an exact match to the registered_path.
app.use(<registered_path>, <middleware>) is triggered for all HTTP methods (POST, GET, PUT, PATCH, and DELETE) where the URL path of the request start with the registered_path.
The order in which you specify your middleware's is important.
If we registered the following middlewares:
app.use('/', <middleware1>)
and
app.get('/manage', <middleware2>)
The request to /manage will never trigger middleware2 (unless you called the next() function in middleware1).
Also, consider using breakpoints in each of your middleware's to see what middleware is actually triggered when you send an HTTP request to /manage.

Routing order is important.
router.get('/:a',(req,res)=>{})
router.get('/manage', (req,res)=>{})
This code won't work well. specifically manage doesn't work.
However, below:
router.get('/manage', (req,res)=>{})
router.get('/:a',(req,res)=>{})
does work well.

Related

How can I share a root path using Express?

I want to be able to have two endpoints sharing the root path, both for different purposes.
One will be for obtain a user via its ID and the other via token.
Right now I have the following routes:
router.get('/:idUser', paramValidationRules(), validate, verifyJWT, getUserFromId);
router.route('/me').get(verifyJWT, getUserFromToken);
Running tests, the 'me' on the second route is considered a parameter and its redirected to the first route. Is possible to share a root path specifying that one will be used strictly to 'me' and the other one to an integer?
First, you're always hitting /:idUser before /me, so it will always stop at /:iduser and never react me.
So to solve the issue that you can never access /me, put the /me route declaration before /:idUser.
As to only catching numbers, there isn't a built in way, but you could use middleware (and change the order of your routes to the original):
router.get('/:idUser', function(req, res, next) {
req.id = /^\d+$/.test(req.params.idUser);
next();
}, paramValidationRules(), validate, verifyJWT, getUserFromId);
Then, (unfortunately) in all your middleware and handler (or just the handler) in the opening of the function add:
if(!req.id)
return next();

Find unused routes or codes in an express app to remove dead code

I have a 4 year old Express project running in production and using Express 4.14. Various developers have kept on adding new features but some old code also remains inside. Is there a way to find unused code- code which is not getting used in a production application ?.
I would like to start by identifying routes that are not being called. We do use logs and logs are ingested in Kibana. We also use APM with Kibana.
Since you log data you can create simple middleware to log every request to your application. After a while (days or weeks, depending on how sure you will feel about this process) you can collect and parse logs to get all requested routes. Then compare requested routes with all routes available in your application and delete unused ones.
The middleware can be as simple as:
// runs for every request
app.use('/', function (req, res, next) {
console.log(`Received request: ${req.method} ${req.path}`);
next();
});
To get all routes registered in your application use this development-only code (inspired by this answer):
console.log(app._router.stack.forEach(middleware => {
if (middleware.route) {
console.log(`${middleware.route.stack[0].method} ${middleware.route.path}`);
} else if (middleware.name === 'router') {
middleware.handle.stack.forEach(route => {
if (route.route) {
console.log(`${route.route.stack[0].method} ${route.route.path}`);
}
});
}
}));

Change response cookies with node-http-proxy?

So, I am proxying my API requests through a node-http-proxy for several reasons.
The external API has a different origin than the actual client, so cookies are not being set correctly. The proxy obviously runs at the same origin, so I want to receive the response from the API, and inside the proxy, change the cookie value to reflect the proper origin.
Here's my current setup:
// Proxy to API server
app.use('/api', (req, res) => {
proxy.web(req, res, { target: targetUrl })
})
proxy.on('proxyRes', function (proxyRes, req, res) {
console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2))
console.log('The original request', req.headers.host)
})
Basically, I need to modify the cookie to req.headers.host, as this is the correct origin.
I've seen Harmon, but this looks very involved and changes how you instantiate your entire app, if I understand correctly.
Is there a way to simply modify the proxyRes after receiving it, in a synchronous fashion?
It seems very strange that there is a proxyReq event that allows you to alter the proxy request before it's sent, but not an equivalent that allows you to alter the response...
For anyone facing the same issue, I found a solution. They just merged a PR a few days ago that hasn't made it into a new release yet.
This PR introduces a new option called cookieDomainRewrite that does exactly what it sounds like. Simply include this in your config and it's all taken care of.

Express wont match url to route when coming from remote server

I'm setting up a site that posts to a remote server. The user performs some steps on this remote server and when the user is done. The server issues a get request with a bunch of query parameters to my server.
The thing is that this request never arrives at the controller method it is supposed to.
I have a custom middleware that intercepts all requests and i am doing some logging in there, i can see there every time this request arrives to my server but express doesn't seem to match it to the controller.
However if i go into my browser and do the request from there with the exact same path and query string it works fine.
I thought maybe the remote server was using a proxy so i enabled trust proxy in express but that didn't make any difference.
I have tried changing the route path and that didn't make a difference.
I don't know what code would be helpful since it is pretty standard express code. I have tried putting the route before all the middleware and the request still bypassed the controller and was logged by my logging middleware.
I'm completely baffled, anyone got any idea what could be causing this?
EDIT:
Here is some of the code I'm using. This is not the exact setup I'm trying but I have tried to make it work this way to rule out my routing logic and this example has the exact same problem. I tried putting the app.get above the middleware and the request from the external server still bypassed the app.get and went directly to the middleware.
app.use(function(req, res, next) {
console.log('path', req.method, req.path, req.query);
});
app.get('/payments/success', function (req, res) {
console.log('SUCCESS', req.query);
res.status(200).send();
});
Here is the result of the middleware logging a request arriving from the remote server(i removed the variables logged from the request query because it is sensitive information, they are returned just the way they are supposed to):
path GET /payment/success {
variable: 'variable",
}
If anyone needs any more information from the request object i will provide it.

Express request is called twice

To learn node.js I'm creating a small app that get some rss feeds stored in mongoDB, process them and create a single feed (ordered by date) from these ones.
It parses a list of ~50 rss feeds, with ~1000 blog items, so it's quite long to parse the whole, so I put the following req.connection.setTimeout(60*1000); to get a long enough time out to fetch and parse all the feeds.
Everything runs quite fine, but the request is called twice. (I checked with wireshark, I don't think it's about favicon here).
I really don't get it.
You can test yourself here : http://mighty-springs-9162.herokuapp.com/feed/mde/20 (it should create a rss feed with the last 20 articles about "mde").
The code is here: https://github.com/xseignard/rss-unify
And if we focus on the interesting bits :
I have a route defined like this : app.get('/feed/:name/:size?', topics.getFeed);
And the topics.getFeed is like this :
function getFeed(req, res) {
// 1 minute timeout to get enough time for the request to be processed
req.connection.setTimeout(60*1000);
var name = req.params.name;
var callback = function(err, topic) {
// if the topic has been found
if (topic) {
// aggregate the corresponding feeds
rssAggregator.aggregate(topic, function(err, rssFeed) {
if (err) {
res.status(500).send({error: 'Error while creating feed'});
}
else {
res.send(rssFeed);
}
},
req);
}
else {
res.status(404).send({error: 'Topic not found'});
}};
// look for the topic in the db
findTopicByName(name, callback);
}
So nothing fancy, but still, this getFeed function is called twice.
What's wrong there? Any idea?
This annoyed me for a long time. It's most likely the Firebug extension which is sending a duplicate of each GET request in the background. Try turning off Firebug to make sure that's not the issue.
I faced the same issue while using Google Cloud Functions Framework (which uses express to handle requests) on my local machine. Each fetch request (in browser console and within web page) made resulted in two requests to the server. The issue was related to CORS (because I was using different ports), Chrome made a OPTIONS method call before the actual call. Since OPTIONS method was not necessary in my code, I used an if-statement to return an empty response.
if(req.method == "OPTIONS"){
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-Headers', 'Content-Type');
res.status(204).send('');
}
Spent nearly 3hrs banging my head. Thanks to user105279's answer for hinting this.
If you have favicon on your site, remove it and try again. If your problem resolved, refactor your favicon url
I'm doing more or less the same thing now, and noticed the same thing.
I'm testing my server by entering the api address in chrome like this:
http://127.0.0.1:1337/links/1
my Node.js server is then responding with a json object depending on the id.
I set up a console log in the get method and noticed that when I change the id in the address bar of chrome it sends a request (before hitting enter to actually send the request) and the server accepts another request after I actually hit enter. This happens with and without having the chrome dev console open.
IE 11 doesn't seem to work in the same way but I don't have Firefox installed right now.
Hope that helps someone even if this was a kind of old thread :)
/J
I am to fix with listen.setTimeout and axios.defaults.timeout = 36000000
Node js
var timeout = require('connect-timeout'); //express v4
//in cors putting options response code for 200 and pre flight to false
app.use(cors({ preflightContinue: false, optionsSuccessStatus: 200 }));
//to put this middleaware in final of middleawares
app.use(timeout(36000000)); //10min
app.use((req, res, next) => {
if (!req.timedout) next();
});
var listen = app.listen(3333, () => console.log('running'));
listen.setTimeout(36000000); //10min
React
import axios from 'axios';
axios.defaults.timeout = 36000000;//10min
After of 2 days trying
you might have to increase the timeout even more. I haven't seen the express source but it just sounds on timeout, it retries.
Ensure you give res.send(); The axios call expects a value from the server and hence sends back a call request after 120 seconds.
I had the same issue doing this with Express 4. I believe it has to do with how it resolves request params. The solution is to ensure your params are resolved by for example checking them in an if block:
app.get('/:conversation', (req, res) => {
let url = req.params.conversation;
//Only handle request when params have resolved
if (url) {
res.redirect(301, 'http://'+ url + '.com')
}
})
In my case, my Axios POST requests were received twice by Express, the first one without body, the second one with the correct payload. The same request sent from Postman only received once correctly. It turned out that Express was run on a different port so my requests were cross origin. This caused Chrome to sent a preflight OPTION method request to the same url (the POST url) and my app.all routing in Express processed that one too.
app.all('/api/:cmd', require('./api.js'));
Separating POST from OPTIONS solved the issue:
app.post('/api/:cmd', require('./api.js'));
app.options('/', (req, res) => res.send());
I met the same problem. Then I tried to add return, it didn't work. But it works when I add return res.redirect('/path');
I had the same problem. Then I opened the Chrome dev tools and found out that the favicon.ico was requested from my Express.js application. I needed to fix the way how I registered the middleware.
Screenshot of Chrome dev tools
I also had double requests. In my case it was the forwarding from http to https protocol. You can check if that's the case by looking comparing
req.headers['x-forwarded-proto']
It will either be 'http' or 'https'.
I could fix my issue simply by adjusting the order in which my middlewares trigger.

Resources