I need to know where user came from node js - node.js

I have a back-end by nodejs I need to know where user come from.
if he came from localhost (postman) or his website HTTP request.
I need to know his user domain's not mind like 'http://localhost/' or 'http://user-website.com' or even from google search ! from he is came ?
, I tried user req.get('origin) but always return undefined

You must connect 'url' module
var http = require('http');
var url = require('url') ;
http.createServer(function (req, res) {
var hostname = req.headers.host; // hostname = 'localhost:8080'
var pathname = url.parse(req.url).pathname; // pathname = '/MyApp'
console.log('http://' + hostname + pathname);
res.writeHead(200);
res.end();
}).listen(8080);

use req.headers['user-agent'] to see if it is postman agent or not.

In order to know whether the request is coming from localhost or a remote client, you'll need to obtain the client's IP address. Example in Express:
app.get('/', (req, res) => {
const ipAddress = req.connection.remoteAddress;
// ...
});
More docs about getting the IP here, also check this other question on the subject.
Basically if the request is coming from localhost, ipAddress will be ::1 or other localhost IP address, but if it's not, it's going to look like a public IP address, like 173.194.79.101 (the IP of google.com).

Related

Express.js Find URL of client consuming REST API

Lets say, I have a server running at: https://example.com
The code in server:
const express = require("express");
const app = express();
app.get('/',(req, res)=>{
let data = {'Hello':'World'}
res.json(data);
});
app.post('/',(req, res)=>{
let name = req.body.name;
let email = req.body.email;
res.json({name, email});
});
app.listen(3000);
Now, there is a client: https://website.com, trying to access server response by making a GET and POST request. (No API key is required)
How can the server find the web address of the client?
In this example, I want the server (example.com) to determine the client's URL (website.com) and save it in the database. req.hostname() is not giving the desired output..
req.hostname is what you're looking for.
Update:
After re-reading your question, I think what you want is identifying cross-origin requests, you would instead use the Origin header.
var origin = req.get('origin');
Note that some cross-origin requests require validation through a "preflight" request:
req.options('/route', function (req, res) {
var origin = req.get('origin');
// ...
});

Node.js multiple subdomains

I am using node.js to build a multi-tenant application where different clients with their own subdomains will be accessing a single instance of my app. My questions is:
Is there a way for the app to find out which subdomain a user is on? That way, I can route the user to the correct database schema (postgresql).
Thanks in advance!
Additional information:
I am using the Express framework
I'm not using multiple instances because I expect to have upwards of thousands of users and I don't want to manage thousands of instances.
Regarding subdomains, I mean something like:
myapp.client1domain.com
myapp.client2domain.com
myapp.client3domain.com
Each of the above url's link to the same instance of the app. However, I need to know which subdomain a user is on so I can route them to the right database schema.
Since "host" from HTTP/1.1 or greater is reflected in the request object as "host" header. You could do something like:
const setupDatabaseScheme = (host, port) => {
// ...
};
http.createServer((req, res) => {
if (req.headers.host) {
const parts = req.headers.host.split(":");
setupDataBaseSchema(parts[0], parts[1]);
}
});
Please note that port might be undefined; and do additional checks, add error handling if there is no host header or HTTP version is below 1.1. Of course you could do similar as an express middleware, or with any similar framework, this is just bare node.js http.
Update:
In express I'd do something like:
const getConnecitonForSchemeByHost = (host) => {
// ... get specific connection for given scheme from pool or similar
return "a connection to scheme by host: " + host;
};
router
.all("*", function (req, res, next) {
const domain = req.get("host").split(":")[0];
const conn = res.locals.dbConnection = getConnecitonForSchemeByHost(domain);
if (conn) {
next();
} else {
next(new Error("no connection for domain: " + domain))
}
})
.get("/", function (req, res) { // use connection from res.locals at further routes
console.log(res.locals.dbConnection);
res.send("ok");
});
app.use("/db", router);
req.get("host") gives you back the host the request was directed to, e.g. myapp.client1domain.com or so (match specific part with regexp) and based on that you could set a property on res.locals which you could use on subsequent routes, or bail out in case of an unknown domain.
The above snipped would log "a connection to scheme by host: localhost", if you do a request to http://localhost:<port>/db.

proxying requests from a secure application

im trying to proxy requests from a secure web application(https) in node (its an internal application) and im not quite sure how to do it...
the below is my code which works when i try it from an non secured app (http).
It just strips out a page name and uses it in another app. I read the docs but still not sure how to do it. Do i need to have the ssl info from my application for this to work?
var http = require('http');
var httpProxy = require('http-proxy');
var request = require('request');
var app = require('express.io')();
app.http().io();
//
// Create proxy server
//
var proxy = httpProxy.createProxyServer({target:'http://localhost:9000'}).listen(9085);
// Send the client html.
app.get('/', function(req, res) {
res.sendfile(__dirname + '/client1.html');
})
proxy.on('error', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong!');
});
app.all('/Domain/*', function(req, res) {
console.log(req.url);
if (req.url.indexOf("Page.do") > -1) {
// URL to Atlas
var otherAppURL = "http://myotherapp/pages/";
var temp = req.url.split("Page.do")[0].split("/");
var pageName = temp[temp.length - 1];;
app.io.broadcast('update', {
url: atlasURL + pageName + '.html'
});
};
// This doesnt work
//var url = "https://mysecureapp:9044" + req.url;
// This works
var url = "http://localhost:9080" + req.url;
req.pipe(request(url)).pipe(res);
})
app.listen(9000);
Yes, you do need an SSL Certificate for an HTTPS connection. According to the website https://www.globalsign.com/en/ssl-information-center/what-is-an-ssl-certificate/ :
The standard HTTP is changed to HTTPS, automatically telling the browser that the connection between the server and the browser must be secured using SSL.
This means that with an HTTPS connection, you need to have the server secured with SSL.
For connecting with HTTPS in Node, this website might help you:
http://gaboesquivel.com/blog/2014/nodejs-https-and-ssl-certificate-for-development/
Ok i might be mistaking but this line doesn't make sense ,
req.pipe(request(url)).pipe(res);
by the time the route handler hits, the req object is ready
so req.pipe has no meaning.
please check that url returns a valid response
request(url).pipe(res); should work
http / https is not an issue

