Let's say my sample URL is
http://example.com/one/two
and I say I have the following route
app.get('/one/two', function (req, res) {
var url = req.url;
}
The value of url
will be /one/two
.
How do I get the full URL in Express? For example, in the case above, I would like to receive http://example.com/one/two
.
req.completeURL()
method · Issue #4697 · expressjs/express for this.
The protocol is available as req.protocol. docs here Before express 3.0, the protocol you can assume to be http unless you see that req.get('X-Forwarded-Protocol') is set and has the value https, in which case you know that's your protocol The host comes from req.get('host') as Gopal has indicated Hopefully you don't need a non-standard port in your URLs, but if you did need to know it you'd have it in your application state because it's whatever you passed to app.listen at server startup time. However, in the case of local development on a non-standard port, Chrome seems to include the port in the host header so req.get('host') returns localhost:3000, for example. So at least for the cases of a production site on a standard port and browsing directly to your express app (without reverse proxy), the host header seems to do the right thing regarding the port in the URL. The path comes from req.originalUrl (thanks @pgrassant). Note this DOES include the query string. docs here on req.url and req.originalUrl. Depending on what you intend to do with the URL, originalUrl may or may not be the correct value as compared to req.url.
Combine those all together to reconstruct the absolute URL.
var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
Instead of concatenating the things together on your own, you could instead use the node.js API for URLs and pass URL.format()
the informations from express.
Example:
var url = require('url');
function fullUrl(req) {
return url.format({
protocol: req.protocol,
host: req.get('host'),
pathname: req.originalUrl
});
}
req.get('host')
returns only the hostname part, not the port. Don't know why, but now I gather the port number from the settings, and use the hostname
field, instead of host
.
pathname
, I think you mean path
. Which includes search/querystring
const url = new URL(req.protocol + '://' + req.get('host') + req.originalUrl)
url.format
is now deprecated.
I found it a bit of a PITA to get the requested url. I can't believe there's not an easier way in express. Should just be req.requested_url
But here's how I set it:
var port = req.app.settings.port || cfg.port;
res.locals.requested_url = req.protocol + '://' + req.host + ( port == 80 || port == 443 ? '' : ':'+port ) + req.path;
req.port
exist? It is not in the Express documentation?
req.app.settings.port
Here is a great way to add a function you can call on the req object to get the url
app.use(function(req, res, next) {
req.getUrl = function() {
return req.protocol + "://" + req.get('host') + req.originalUrl;
}
return next();
});
Now you have a function you can call on demand if you need it.
In 2021
The above answers are working fine but not preferred by the Documentation because url.parse
is now legacy
so I suggest you to use new URL()
function if you want to get more control on url
.
Express Way
You can get Full URL
from the below code.
`${req.protocol}://${req.get('host')}${req.originalUrl}`
Example URL: http://localhost:5000/a/b/c?d=true&e=true#f=false
Fixed Properties ( you will get the same results in all routes )
req.protocol: http
req.hostname: localhost
req.get('Host'): localhost:5000
req.originalUrl: /a/b/c?d=true&e=true
req.query: { d: 'true', e: 'true' }
Not Fixed Properties ( will change in every route because it controlled by express itself )
Route: /
req.baseUrl: <blank>
req.url: /a/b/c?d=true&e=true
req.path: /a/b/c
Route /a
req.baseUrl: /a
req.url: /b/c?d=true&e=true
req.path: /b/c
Documentation: http://expressjs.com/en/api.html#req.baseUrl
URL Package Way
In the URL
function, you will get the same results in every route so properties are always fixed.
Properties
https://i.stack.imgur.com/QKa0Q.png
const url = new URL(`${req.protocol}://${req.get('host')}${req.originalUrl}`);
console.log(url)
You will get the results like the below. I changed the order of the properties as per the image so it can match the image flow.
URL {
href: 'http://localhost:5000/a/b/c?d=true&e=true',
protocol: 'http:',
username: '',
password: '',
hostname: 'localhost',
port: '5000',
host: 'localhost:5000',
origin: 'http://localhost:5000',
pathname: '/a/b/c',
search: '?d=true&e=true',
searchParams: URLSearchParams { 'd' => 'true', 'e' => 'true' },
hash: ''
}
Note: Hash
can not send to the server because it treats as Fragment
in the server but you will get that in the client-side means browser.
Documentation: https://nodejs.org/api/url.html#url_new_url_input_base
req.get("host")
will include the port but besides "host" being deprecated, this is just not the case.
get()
is used for getting headers of the request and in the request, you have the host
header so it simply calls the request header and gets the port and it's very safe to use and nothing is depereacted here
Using url.format:
var url = require('url');
This support all protocols and include port number. If you don't have a query string in your originalUrl you can use this cleaner solution:
var requrl = url.format({
protocol: req.protocol,
host: req.get('host'),
pathname: req.originalUrl,
});
If you have a query string:
var urlobj = url.parse(req.originalUrl);
urlobj.protocol = req.protocol;
urlobj.host = req.get('host');
var requrl = url.format(urlobj);
make req.host/req.hostname effective must have two condition when Express behind proxies:
app.set('trust proxy', 'loopback'); in app.js X-Forwarded-Host header must specified by you own in webserver. eg. apache, nginx
nginx:
server {
listen myhost:80;
server_name myhost;
location / {
root /path/to/myapp/public;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://myapp:8080;
}
}
apache:
<VirtualHost myhost:80>
ServerName myhost
DocumentRoot /path/to/myapp/public
ProxyPass / http://myapp:8080/
ProxyPassReverse / http://myapp:8080/
</VirtualHost>
127.0.0.1
from req.get('host')
Use this,
var url = req.headers.host + '/' + req.url;
Just the code below was enough for me!
const baseUrl = `${request.protocol}://${request.headers.host}`;
// http://127.0.0.1:3333
I would suggest using originalUrl instead of URL:
var url = req.protocol + '://' + req.get('host') + req.originalUrl;
See the description of originalUrl here: http://expressjs.com/api.html#req.originalUrl
In our system, we do something like this, so originalUrl is important to us:
foo = express();
express().use('/foo', foo);
foo.use(require('/foo/blah_controller'));
blah_controller looks like this:
controller = express();
module.exports = controller;
controller.get('/bar/:barparam', function(req, res) { /* handler code */ });
So our URLs have the format:
www.example.com/foo/bar/:barparam
Hence, we need req.originalUrl in the bar controller get handler.
var full_address = req.protocol + "://" + req.headers.host + req.originalUrl;
or
var full_address = req.protocol + "://" + req.headers.host + req.baseUrl;
You need to construct it using req.headers.host + req.url
. Of course if you are hosting in a different port and such you get the idea ;-)
req.protocol
I use the node package 'url' (npm install url)
What it does is when you call
url.parse(req.url, true, true)
it will give you the possibility to retrieve all or parts of the url. More info here: https://github.com/defunctzombie/node-url
I used it in the following way to get whatever comes after the / in http://www.example.com/ to use as a variable and pull up a particular profile (kind of like facebook: http://www.facebook.com/username)
var url = require('url');
var urlParts = url.parse(req.url, true, true);
var pathname = urlParts.pathname;
var username = pathname.slice(1);
Though for this to work, you have to create your route this way in your server.js file:
self.routes['/:username'] = require('./routes/users');
And set your route file this way:
router.get('/:username', function(req, res) {
//here comes the url parsing code
}
My code looks like this,
params['host_url'] = req.protocol + '://' + req.headers.host + req.url;
You can use this function in the route like this
app.get('/one/two', function (req, res) {
const url = getFullUrl(req);
}
/**
* Gets the self full URL from the request
*
* @param {object} req Request
* @returns {string} URL
*/
const getFullUrl = (req) => `${req.protocol}://${req.headers.host}${req.originalUrl}`;
req.protocol
will give you http or https, req.headers.host
will give you the full host name like www.google.com, req.originalUrl
will give the rest pathName
(in your case /one/two
)
You can get the full url from req of express.
function fetchPages(req, res, next) {
let fullUrl = req.headers.host + req.originalUrl;
console.log("full url ==> ",fullUrl);
}
Thank you all for this information. This is incredibly annoying.
Add this to your code and you'll never have to think about it again:
var app = express();
app.all("*", function (req, res, next) { // runs on ALL requests
req.fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl
next()
})
You can do or set other things there as well, such as log to console.
You can combine req.protocol
, req.hostname
, and req.originalUrl
. Note req.hostname
rather than req.host
or req.get("host")
which works but is harder to read.
const completeUrl = `${req.protocol}://${req.hostname}${req.originalUrl}`;
async function (request, response, next) {
const url = request.rawHeaders[9] + request.originalUrl;
//or
const url = request.headers.host + request.originalUrl;
}
I tried to just logged all the data for req
then I found that logging rawHeaders and found all the data available in the url
and I tried this
app.post("/news-letter", (req,res) => {
console.log(req.body);
res.redirect(req.rawHeaders[33]);
})
Usually I rely on these 2, depends on the server and proxy exists:
req.socket.remoteAddress
req.headers.referer
const fullUrl = `${protocol}://${host}:${port}${url}`
const responseString = `Full URL is: ${fullUrl}`;
res.send(responseString);
})
Simply put it in .env
where .env file is ignored by .gitignore so for each server environment you'll be having different .env with host string of that server in it
.env code
HOSTNAME=example.com
file where you want hotname.
const dotenv = require("dotenv");
dotenv.config();
console.log('hostname: '+process.env.HOSTNAME)
OUTPUT:
hostname: example.com
Success story sharing
req.get('Host')
instead ofreq.host
which gives the host plus the port section.host
parameter in the request headers can be spoofed. There's a possible "host header attack" if using theres.host
this way. In the Django framework they have an 'allowed hosts' variable that is used to prevent such attack. I use a configuration variable that is myroot_url
which can be added to thereq.url
for completion. About the attack: skeletonscribe.net/2013/05/…req.originalUrl
without parameters, simply doreq.originalUrl.split("?").shift()
. Source: stackoverflow.com/a/32118818/2037431