Node.js : relative and absolute paths - node.js

There is something I have trouble with when serving pages (in my case, nodejs).
Let's say I have the following url : http://localhost:80 which serves a simple html page, but you must be logged in, either way you are redirected to a login page (http://localhost:80/login).
That's easy, and everything works fine.
Now let's say I have another url http://otherdoamin.com/internal/back that redirects to my server listening on the port 80.
I am having trouble to find what's the best way to manage my server to work on both url.
Here's a code sample just to show the logic :
function checkAuth(req, res, next) {
//if user isn't logged, redirect to login
}
app.get('/login', function(req, res) {
//if user is logged, redirect to base path (/) which serves an html page
//else
//display login.html page
})
app.get('/', checkAuth, function (req, res) {
res.sendFile(__dirname + '/views/index.html');
});
Let's say now that I have the following case :
I go to http://localhost:80, but I am not logged, I am redirected to the login page (http://localhost:80/login). Then after logging in, I am redirected back to http://localhost:80.
But if I do the following case with my other url (http://otherdoamin.com/internal/back), I'll have problems with the paths : if I have absolute paths, the redirection to login will work, but after logging in, I'll have a redirection to http://otherdoamin.com/ instead of http://otherdoamin.com/internal/back/, which is obvious.

Option 1:
Set otherdomain.com/internal/back as the base url in the Reverse Proxy Path definition.
Option 2:
Store the fully qualified original request url:
var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
And then use that to redirect;

Related

get host WITH PORT from request

I am trying to redirect to the original page after a login redirect. I have some middleware which checks if the user is logged in and if not redirects to the login page. code below
middlewareObj.isLoggedIn = function(req, res, next){
if(req.isAuthenticated()){
return next();
}
res.redirect("/login");
};
I am trying to get the full url from the request and tack it on the the end of the login URL so that after the login, I can redirect. According to the nodejs. docs I should be able to pull this info using req.host + req.originalURL. However, when I do that, it just pulls the hostname without pulling the port. in other words, it just returns localhost/pathname instead of localhost:3000/pathname. node js docs say that req.host should return the port while req.hostname should return just the hostname, but I'm getting the same output either way.
Thanks so much for any help!
req.header('Host') should get the HTTP Host header which will contain the port.

Appending to url path in express

I am building freeboard using freeboard.io. I am running it on a node server using express. I use
router.get('/', function(req, res, next) {
res.sendFile(path.join(__dirname + '/index.html'));
});
to send the freeboard html file when the base route is hit. However, in order for freeboard to load my saved dashboard I need to append #source=dashboard.json to the url. So the final url would look like
http://localhost:8080/#source=dashboard.json
is there some way I can do this using express? Pretty much when I hit localhost:8080/ I want to append to the url path #source=dashboard.json and respond with the index.html file. Thanks!
The fragment section of the URL is never sent to the server by the browser. See here for more info. Therefore for the server the fragment will always be missing even if the user has entered it on the URL field. In this case redirecting the browser back with the same URL inclusing the fragment may be the wrong thing.

ExpressJS : res.redirect() not working as expected?

I've been struggling for 2 days on this one, googled and stackoverflowed all I could, but I can't work it out.
I'm building a simple node app (+Express + Mongoose) with a login page that redirects to the home page. Here's my server JS code :
app
.get('/', (req, res) => {
console.log("Here we are : root");
return res.sendfile(__dirname + '/index.html');
})
.get('/login', (req, res) => {
console.log("Here we are : '/login'");
return res.sendfile(__dirname + '/login.html');
})
.post('/credentials', (req, res) => {
console.log("Here we are : '/credentials'");
// Some Mongoose / DB validations
return res.redirect('/');
});
The login page makes a POST request to /credentials, where posted data is verified. This works. I can see "Here we are : '/credentials'" in the Node console.
Then comes the issue : the res.redirect doesn't work properly. I know that it does reach the '/' route, because :
I can see "Here we are : root" in the Node console
The index.html page is being sent back to the browser as a reponse, but not displayed in the window.
Chrome inspector shows the POST request response, I CAN see the HTML code being sent to the browser in the inspector, but the URL remains /login and the login page is still being displayed on screen.
(Edit) The redirection is in Mongoose's callback function, it's not synchronous (as NodeJS should be). I have just removed Mongoose validation stuff for clarity.
I have tried adding res.end(), doesn't work
I have tried
req.method = 'get';
res.redirect('/');
and
res.writeHead(302, {location: '/'});
res.end();
Doesn't work
What am I doing wrong? How can I actually leave the '/login' page, redirect the browser to '/' and display the HTML code that it received?
Thanks a million for your help in advance :)
The problem might not lie with the backend, but with the frontend. If you are using AJAX to send the POST request, it is specifically designed to not change your url.
Use window.location.href after AJAX's request has completed (in the .done()) to update the URL with the desired path, or use JQuery: $('body').replaceWith(data) when you receive the HTML back from the request.
If you are using an asynchronous request to backend and then redirecting in backend, it will redirect in backend (i.e. it will create a new get request to that URL), but won't change the URL in front end.
To make it work you need to:
use window.location.href = "/url"
change your async request (in front end) to simple anchor tag (<a></a>)
It's almost certain that you are making an async call to check Mongoose but you haven't structured the code so that the redirect only happens after the async call returns a result.
In javascript, the POST would look like something this:
function validateCredentials(user, callback){
// takes whatever you need to validate the visitor as `user`
// uses the `callback` when the results return from Mongoose
}
app.post('/credentials', function(req, res){
console.log("Here was are: '/credentials'";
validateCredentials(userdata, function(err, data){
if (err) {
// handle error and redirect to credentials,
// display an error page, or whatever you want to do here...
}
// if no error, redirect
res.redirect('/');
};
};
You can also see questions like Async call in node.js vs. mongoose for parallel/related problems...
I've been working on implementing nodemailer into my NextJS app with Express. Was having this issue and came across this. I had event.preventDefault() in my function that was firing the form to submit and that was preventing the redirect as well, I took it off and it was redirecting accordingly.
Add the following in your get / route :
res.setHeader("Content-Type", "text/html")
Your browser will render file instead of downloading it

URL rewriting not working with iframe expressjs

I am trying to rewrite the URL of an iframe using express.
Similar code works fine on files available in my public folder (which express knows about thanks to server.use(express['static'](__dirname + '/public').
Jade code:
iframe(width="560", height="315", src="/videos/9bZkp7q19f0", frameborder="0", allowfullscreen=true)
Express code:
server.use(function(req, res, next) {
if (/videos/.test(req.url)) {
req.url = req.url.replace("videos", "embed");
req.url = "www.youtube.com" + req.url;
}
next();
});
Adding console.log(req.url) shows the correct url (www.youtube.com/embed/9bZkp7q19f0), yet express logs a 404 error.
Thanks in advance.
You can't just change req.url and expect the client to actually retrieve data from there. What you need is either a proxy or a redirect.
A redirect will force the iframe to redirect to youtube.com:
res.redirect('http://www.youtube.com' + req.url.replace('videos', 'embed'));
A proxy will actually request the page from your server, download the content, and serve back to the client: (you can use request for this)
req.pipe(require('request')('http://www.youtube.com'
+ req.url.replace('videos', 'embed'))).pipe(res);

Node - Tell origin of request

Is it possible to tell the difference between a request coming directly from a URL in a browser vs. a resource being called from a remote web page?
For example, I would like to serve a web page when someone visits my URL directly (types in http://mywebsite.com) in a web browser, but when a user calls a resource on my app via a url from a seperate domain (like <img src='http://mywebsite.com' />) then I'd like to serve different content.
I've looked in the request and in the headers but it looks the same regardless of
I think you are looking for the referer string in the request.header.
So the simple version would look like this:
http.createServer(function (req, res) {
var ref = req.headers.referer;
if(ref) {
// serve special content
}
else {
// serve regular homepage
}
}).listen(1337, '127.0.0.1');
edited the answer to reflect the input from anu below - it should be referer
In middleware you have to use this way "req.headers.origin"
app.use(function(req, res, next) {
//var origin=req.headers.origin
next();
});

Resources