From 8aac53679d04ade28068bdec63488e35908717dd Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Thu, 22 Mar 2018 22:01:45 -0700 Subject: [PATCH] Fix custom Host header with arbitrary case (#430) Regression since 1592ca1148e657110fd6f64dc8b29a576cd1da1c. Fixes: #416 Fixes: #425 --- src/headers.js | 19 +++++++++++++++++++ src/index.js | 5 ----- src/request.js | 4 ++-- test/test.js | 14 ++++++++++++++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/headers.js b/src/headers.js index 80077e8..6b75371 100644 --- a/src/headers.js +++ b/src/headers.js @@ -323,6 +323,25 @@ Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { configurable: true }); +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +export function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + /** * Create a Headers object from an object of headers, ignoring those that do * not conform to HTTP grammar productions. diff --git a/src/index.js b/src/index.js index d395dad..c6d856e 100644 --- a/src/index.js +++ b/src/index.js @@ -43,11 +43,6 @@ export default function fetch(url, opts) { const send = (options.protocol === 'https:' ? https : http).request; - // http.request only support string as host header, this hack make custom host header possible - if (options.headers.host) { - options.headers.host = options.headers.host[0]; - } - // send request const req = send(options); let reqTimeout; diff --git a/src/request.js b/src/request.js index 108a6bf..fb06783 100644 --- a/src/request.js +++ b/src/request.js @@ -7,7 +7,7 @@ * All spec algorithm step numbers are based on https://fetch.spec.whatwg.org/commit-snapshots/ae716822cb3a61843226cd090eefc6589446c1d2/. */ -import Headers from './headers.js'; +import Headers, { exportNodeCompatibleHeaders } from './headers.js'; import Body, { clone, extractContentType, getTotalBytes } from './body'; const { format: format_url, parse: parse_url } = require('url'); @@ -200,7 +200,7 @@ export function getNodeRequestOptions(request) { return Object.assign({}, parsedURL, { method: request.method, - headers: headers.raw(), + headers: exportNodeCompatibleHeaders(headers), agent: request.agent }); } diff --git a/test/test.js b/test/test.js index 555446d..cca2e61 100644 --- a/test/test.js +++ b/test/test.js @@ -208,6 +208,20 @@ describe('node-fetch', () => { }); }); + it('should accept custom HoSt header', function() { + const url = `${base}inspect`; + const opts = { + headers: { + HoSt: 'example.com' + } + }; + return fetch(url, opts).then(res => { + return res.json(); + }).then(res => { + expect(res.headers['host']).to.equal('example.com'); + }); + }); + it('should follow redirect code 301', function() { const url = `${base}redirect/301`; return fetch(url).then(res => {