I have created and tested the POST and GET request methods in Nodejs such that I can send the user through the Gocardless sign-up API perfectly fine.
This is a sign-up form provided by their API which allows them to input their details and then returns the user back after they fill it in.
But when I set up a front-end using Vuejs and make the same calls previously made from the back end using Axios, it seems that because the "redirect_url" fed back to me from the GC API had previously been fed directly into the browser url before, now, because it seems vue-router has control of the browser, I'm getting a cross origin error.
How can I configure the files to have the Nodejs back end acting as if it had control of the browser?
The end points are described here:
https://developer.gocardless.com/api-reference/#core-endpoints-redirect-flows
My nginx default is:
server {
charset UTF-8;
listen 80;
root /srv/www/sitename/;
index index.html;
server_name sitename.com;
location /api/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://sitename.com:8081;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
}
location / {
try_files $uri.html $uri $uri/ /index.html;
}
My button from Vuejs front end:
completeOrder()
..and uses axios this way:
import axios from 'axios'
export default() => {
return axios.create({
baseURL: 'http://sitename.com:8081/api'
})
}
And set it up here:
import Api from '#/services/Api'
export default {
completeOrder () {
return Api().post('order')
}
}
In the back end it sends:
app.post('/api/order', function (req, res){
rp({
//rp is npm request-promise
uri: BASE_URL + "/redirect_flows",
method: 'POST',
body:JSON.stringify(input_json),
headers: headers
}) // this works and API sends me the response
.then(function(response) {
var str_response =JSON.parse(response);
url = str_response['redirect_flows']['redirect_url']
// url works fine when I paste into a separate browser
res.redirect(url)
})
.catch(function (err) {
console.error(err);
})
})
Everything works up until the point:
res.redirect(url)
..where the Gocardless API response supplies me with the URL which I need to load into a browser.
It looks something like this:
https://pay-sandbox.gocardless.com/flow/RE000156
I think I need to break out of Vuejs's control of the browser via vue-router just long enough to allow the user to call the form with the redirect_url, then come back to the home page of the app again.
Any ideas very welcome!
I think you actually have a JS error. In the then block you instantiate a response, but you use a res variable to redirect.
Try chaging the variable
.then(function(response) {
var str_response = JSON.parse(response);
url = str_response['redirect_flows']['redirect_url']
// url works fine when I paste into a separate browser
response.redirect(url)
})
I am not a Vue.JS expert, so I don't know if that works, try using a vanilla JS redirect to test this feature:
window.location.href = url;
This way, you will be sure that the url works. After that, try checking out a full Vue.JS option.
I have a host computer which serves a number of webapplications (not node.js based). It does this using different ports. This means that for example the following applications are live:
app1: http://hostname:3000
app2: http://hostname:3001
app3: http://hostname:3003
Next to that I have a node.js based webapp (running on port 80) which I want to use as a sort of router. When someone navigates to http://localhost/app/app1. I want it to navigate to http://hostname:3000. This is relatively straightforward using a simple redirect. However, I would want to preserve the url http://localhost/app/app1. Can someone point me to a way to make this work using node.js/express?
My routing logic looks somewhat like this (pseudo-code).
app.route('/app/:appName')
.get(appEngine.gotoApp);
appEngine.gotoApp = function(req, res) {
redirectToApp logic
}
You probably better use Nginx setting up a reverse proxy with different locations per application.
It's not what you ask for because it does not use node.js, but if it's the only purpose, Nginx really suits your needs.
For example a Nginx configuration file like should work the way you want :
server {
listen 80;
server_name myapp.com;
location /app1 {
proxy_pass http://APP_PRIVATE_IP_ADDRESS:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /app2 {
proxy_pass http://APP_PRIVATE_IP_ADDRESS:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /app3 {
proxy_pass http://APP_PRIVATE_IP_ADDRESS:3003;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
If you use express, you can try to create the app with the cli express application generator.
It creates an express app and returns it with module exports.
In the server.js file it pass to listen function of the server instance the express app object.
You can create more server object and listen different app with different port.
var server = http.createServer(app);
server.listen(port);
var server2 = http.createServer(app2);
server2.listen(port2);
If you want to point different app based on the url, you can instance an express router instead of express object.
var app1 = express.Router();
Then you can set all your routes into this object with classic get or post or other methods.
Now you are able to pass the router as a middleware of your main express app.
app.use( "app1/", app1 );
You can also pass an express app to middleware, instead of router object, in order to gain the possibility of exec the app with a different url and port server listening.
There is a nice http-proxy lib designed exactly for that!
const httpProxy = require('http-proxy');
const url = require('url');
const proxy = httpProxy.createProxy();
const options = {
'/app/app1': 'http://localhost:3000',
'/app/app2': 'http://localhost:3001',
'/app/app3': 'http://localhost:3003',
}
require('http').createServer((req, res) => {
const pathname = url.parse(req.url).pathname;
for (const [pattern, target] of Object.entries(options)) {
if (pathname === pattern ||
pathname.startsWith(pattern + '/')
) {
proxy.web(req, res, {target});
}
}
}).listen(80);
How can I determine the IP address of a given request from within a controller? For example (in express):
app.post('/get/ip/address', function (req, res) {
// need access to IP address here
})
In your request object there is a property called socket, which is a net.Socket object. The net.Socket object has a property remoteAddress, therefore you should be able to get the IP with this call:
request.socket.remoteAddress
(if your node version is below 13, use the deprecated now request.connection.remoteAddress)
EDIT
As #juand points out in the comments, the correct method to get the remote IP, if the server is behind a proxy, is request.headers['x-forwarded-for']
EDIT 2
When using express with Node.js:
If you set app.set('trust proxy', true), req.ip will return the real IP address even if behind proxy. Check the documentation for further information
var ip = req.headers['x-forwarded-for'] ||
req.socket.remoteAddress ||
null;
Note that sometimes you can get more than one IP address in req.headers['x-forwarded-for']. Also, an x-forwarded-for header will not always be set which may throw an error.
The general format of the field is:
x-forwarded-for: client, proxy1, proxy2, proxy3
where the value is a comma+space separated list of IP addresses, the left-most being the original client, and each successive proxy that passed the request adding the IP address where it received the request from. In this example, the request passed through proxy1, proxy2, and then proxy3. proxy3 appears as remote address of the request.
This is the solution suggested by Arnav Gupta with a fix Martin has suggested below in the comments for cases when x-forwarded-for is not set :
var ip = (req.headers['x-forwarded-for'] || '').split(',').pop().trim() ||
req.socket.remoteAddress
Suggestion using modern JS:
processing x-forwarded-for only if set, if so, take the first address
other parameters use optional chaining (?.)
const parseIp = (req) =>
req.headers['x-forwarded-for']?.split(',').shift()
|| req.socket?.remoteAddress
console.log(parseIp(req))
// => 127.0.0.1
If using express...
req.ip
I was looking this up then I was like wait, I'm using express. Duh.
You can stay DRY and just use node-ipware that supports both IPv4 and IPv6.
Install:
npm install ipware
In your app.js or middleware:
var getIP = require('ipware')().get_ip;
app.use(function(req, res, next) {
var ipInfo = getIP(req);
console.log(ipInfo);
// { clientIp: '127.0.0.1', clientIpRoutable: false }
next();
});
It will make the best attempt to get the user's IP address or returns 127.0.0.1 to indicate that it could not determine the user's IP address. Take a look at the README file for advanced options.
You can use request-ip, to retrieve a user's ip address. It handles quite a few of the different edge cases, some of which are mentioned in the other answers.
Disclosure: I created this module
Install:
npm install request-ip
In your app:
var requestIp = require('request-ip');
// inside middleware handler
var ipMiddleware = function(req, res, next) {
var clientIp = requestIp.getClientIp(req); // on localhost > 127.0.0.1
next();
};
Hope this helps
request.headers['x-forwarded-for'] || request.connection.remoteAddress
If the x-forwarded-for header is there then use that, otherwise use the .remoteAddress property.
The x-forwarded-for header is added to requests that pass through load balancers (or other types of proxy) set up for HTTP or HTTPS (it's also possible to add this header to requests when balancing at a TCP level using proxy protocol). This is because the request.connection.remoteAddress the property will contain the private IP address of the load balancer rather than the public IP address of the client. By using an OR statement, in the order above, you check for the existence of an x-forwarded-for header and use it if it exists otherwise use the request.connection.remoteAddress.
Following Function has all the cases covered will help
var ip;
if (req.headers['x-forwarded-for']) {
ip = req.headers['x-forwarded-for'].split(",")[0];
} else if (req.connection && req.connection.remoteAddress) {
ip = req.connection.remoteAddress;
} else {
ip = req.ip;
}console.log("client IP is *********************" + ip);
Warning:
Don't just blindly use this for important rate-limiting:
let ip = request.headers['x-forwarded-for'].split(',')[0];
It's very easy to spoof:
curl --header "X-Forwarded-For: 1.2.3.4" "https://example.com"
In that case ther user's real IP address will be:
let ip = request.headers['x-forwarded-for'].split(',')[1];
I'm surprised that no other answers have mentioned this.
I have tried all of them didn't work though,
console.log(clientIp);
console.log(req.ip);
console.log(req.headers['x-forwarded-for']);
console.log(req.connection.remoteAddress);
console.log(req.socket.remoteAddress);
console.log(req.connection.socket.remoteAddress.split(",")[0]);
When running an Express app behind a proxy for me Nginx, you have to set the application variable trust proxy to true. Express offers a few other trust proxy values which you can review in their documentation, but below steps worked for me.
app.set('trust proxy', true) in your Express app.
app.set('trust proxy', true);
Add proxy_set_header X-Forwarded-For $remote_addr in the Nginx
configuration for your server block.
location / {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr; # this line
proxy_cache_bypass $http_upgrade;
}
You can now read off the client’s IP address from the
req.header('x-forwarded-for') or req.connection.remoteAddress; Full code for ipfilter
module.exports = function(req, res, next) {
let enable = true; // true/false
let blacklist = ['x.x.x.x'];
let whitelist = ['x.x.x.x'];
let clientIp = req.header('x-forwarded-for') || req.connection.remoteAddress;
if (!clientIp) {
return res.json('Error');
}
if (enable
&& paths.some((path) => (path === req.originalUrl))) {
let blacklist = blacklist || [];
if (blacklist.some((ip) => clientIp.match(ip) !== null)) {
return res.json({ status: 401, error: 'Your IP is black-listed !'});
}
let whitelist = whitelist || [];
if (whitelist.length === 0 || whitelist.some((ip) => clientIp.match(ip) !== null)) {
next();
return;
} else {
return res.json({ status: 401, error: 'Your IP is not listed !'});
}
}
next();
};
There are two ways to get the ip address :
let ip = req.ip
let ip = req.connection.remoteAddress;
But there is a problem with above approaches.
If you are running your app behind Nginx or any proxy, every single IP addresses will be 127.0.0.1.
So, the best solution to get the ip address of user is :-
let ip = req.header('x-forwarded-for') || req.connection.remoteAddress;
function getCallerIP(request) {
var ip = request.headers['x-forwarded-for'] ||
request.connection.remoteAddress ||
request.socket.remoteAddress ||
request.connection.socket.remoteAddress;
ip = ip.split(',')[0];
ip = ip.split(':').slice(-1); //in case the ip returned in a format: "::ffff:146.xxx.xxx.xxx"
return ip;
}
In node 10.14 , behind nginx, you can retrieve the ip by requesting it through nginx header like this:
proxy_set_header X-Real-IP $remote_addr;
Then in your app.js:
app.set('trust proxy', true);
After that, wherever you want it to appear:
var userIp = req.header('X-Real-IP') || req.connection.remoteAddress;
If you're using express version 3.x or greater, you can use the trust proxy setting (http://expressjs.com/api.html#trust.proxy.options.table) and it will walk the chain of addresses in the x-forwarded-for header and put the latest ip in the chain that you've not configured as a trusted proxy into the ip property on the req object.
If you're using express.js then,
app.post('/get/ip/address', function (req, res) {
res.send(req.ip);
})
var ipaddress = (req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress).split(",")[0];
If you get multiple IPs , this works for me:
var ipaddress = (req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress).split(",")[0];
Simple get remote ip in nodejs:
var ip = req.header('x-forwarded-for') || req.connection.remoteAddress;
req.connection has been deprecated since node#12.12.0. Using req.connection.remoteAddress to get the client IP might still work but is discouraged.
Luckily, req.socket.remoteAddress has been there since node#0.5.10 and is a perfect replacement:
The string representation of the remote IP address. For example, '74.125.127.100' or '2001:4860:a005::68'. Value may be undefined if the socket is destroyed (for example, if the client disconnected).
There were a lot of great points here but nothing that was comprehensive, so here's what I ended up using:
function getIP(req) {
// req.connection is deprecated
const conRemoteAddress = req.connection?.remoteAddress
// req.socket is said to replace req.connection
const sockRemoteAddress = req.socket?.remoteAddress
// some platforms use x-real-ip
const xRealIP = req.headers['x-real-ip']
// most proxies use x-forwarded-for
const xForwardedForIP = (() => {
const xForwardedFor = req.headers['x-forwarded-for']
if (xForwardedFor) {
// The x-forwarded-for header can contain a comma-separated list of
// IP's. Further, some are comma separated with spaces, so whitespace is trimmed.
const ips = xForwardedFor.split(',').map(ip => ip.trim())
return ips[0]
}
})()
// prefer x-forwarded-for and fallback to the others
return xForwardedForIP || xRealIP || sockRemoteAddress || conRemoteAddress
}
I realize this has been answered to death, but here's a modern ES6 version I wrote that follows airbnb-base eslint standards.
const getIpAddressFromRequest = (request) => {
let ipAddr = request.connection.remoteAddress;
if (request.headers && request.headers['x-forwarded-for']) {
[ipAddr] = request.headers['x-forwarded-for'].split(',');
}
return ipAddr;
};
The X-Forwarded-For header may contain a comma-separated list of proxy IPs. The order is client,proxy1,proxy2,...,proxyN. In the real world, people implement proxies that may supply whatever they want in this header. If you are behind a load balancer or something, you can at least trust the first IP in the list is at least whatever proxy some request came through.
I use this for ipv4 format
req.connection.remoteAddress.split(':').slice(-1)[0]
You can Get User Ip with Express Like this
req.ip
For Example In This case we get the user Ip and send it back to the user With req.ip
app.get('/', (req, res)=> {
res.send({ ip : req.ip})
})
If you are using Graphql-Yoga you can use the following function:
const getRequestIpAddress = (request) => {
const requestIpAddress = request.request.headers['X-Forwarded-For'] || request.request.connection.remoteAddress
if (!requestIpAddress) return null
const ipv4 = new RegExp("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")
const [ipAddress] = requestIpAddress.match(ipv4)
return ipAddress
}
I'm using express behind nginx and
req.headers.origin
did the trick for me
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
var ip = req.ip
console.log(ip);
res.send('Hello World!')
})
// Run as nodejs ip.js
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
In a shell, you would just curl https://api.ipify.org
So, let's observe this to port it to node.js!
curl is a application to fetch data from websites, we pass the website "https://api.ipify.org" as the argument. We could use node-fetch to replace curl!
The data we get from the website is our IP address, It's some sort of thing which just fetches your IP.
So to sum it up:
const fetch = require('node-fetch');
fetch('https://api.ipify.org')
.then(response => {/* whatever */})
.catch(err => {/* whatever */})
First, install request-ip in your project
import requestIp from 'request-ip';
const clientIp = requestIp.getClientIp(req);
console.log(clientIp)
If you work on localhost, the result might come ::1 because ::1 is real IP Address and is IPV6 notation for localhost.
Using ValidatorJS in Typescript. Here is NodeJS middleware:
// Extract Client IP Address
app.use((req, res, next) => {
let ipAddress = (req.headers['x-forwarded-for'] as string || '').split(',')[0]
if (!validator.isIP(ipAddress))
ipAddress = req.socket.remoteAddress?.toString().split(':').pop() || ''
if (!validator.isIP(ipAddress))
return res.status(400).json({errorMessage: 'Bad Request'})
req.headers['x-forwarded-for'] = ipAddress
next()
})
Here I am assuming all requests should have a valid IP address and hence return a response with code 400 if there is no valid IP address found.
For me using kubernetes ingress (NGINX):
req.headers['x-original-forwarded-for']
Worked like a charm in Node.js
we can check with this code in node js
const os = require('os');
const interfaces = os.networkInterfaces();
let addresses = [];
for (var k in interfaces) {
for (var k2 in interfaces[k]) {
const address = interfaces[k][k2];
if ( (address.family === 'IPv4' || address.family === 'IPv6') &&
!address.internal) {
addresses.push(address.address);
}
}
}
console.log(addresses);
I have a node application on an instance-store amazon machine behind the elastic load balancer (elb). However, the remote IP adress seems to always be the same. I used this code to get the client's IP address in node (via connect/express):
req.socket.remoteAddress
I didn't get anything else from the node documentation. Any hint?
Here's a solution in case you are using express:
According to the documentation, you can enable trust proxy for your express instance and then req.ip will be populated with the correct ip address.
By enabling the "trust proxy" setting via app.enable('trust proxy'),
Express will have knowledge that it's sitting behind a proxy and that
the X-Forwarded-* header fields may be trusted, which otherwise may be
easily spoofed.
Enabling this setting has several subtle effects. The first of which
is that X-Forwarded-Proto may be set by the reverse proxy to tell the
app that it is https or simply http. This value is reflected by
req.protocol.
The second change this makes is the req.ip and req.ips values will be
populated with X-Forwarded-For's list of addresses.
Here's an example:
var app = express();
app.enable('trust proxy');
// ...
app.use(function(req, res, next) {
console.log('client ip address:', req.ip);
return next();
});
The answer worked for me, thanks. But you may just try:
var ip_address = null;
if(req.headers['x-forwarded-for']){
ip_address = req.headers['x-forwarded-for'];
}
else {
ip_address = req.connection.remoteAddress;
}
sys.puts( ip_address );
Your receiving the IP of the ELB instance and you'll need to get the x-forwarded-for value from the headers. Since I'm not a node.js guru, I found this code at http://forum.webfaction.com/viewtopic.php?id=4500
Example:
var http = require( 'http' ),
sys = require( 'sys' );
http.createServer(
function( req, res ) {
var ip_address = null;
try {
ip_address = req.headers['x-forwarded-for'];
}
catch ( error ) {
ip_address = req.connection.remoteAddress;
}
sys.puts( ip_address );
}
);
The selected correct answer here is dangerous, because AWS ELBs switch the order as expected: https://github.com/koajs/koa/issues/1094#issuecomment-345861282
Express, koa, etc. typically take the left-most item, while ELB makes it the right-most item
(express docs):
If true, the client’s IP address is understood as the left-most entry in the X-Forwarded-For header.
In case if express.js is in use:
app.set('trust proxy', 2)
Instead of
app.enable('trust proxy')
Because the app.enable('trust proxy') uses the leftmost ip from the x-forwarded-for header and so can be easily spoofed by just providing x-forwarded-for header manually.
While the app.set('trust proxy', 2) has the number of hops specified that being counted from right to left of the x-forwarded-for header. I.e. if there is an AWS load balancer than 2 will be the right number to count because each new hop ip is added to the end of the x-forwarded-for header.
If you're using something else then do the similar way. Just get the req.headers['x-forwarded-for'], split by coma and then count hops from right to left until load balancer ip is not excluded.