URIs identify and URLs locate; however, locators are also identifiers, so every URL is also a URI, but there are URIs which are not URLs.
Examples
This is my name, which is an identifier.
It is like a URI, but cannot be a URL, as it tells you nothing about my location or how to contact me.
In this case it also happens to identify at least 5 other people in the USA alone.
- 4914 West Bay Street, Nassau, Bahamas
This is a locator, which is an identifier for that physical location.
It is like both a URL and URI (since all URLs are URIs), and also identifies me indirectly as "resident of..".
In this case it uniquely identifies me, but that would change if I get a roommate.
I say "like" because these examples do not follow the required syntax.
Popular confusion
From Wikipedia:
In computing, a Uniform Resource Locator (URL) is a subset of the Uniform Resource Identifier (URI) that specifies where an identified resource is available and the mechanism for retrieving it. In popular usage and in many technical documents and verbal discussions it is often incorrectly used as a synonym for URI, ... [emphasis mine]
Because of this common confusion, many products and documentation incorrectly use one term instead of the other, assign their own distinction, or use them synonymously.
URNs
My name, Roger Pate, could be like a URN (Uniform Resource Name), except those are much more regulated and intended to be unique across both space and time.
Because I currently share this name with other people, it's not globally unique and would not be appropriate as a URN. However, even if no other family used this name, I'm named after my paternal grandfather, so it still wouldn't be unique across time. And even if that wasn't the case, the possibility of naming my descendants after me make this unsuitable as a URN.
URNs are different from URLs in this rigid uniqueness constraint, even though they both share the syntax of URIs.
Best Answer
The protocol is available as
req.protocol
. docs herehttp
unless you see thatreq.get('X-Forwarded-Protocol')
is set and has the valuehttps
, in which case you know that's your protocolThe host comes from
req.get('host')
as Gopal has indicatedHopefully 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 soreq.get('host')
returnslocalhost: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), thehost
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 toreq.url
.Combine those all together to reconstruct the absolute URL.