| | |
| | | const isUnixSocket = parsedUrl.protocol === 'ws+unix:'; |
| | | |
| | | if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) { |
| | | throw new Error(`Invalid URL: ${websocket.url}`); |
| | | const err = new Error(`Invalid URL: ${websocket.url}`); |
| | | |
| | | if (websocket._redirects === 0) { |
| | | throw err; |
| | | } else { |
| | | emitErrorAndClose(websocket, err); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | const isSecure = |
| | |
| | | opts.path = parts[1]; |
| | | } |
| | | |
| | | if (opts.followRedirects) { |
| | | if (websocket._redirects === 0) { |
| | | websocket._originalHost = parsedUrl.host; |
| | | |
| | | const headers = options && options.headers; |
| | | |
| | | // |
| | | // Shallow copy the user provided options so that headers can be changed |
| | | // without mutating the original object. |
| | | // |
| | | options = { ...options, headers: {} }; |
| | | |
| | | if (headers) { |
| | | for (const [key, value] of Object.entries(headers)) { |
| | | options.headers[key.toLowerCase()] = value; |
| | | } |
| | | } |
| | | } else if (parsedUrl.host !== websocket._originalHost) { |
| | | // |
| | | // Match curl 7.77.0 behavior and drop the following headers. These |
| | | // headers are also dropped when following a redirect to a subdomain. |
| | | // |
| | | delete opts.headers.authorization; |
| | | delete opts.headers.cookie; |
| | | delete opts.headers.host; |
| | | opts.auth = undefined; |
| | | } |
| | | |
| | | // |
| | | // Match curl 7.77.0 behavior and make the first `Authorization` header win. |
| | | // If the `Authorization` header is set, then there is nothing to do as it |
| | | // will take precedence. |
| | | // |
| | | if (opts.auth && !options.headers.authorization) { |
| | | options.headers.authorization = |
| | | 'Basic ' + Buffer.from(opts.auth).toString('base64'); |
| | | } |
| | | } |
| | | |
| | | let req = (websocket._req = get(opts)); |
| | | |
| | | if (opts.timeout) { |
| | |
| | | if (req === null || req.aborted) return; |
| | | |
| | | req = websocket._req = null; |
| | | websocket._readyState = WebSocket.CLOSING; |
| | | websocket.emit('error', err); |
| | | websocket.emitClose(); |
| | | emitErrorAndClose(websocket, err); |
| | | }); |
| | | |
| | | req.on('response', (res) => { |
| | |
| | | |
| | | req.abort(); |
| | | |
| | | const addr = new URL(location, address); |
| | | let addr; |
| | | |
| | | try { |
| | | addr = new URL(location, address); |
| | | } catch (err) { |
| | | emitErrorAndClose(websocket, err); |
| | | return; |
| | | } |
| | | |
| | | initAsClient(websocket, addr, protocols, options); |
| | | } else if (!websocket.emit('unexpected-response', req, res)) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Emit the `'error'` and `'close'` event. |
| | | * |
| | | * @param {WebSocket} websocket The WebSocket instance |
| | | * @param {Error} The error to emit |
| | | * @private |
| | | */ |
| | | function emitErrorAndClose(websocket, err) { |
| | | websocket._readyState = WebSocket.CLOSING; |
| | | websocket.emit('error', err); |
| | | websocket.emitClose(); |
| | | } |
| | | |
| | | /** |
| | | * Create a `net.Socket` and initiate a connection. |
| | | * |
| | | * @param {Object} options Connection options |