diff --git a/README.md b/README.md index 63c6a6b..1fc49cd 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ For `POST`, call `get.post` or use option `{ method: 'POST' }`. const get = require('simple-get') const opts = { - url: 'http://example.com', + href: 'http://example.com', body: 'this is the POST body' } get.post(opts, function (err, res) { @@ -85,7 +85,7 @@ get.post(opts, function (err, res) { const get = require('simple-get') get({ - url: 'http://example.com', + href: 'http://example.com', method: 'POST', body: 'this is the POST body', @@ -121,7 +121,7 @@ const get = require('simple-get') const opts = { method: 'POST', - url: 'http://example.com', + href: 'http://example.com', body: { key: 'value' }, @@ -143,7 +143,7 @@ will fail with an `Error`. const get = require('simple-get') const opts = { - url: 'http://example.com', + href: 'http://example.com', timeout: 2000 // 2 second timeout } @@ -176,7 +176,7 @@ const get = require('simple-get') const tunnel = require('tunnel') const opts = { - url: 'http://example.com', + href: 'http://example.com', agent: tunnel.httpOverHttp({ proxy: { host: 'localhost' @@ -197,7 +197,7 @@ const get = require('simple-get') const cookie = require('cookie') const opts = { - url: 'http://example.com', + href: 'http://example.com', headers: { cookie: cookie.serialize('foo', 'bar') } @@ -220,7 +220,7 @@ const form = new FormData() form.append('my_file', fs.createReadStream('/foo/bar.jpg')) const opts = { - url: 'http://example.com', + href: 'http://example.com', body: form } @@ -233,7 +233,7 @@ get.post(opts, function (err, res) {}) const get = require('simple-get') const opts = { - url: 'http://example.com', + href: 'http://example.com', form: { key: 'value' } @@ -247,7 +247,7 @@ get.post(opts, function (err, res) {}) const get = require('simple-get') const opts = { - url: 'http://example.com/will-redirect-elsewhere', + href: 'http://example.com/will-redirect-elsewhere', followRedirects: false } // res.statusCode will be 301, no error thrown @@ -295,7 +295,7 @@ const token = { const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json' const opts = { - url: url, + href: url, headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)), json: true } @@ -316,7 +316,7 @@ const get = (opts, cb) => limiter.removeTokens(1, () => simpleGet(opts, cb)) get.concat = (opts, cb) => limiter.removeTokens(1, () => simpleGet.concat(opts, cb)) var opts = { - url: 'http://example.com' + href: 'http://example.com' } get.concat(opts, processResult) diff --git a/index.js b/index.js index 80e52e8..ab46465 100644 --- a/index.js +++ b/index.js @@ -6,21 +6,22 @@ const decompressResponse = require('decompress-response') // excluded from brows const http = require('http') const https = require('https') const once = require('once') -const querystring = require('querystring') -const url = require('url') const isStream = o => o !== null && typeof o === 'object' && typeof o.pipe === 'function' function simpleGet (opts, cb) { - opts = Object.assign({ maxRedirects: 10 }, typeof opts === 'string' ? { url: opts } : opts) + opts = Object.assign({ maxRedirects: 10 }, typeof opts === 'string' ? { href: opts } : opts) cb = once(cb) - if (opts.url) { - const { hostname, port, protocol, auth, path } = url.parse(opts.url) // eslint-disable-line node/no-deprecated-api - delete opts.url - if (!hostname && !port && !protocol && !auth) opts.path = path // Relative redirect - else Object.assign(opts, { hostname, port, protocol, auth, path }) // Absolute redirect - } + if (opts.auth) throw new Error('simple-get: opts.auth has been removed in favour of opts.username and opts.password') + if (opts.path) throw new Error('simple-get: opts.path has been removed in favour of opts.pathname') + if (opts.url) throw new Error('simple-get: opts.url has been removed in favour of opts.href') + + const url = new URL(opts.href || '', 'http://localhost'); delete opts.href + ;['hash', 'host', 'hostname', 'origin', 'password', 'pathname', 'port', 'protocol', 'search', 'searchParams', 'username'].forEach(key => { + if (opts[key]) url[key] = opts[key] + delete opts[key] + }) const headers = { 'accept-encoding': 'gzip, deflate' } if (opts.headers) Object.keys(opts.headers).forEach(k => (headers[k.toLowerCase()] = opts.headers[k])) @@ -30,7 +31,7 @@ function simpleGet (opts, cb) { if (opts.body) { body = opts.json && !isStream(opts.body) ? JSON.stringify(opts.body) : opts.body } else if (opts.form) { - body = typeof opts.form === 'string' ? opts.form : querystring.stringify(opts.form) + body = typeof opts.form === 'string' ? opts.form : new URLSearchParams(opts.form).toString() opts.headers['content-type'] = 'application/x-www-form-urlencoded' } @@ -44,17 +45,16 @@ function simpleGet (opts, cb) { if (opts.json) opts.headers.accept = 'application/json' if (opts.method) opts.method = opts.method.toUpperCase() - const originalHost = opts.hostname // hostname before potential redirect - const protocol = opts.protocol === 'https:' ? https : http // Support http/https urls - const req = protocol.request(opts, res => { + const protocol = url.protocol === 'https:' ? https : http // Support http/https urls + const req = protocol.request(url, opts, res => { if (opts.followRedirects !== false && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { - opts.url = res.headers.location // Follow 3xx redirects + const target = new URL(res.headers.location, url) // Follow 3xx redirects + opts.href = target.href delete opts.headers.host // Discard `host` header on redirect (see #32) res.resume() // Discard response - const redirectHost = url.parse(opts.url).hostname // eslint-disable-line node/no-deprecated-api // If redirected host is different than original host, drop headers to prevent cookie leak (#73) - if (redirectHost !== null && redirectHost !== originalHost) { + if (target.hostname !== url.hostname) { delete opts.headers.cookie delete opts.headers.authorization } @@ -102,7 +102,7 @@ simpleGet.concat = (opts, cb) => { ;['get', 'post', 'put', 'patch', 'head', 'delete'].forEach(method => { simpleGet[method] = (opts, cb) => { - if (typeof opts === 'string') opts = { url: opts } + if (typeof opts === 'string') opts = { href: opts } return simpleGet(Object.assign({ method: method.toUpperCase() }, opts), cb) } }) diff --git a/package.json b/package.json index 71e96c0..f8193df 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "tape": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=10.9" }, "files": [ "index.js" diff --git a/test/auth.js b/test/auth.js index 9878351..1efc92f 100644 --- a/test/auth.js +++ b/test/auth.js @@ -37,7 +37,7 @@ test('basic auth + host', function (t) { server.listen(0, function () { const port = server.address().port - get({ auth: 'foo:bar', host: 'localhost', port }, function (err, res) { + get({ username: 'foo', password: 'bar', host: 'localhost:' + port }, function (err, res) { t.error(err) t.equal(res.statusCode, 200) concat(res, function (err, data) { @@ -60,7 +60,7 @@ test('basic auth + hostname', function (t) { server.listen(0, function () { const port = server.address().port - get({ auth: 'foo:bar', hostname: 'localhost', port }, function (err, res) { + get({ username: 'foo', password: 'bar', hostname: 'localhost', port }, function (err, res) { t.error(err) t.equal(res.statusCode, 200) concat(res, function (err, data) { diff --git a/test/basic.js b/test/basic.js index 8fd106b..afdcde7 100644 --- a/test/basic.js +++ b/test/basic.js @@ -39,7 +39,7 @@ test('https', function (t) { server.listen(0, function () { const port = server.address().port get({ - url: 'https://localhost:' + port + '/path', + href: 'https://localhost:' + port + '/path', rejectUnauthorized: false }, function (err, res) { t.error(err) @@ -66,7 +66,7 @@ test('simple get json', function (t) { server.listen(0, function () { const port = server.address().port const opts = { - url: 'http://localhost:' + port + '/path', + href: 'http://localhost:' + port + '/path', json: true } get(opts, function (err, res) { @@ -98,7 +98,7 @@ test('HEAD request', function (t) { const port = server.address().port const opts = { method: 'HEAD', - url: 'http://localhost:' + port + href: 'http://localhost:' + port } get.head(opts, function (err, res) { t.error(err) @@ -122,7 +122,7 @@ test('timeout option', function (t) { server.listen(0, function () { const port = server.address().port get({ - url: 'http://localhost:' + port + '/path', + href: 'http://localhost:' + port + '/path', timeout: 1000 }, function (err, res) { t.ok(err instanceof Error) @@ -157,7 +157,7 @@ test('rewrite POST redirects to GET', function (t) { const opts = { method: 'POST', body: '123', - url: 'http://localhost:' + port + href: 'http://localhost:' + port } get(opts, function (err, res) { t.error(err) @@ -182,7 +182,7 @@ test('simple get hostname + url', function (t) { server.listen(0, function () { const port = server.address().port - get({ host: 'localhost', port, url: '/path' }, function (err, res) { + get({ host: 'localhost', port, href: '/path' }, function (err, res) { t.error(err) t.equal(res.statusCode, 200) concat(res, function (err, data) { diff --git a/test/concat.js b/test/concat.js index 2bc22c9..94f2212 100644 --- a/test/concat.js +++ b/test/concat.js @@ -14,7 +14,7 @@ test('get.concat (post, stream body, and json option)', function (t) { server.listen(0, function () { const port = server.address().port const opts = { - url: 'http://localhost:' + port, + href: 'http://localhost:' + port, body: str('{"a": "b"}'), method: 'POST', json: true @@ -58,7 +58,7 @@ test('get.concat json', function (t) { server.listen(0, function () { const port = server.address().port const opts = { - url: 'http://localhost:' + port + '/path', + href: 'http://localhost:' + port + '/path', json: true } get.concat(opts, function (err, res, data) { @@ -80,7 +80,7 @@ test('get.concat json error', function (t) { server.listen(0, function () { const port = server.address().port const opts = { - url: 'http://localhost:' + port + '/path', + href: 'http://localhost:' + port + '/path', json: true } get.concat(opts, function (err, res, data) { diff --git a/test/headers.js b/test/headers.js index ac51f81..2c5778d 100644 --- a/test/headers.js +++ b/test/headers.js @@ -17,7 +17,7 @@ test('custom headers', function (t) { server.listen(0, function () { const port = server.address().port get({ - url: 'http://localhost:' + port, + href: 'http://localhost:' + port, headers: { 'custom-header': 'custom-value' } diff --git a/test/post.js b/test/post.js index b0ae806..611fc1b 100644 --- a/test/post.js +++ b/test/post.js @@ -17,7 +17,7 @@ test('post (text body)', function (t) { server.listen(0, function () { const port = server.address().port const opts = { - url: 'http://localhost:' + port, + href: 'http://localhost:' + port, body: 'this is the body' } get.post(opts, function (err, res) { @@ -44,7 +44,7 @@ test('post (utf-8 text body)', function (t) { server.listen(0, function () { const port = server.address().port const opts = { - url: 'http://localhost:' + port, + href: 'http://localhost:' + port, body: 'jedan dva tri Ĩetiri' } get.post(opts, function (err, res) { @@ -71,7 +71,7 @@ test('post (buffer body)', function (t) { server.listen(0, function () { const port = server.address().port const opts = { - url: 'http://localhost:' + port, + href: 'http://localhost:' + port, body: Buffer.from('this is the body') } get.post(opts, function (err, res) { @@ -99,7 +99,7 @@ test('post (stream body)', function (t) { server.listen(0, function () { const port = server.address().port const opts = { - url: 'http://localhost:' + port, + href: 'http://localhost:' + port, body: str('this is the body') } get.post(opts, function (err, res) { @@ -128,7 +128,7 @@ test('post (json body)', function (t) { const port = server.address().port const opts = { method: 'POST', - url: 'http://localhost:' + port, + href: 'http://localhost:' + port, body: { message: 'this is the body' }, @@ -160,7 +160,7 @@ test('post (form, object)', function (t) { const port = server.address().port const opts = { method: 'POST', - url: 'http://localhost:' + port, + href: 'http://localhost:' + port, form: formData } get.concat(opts, function (err, res, data) { @@ -188,7 +188,7 @@ test('post (form, querystring)', function (t) { const port = server.address().port const opts = { method: 'POST', - url: 'http://localhost:' + port, + href: 'http://localhost:' + port, form: formData } get.concat(opts, function (err, res, data) { diff --git a/test/redirect.js b/test/redirect.js index 19458f8..6a0ea63 100644 --- a/test/redirect.js +++ b/test/redirect.js @@ -50,7 +50,7 @@ test('do not follow redirects', function (t) { server.listen(0, function () { const port = server.address().port get({ - url: 'http://localhost:' + port + '/0', + href: 'http://localhost:' + port + '/0', maxRedirects: 0 }, function (err) { t.ok(err instanceof Error, 'got error') @@ -73,7 +73,7 @@ test('do not follow redirects and do not error', function (t) { server.listen(0, function () { const port = server.address().port get({ - url: 'http://localhost:' + port + '/0', + href: 'http://localhost:' + port + '/0', followRedirects: false }, function (err, res) { t.ok(!err, 'got no error') @@ -134,7 +134,7 @@ test('redirect https to http', function (t) { httpServer.listen(0, function () { httpPort = httpServer.address().port get({ - url: 'https://localhost:' + httpsPort + '/path1', + href: 'https://localhost:' + httpsPort + '/path1', rejectUnauthorized: false }, function (err, res) { t.error(err) @@ -174,7 +174,7 @@ test('redirect http to https', function (t) { httpsServer.listen(0, function () { httpsPort = httpsServer.address().port get({ - url: 'http://localhost:' + httpPort + '/path1', + href: 'http://localhost:' + httpPort + '/path1', rejectUnauthorized: false }, function (err, res) { t.error(err) @@ -260,7 +260,7 @@ test('redirect should clear explicitly specified `host` header', function (t) { server2.listen(0, function () { port2 = server2.address().port get({ - url: `http://localhost:${port1}/path1`, + href: `http://localhost:${port1}/path1`, // Explicitly specify a `Host` header, so it won't be set automatically headers: { host: `localhost:${port1}` @@ -308,7 +308,7 @@ test('redirect should clear explicitly specified `Host` (note uppercase) header' server2.listen(0, function () { port2 = server2.address().port get({ - url: `http://localhost:${port1}/path1`, + href: `http://localhost:${port1}/path1`, // Explicitly specify a `Host` header, so it won't be set automatically headers: { Host: `localhost:${port1}` @@ -347,7 +347,7 @@ test('follow redirects without "url" option', function (t) { server.listen(0, function () { const port = server.address().port - get({ hostname: 'localhost', port, path: '/0' }, function (err, res) { + get({ hostname: 'localhost', port, pathname: '/0' }, function (err, res) { t.error(err) t.equal(res.statusCode, 200) concat(res, function (err, data) {