fix: properly encode url with unicode characters (#1291)

* fix: properly encode url with unicode characters
* release: 2.6.3
This commit is contained in:
Linus Unnebäck 2021-09-20 16:09:10 +02:00 committed by GitHub
parent 152214ca2f
commit ace7536c95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 79 additions and 8 deletions

View File

@ -5,6 +5,10 @@ Changelog
# 2.x release # 2.x release
## v2.6.3
- Fix: properly encode url with unicode characters
## v2.6.2 ## v2.6.2
- Fix: used full filename for main in package.json - Fix: used full filename for main in package.json

View File

@ -1,6 +1,6 @@
{ {
"name": "node-fetch", "name": "node-fetch",
"version": "2.6.2", "version": "2.6.3",
"description": "A light-weight module that brings window.fetch to node.js", "description": "A light-weight module that brings window.fetch to node.js",
"main": "lib/index.js", "main": "lib/index.js",
"browser": "./browser.js", "browser": "./browser.js",
@ -36,6 +36,9 @@
"url": "https://github.com/bitinn/node-fetch/issues" "url": "https://github.com/bitinn/node-fetch/issues"
}, },
"homepage": "https://github.com/bitinn/node-fetch", "homepage": "https://github.com/bitinn/node-fetch",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"devDependencies": { "devDependencies": {
"@ungap/url-search-params": "^0.1.2", "@ungap/url-search-params": "^0.1.2",
"abort-controller": "^1.1.0", "abort-controller": "^1.1.0",
@ -60,7 +63,6 @@
"rollup": "^0.63.4", "rollup": "^0.63.4",
"rollup-plugin-babel": "^3.0.7", "rollup-plugin-babel": "^3.0.7",
"string-to-arraybuffer": "^1.0.2", "string-to-arraybuffer": "^1.0.2",
"teeny-request": "3.7.0", "teeny-request": "3.7.0"
"whatwg-url": "^5.0.0"
} }
} }

View File

@ -1,9 +1,12 @@
import isBuiltin from 'is-builtin-module'; import isBuiltin from 'is-builtin-module';
import babel from 'rollup-plugin-babel'; import babel from 'rollup-plugin-babel';
import packageJson from './package.json';
import tweakDefault from './build/rollup-plugin'; import tweakDefault from './build/rollup-plugin';
process.env.BABEL_ENV = 'rollup'; process.env.BABEL_ENV = 'rollup';
const dependencies = Object.keys(packageJson.dependencies);
export default { export default {
input: 'src/index.js', input: 'src/index.js',
output: [ output: [
@ -18,6 +21,6 @@ export default {
tweakDefault() tweakDefault()
], ],
external: function (id) { external: function (id) {
return isBuiltin(id); return dependencies.includes(id) || isBuiltin(id);
} }
}; };

View File

@ -9,6 +9,7 @@
import Url from 'url'; import Url from 'url';
import Stream from 'stream'; import Stream from 'stream';
import {URL} from 'whatwg-url';
import Headers, { exportNodeCompatibleHeaders } from './headers.js'; import Headers, { exportNodeCompatibleHeaders } from './headers.js';
import Body, { clone, extractContentType, getTotalBytes } from './body'; import Body, { clone, extractContentType, getTotalBytes } from './body';
@ -18,6 +19,39 @@ const INTERNALS = Symbol('Request internals');
const parse_url = Url.parse; const parse_url = Url.parse;
const format_url = Url.format; const format_url = Url.format;
/**
* Wrapper around `new URL` to handle arbitrary URLs
*
* @param {string} urlStr
* @return {void}
*/
function parseURL(urlStr) {
/*
Check whether the URL is absolute or not
Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
*/
if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) {
const url = new URL(urlStr);
return {
path: url.pathname,
pathname: url.pathname,
hostname: url.hostname,
protocol: url.protocol,
port: url.port,
hash: url.hash,
search: url.search,
query: url.query,
href: url.href,
}
}
// Fallback to old implementation for arbitrary URLs
return parse_url(urlStr);
}
const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; const streamDestructionSupported = 'destroy' in Stream.Readable.prototype;
/** /**
@ -59,14 +93,14 @@ export default class Request {
// in order to support Node.js' Url objects; though WHATWG's URL objects // in order to support Node.js' Url objects; though WHATWG's URL objects
// will fall into this branch also (since their `toString()` will return // will fall into this branch also (since their `toString()` will return
// `href` property anyway) // `href` property anyway)
parsedURL = parse_url(input.href); parsedURL = parseURL(input.href);
} else { } else {
// coerce input to a string before attempting to parse // coerce input to a string before attempting to parse
parsedURL = parse_url(`${input}`); parsedURL = parseURL(`${input}`);
} }
input = {}; input = {};
} else { } else {
parsedURL = parse_url(input.url); parsedURL = parseURL(input.url);
} }
let method = init.method || input.method || 'GET'; let method = init.method || input.method || 'GET';

View File

@ -32,7 +32,7 @@ export default class TestServer {
} }
router(req, res) { router(req, res) {
let p = parse(req.url).pathname; let p = decodeURIComponent(parse(req.url).pathname);
if (p === '/hello') { if (p === '/hello') {
res.statusCode = 200; res.statusCode = 200;
@ -384,6 +384,12 @@ export default class TestServer {
}); });
req.pipe(parser); req.pipe(parser);
} }
if (p === '/issues/1290/ひらがな') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Success');
}
} }
} }

View File

@ -2845,3 +2845,25 @@ describe('external encoding', () => {
}); });
}); });
}); });
describe('issue #1290', function() {
it('should handle escaped unicode in URLs', () => {
const url = `${base}issues/1290/%E3%81%B2%E3%82%89%E3%81%8C%E3%81%AA`;
return fetch(url).then((res) => {
expect(res.status).to.equal(200);
return res.text().then(result => {
expect(result).to.equal('Success');
});
});
});
it('should handle unicode in URLs', () => {
const url = `${base}issues/1290/ひらがな`;
return fetch(url).then((res) => {
expect(res.status).to.equal(200);
return res.text().then(result => {
expect(result).to.equal('Success');
});
});
});
});