What is nodejs express manage several domains?

I have got 2 domain names. For instance, example0.org and example1.org.
How to setup nodejs using express to manage both of them?
For instance, I wanna share
/publicexample0
folder as root for
example0.org
and
/publicexample1
folder for
example1.org
as root
This works just for a one domain:
var app = express.createServer();
app.get('/', function(req, res) {
res.send('Hello World');
});
app.listen(3000);
I guess what you can do is to take advantage of the HTTP host header. It contains:
The domain name of the server (for virtual hosting), and the TCP port
number on which the server is listening. The port number may be
omitted if the port is the standard port for the service requested.
Mandatory since HTTP/1.1.
You can see its specification in the RFC 2616 - HTTP v1.1
And obviously you could read the header out of your request in Express and make a decision based on its value.
router.get('/hello', function(req, res){
var host = req.get('host');
if(host === 'example0.org'){
res.send(200,'Welcome from example0.org');
} else if(host === 'example1.org'){
res.send(200,'Welcome from example1.org');
} else {
res.send(200,'Welcome stranger');
}
});

NodeJS - Reverse Proxy with Route Changing

I'm currently using NodeJS/Express as a simple domain router running on my VPS on port 80. My routes.coffee looks something like this:
request = require("request")
module.exports = (app) ->
#404, 503, error
app.get "/404", (req, res, next) ->
res.send "404. Sowway. :("
app.get "/error", (req, res, next) ->
res.send "STOP SENDING ERRORS! It ain't cool, yo."
#Domain Redirects
app.all '/*', (req, res, next) ->
hostname = req.headers.host.split(":")[0]
#Website1.com
if hostname == 'website1.com'
res.status 301
res.redirect 'http://facebook.com/website1'
#Example2.com
else if hostname == 'example2.com'
pathToGo = (req.url).replace('www.','').replace('http://example2.com','')
request('http://localhost:8020'+pathToGo).pipe(res)
#Other
else
res.redirect '/404'
As you can see in Example2.com, I'm attempting to reverse proxy to another node instance on a different port. Overall it works perfectly, except for one issue. If the route on the other node instance changes (Redirects from example2.com/page1.html to example2.com/post5), the URL in the address bar doesn't change. Would anyone happen to have a nice workaround for this? Or maybe a better way to reverse proxy? Thanks!
In order to redirect the client, you should set the http-status-code to 3xx and send a location header.
I'm not familiar with request module but I believe it follows redirects by default.
On the other hand, you're piping the proxy-request's response to client's response object, discarding the headers and the status code. That's why the clients don't get redirected.
Here is a simple reverse HTTP proxy using the built-in HTTP client. It's written in javascript but you can easily translate it to coffeescript and use request module if you want.
var http = require('http');
var url = require('url');
var server = http.createServer(function (req, res) {
parsedUrl = url.parse(req.url);
var headersCopy = {};
// create a copy of request headers
for (attr in req.headers) {
if (!req.headers.hasOwnProperty(attr)) continue;
headersCopy[attr] = req.headers[attr];
}
// set request host header
if (headersCopy.host) headersCopy.host = 'localhost:8020';
var options = {
host: 'localhost:8020',
method: req.method,
path: parsedUrl.path,
headers: headersCopy
};
var clientRequest = http.request(options);
clientRequest.on('response', function (clientResponse) {
res.statusCode = clientResponse.statusCode;
for (header in clientResponse.headers) {
if (!clientResponse.headers.hasOwnProperty(header)) continue;
res.setHeader(header, clientResponse.headers[header]);
}
clientResponse.pipe(res);
});
req.pipe(clientRequest);
});
server.listen(80);
// drop root privileges
server.on('listening', function () {
process.setgid && process.setgid('nobody');
process.setuid && process.setuid('nobody');
});

Resources