diff --git a/packages/bruno-electron/src/ipc/network/axios-instance.js b/packages/bruno-electron/src/ipc/network/axios-instance.js index 22515648..26278599 100644 --- a/packages/bruno-electron/src/ipc/network/axios-instance.js +++ b/packages/bruno-electron/src/ipc/network/axios-instance.js @@ -1,5 +1,32 @@ +const URL = require('url'); +const Socket = require('net').Socket; const axios = require('axios'); +const getTld = (hostname) => { + if (!hostname) { + return ''; + } + + return hostname.substring(hostname.lastIndexOf('.') + 1); +}; + +const checkConnection = (host, port) => + new Promise((resolve) => { + const socket = new Socket(); + + socket.once('connect', () => { + socket.end(); + resolve(true); + }); + + socket.once('error', () => { + resolve(false); + }); + + // Try to connect to the host and port + socket.connect(port, host); + }); + /** * Function that configures axios with timing interceptors * Important to note here that the timings are not completely accurate. @@ -10,7 +37,22 @@ function makeAxiosInstance() { /** @type {axios.AxiosInstance} */ const instance = axios.create(); - instance.interceptors.request.use((config) => { + instance.interceptors.request.use(async (config) => { + const url = URL.parse(config.url); + + // Resolve all *.localhost to localhost and check if it should use IPv6 or IPv4 + // RFC: 6761 section 6.3 (https://tools.ietf.org/html/rfc6761#section-6.3) + // @see https://github.com/usebruno/bruno/issues/124 + if (getTld(url.hostname) === 'localhost') { + config.headers.Host = url.hostname; // Put original hostname in Host + + const portNumber = Number(url.port) || (url.protocol.includes('https') ? 443 : 80); + const useIpv6 = await checkConnection('::1', portNumber); + url.hostname = useIpv6 ? '::1' : '127.0.0.1'; + delete url.host; // Clear hostname cache + config.url = URL.format(url); + } + config.headers['request-start-time'] = Date.now(); return config; });