let host = req.headers.host
console.log(host)
Prints localhost:3000
. So far so good.
console.log(host === "localhost:3000")
Prints false
. Uh?
console.log(host.length)
console.log("localhost:3000".length)
Prints 15
and 14
. Our mystery string is one character longer? Let's look at each character one by one.
for (var i = 0; i < host.length; i ) {
console.log(i, host.charAt(i));
}
Prints:
0 l
1 o
2 c
3 a
4 l
5 h
6 o
7 s
8 t
9 :
10 6
11 0
12 6
13 4
14 3
Printing one character at a time reveals that there are now 5 digits after the colon: 60643
. Whaaat?
This result changes every time I restart my web server. For example, last run it was 63275
and the previous run was 54313
.
Adding console.log(host)
immediately after the for loop confirms the string is still localhost:3000
. What's going on here?
I almost feel crazy asking this question, but I've looked at it all day and this happens 100% of the time. Environment: latest version of Node (v17.3.0
), macOS Monterey (M1 mac).
Followups
- Reproducible example here (requires a free Vercel account)
typeof host
returnsstring
- Here's additional debugging information for each character of the string:
i |
charAt(i) |
charCodeAt(i) |
codePointAt(i).toString(16) |
---|---|---|---|
0 | l | 108 | 6c |
1 | o | 111 | 6f |
2 | c | 99 | 63 |
3 | a | 97 | 61 |
4 | l | 108 | 6c |
5 | h | 104 | 68 |
6 | o | 111 | 6f |
7 | s | 115 | 73 |
8 | t | 116 | 74 |
9 | : | 58 | 3a |
10 | 5 | 53 | 35 |
11 | 4 | 52 | 34 |
12 | 8 | 56 | 38 |
13 | 6 | 54 | 36 |
14 | 2 | 50 | 32 |
CodePudding user response:
According to the documentation:
The vercel dev command is used to replicate the Vercel deployment environment locally, allowing you to test your Serverless Functions, without requiring you to deploy each time a change is made.
For this reason, calls like /api/hello
are processed by local proxy server running with a random free port.
And here the most interesting thing begins: for the standard output (stdout) of the proxy server (and of course for the console.log
too), the proxy port is replaced with the development port (it feels like it's an outdated legacy):
p.stdout.on('data', (data: string) => {
process.stdout.write(data.replace(proxyPort, devPort));
});
For this reason, there is a difference in the length of the req.headers.host
and localhost:3000
, and why they look the same in the console.log
, but are not equal when compared.
So it's better for example to use x-forwarded-host
header instead of host
:
console.log((
req.headers['x-forwarded-host'] || req.headers.host
) === "localhost:3000");
res.status(200).json(req.headers);