I have a Node.js-based deployment script for my application servers. One step in the deployment process is to validate that these application servers are listening on HTTPS correctly before registering them with DNS. To do that, I simply need to make an HTTPS request to that server's IP address.
If this were HTTP, it's a non-issue. I can make a HTTP GET
request for http://[2001:0db8::0370:7334]/
, and this will work. However, if I make an HTTPS GET request for https://[2001:0db8::0370:7334]/
, this will fail since the certificate is for a specific hostname like api.example.com
.
If I were testing manually, I would temporarily put the IP address in the hosts
file and cURL https://api.example.com
. However, in this automated process, I may be deploying several hosts at once so this isn't a solution for my deployment script.
How can I make an HTTPS request where I specify the hostname and IP address?
Perhaps there's some way to do this with a custom Agent?
I'm currently using node-fetch, but I'm happy to use whatever API is needed to make this work.
A host name is used when a web client makes an HTTP request to a host. The user making the request can specify the IP address of the server rather than the host name, but that is now unusual on the Internet. Host names are more convenient for users than numeric IP addresses.
To do this, we can use curl to query websites that are configured to do nothing more than return the IP address of whichever system is connecting to it. This is one of the quickest and easiest ways to get your public IP address on the Linux command line. Follow along with us below and we'll show you a few examples.
To do this in Chrome, simply open up the DevTools, navigate to the Network tab and select the site's HTML doc. You should then see the IP address associated with that URL under Headers > General > Remote Address.
If no connection can be reused, libcurl resolves the host name to the set of addresses it resolves to. Typically this means asking for both IPv4 and IPv6 addresses and there may be a whole set of those returned to libcurl. That set of addresses is then tried until one works, or it returns failure.
Set the host
header for the request:
const https = require('https');
https.get('https://AA.BB.CC.DD', {
headers : { host : 'api.example.com' }
}, res => {
console.log('okay');
}).on('error', e => {
console.log('E', e.message);
});
EDIT: I dug around a bit to see how this works exactly. To allow HTTPS-based virtual hosting, there's a TLS extension called SNI (Server Name Indication). This extension is used by a client to indicate the hostname to which it is trying to connect, so the server can pick the appropriate certificate that belongs to that hostname.
Node's tls
module, which is used by https
, has an option servername
to set this hostname:
https.get('https://AA.BB.CC.DD', {
servername : api.example.com'
}, ...)
However, you still need to pass a Host
header too (that's part of the regular HTTP protocol):
https.get('https://AA.BB.CC.DD', {
headers : { host : 'api.example.com' },
servername : 'api.example.com'
}, ...)
To keep things DRY, Node.js will set servername
to the Host
header, unless it's already set to something else (here).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With