Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Fix querystring encoding #1386

Merged
merged 1 commit into from Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 26 additions & 1 deletion index.js
Expand Up @@ -939,10 +939,35 @@ class HtmlWebpackPlugin {
* Encode each path component using `encodeURIComponent` as files can contain characters
* which needs special encoding in URLs like `+ `.
*
* Valid filesystem characters which need to be encoded for urls:
*
* # pound, % percent, & ampersand, { left curly bracket, } right curly bracket,
* \ back slash, < left angle bracket, > right angle bracket, * asterisk, ? question mark,
* blank spaces, $ dollar sign, ! exclamation point, ' single quotes, " double quotes,
* : colon, @ at sign, + plus sign, ` backtick, | pipe, = equal sign
*
* However the query string must not be encoded:
*
* fo:demonstration-path/very fancy+name.js?path=/home?value=abc&value=def#zzz
* ^ ^ ^ ^ ^ ^ ^ ^^ ^ ^ ^ ^ ^
* | | | | | | | || | | | | |
* encoded | | encoded | | || | | | | |
* ignored ignored ignored ignored ignored
*
* @param {string} filePath
*/
urlencodePath (filePath) {
return filePath.split('/').map(encodeURIComponent).join('/');
// People use the filepath in quite unexpected ways.
// Try to extract the first querystring of the url:
//
// some+path/demo.html?value=abc?def
//
const queryStringStart = filePath.indexOf('?');
const urlPath = queryStringStart === -1 ? filePath : filePath.substr(0, queryStringStart);
const queryString = filePath.substr(urlPath.length);
// Encode all parts except '/' which are not part of the querystring:
const encodedUrlPath = urlPath.split('/').map(encodeURIComponent).join('/');
return encodedUrlPath + queryString;
}

/**
Expand Down
12 changes: 12 additions & 0 deletions spec/basic.spec.js
Expand Up @@ -116,6 +116,18 @@ describe('HtmlWebpackPlugin', () => {
}, [/<body>[\s]*<script src="foo\/very%20fancy%2Bname.js"><\/script>[\s]*<\/body>/], null, done);
});

it('properly encodes file names in emitted URIs but keeps the querystring', done => {
testHtmlPlugin({
mode: 'production',
entry: path.join(__dirname, 'fixtures/index.js'),
output: {
path: OUTPUT_DIR,
filename: 'fo:o/very fancy+file-name.js?path=/home?value=abc&value=def#zzz'
},
plugins: [new HtmlWebpackPlugin()]
}, ['<script src="fo%3Ao/very%20fancy%2Bfile-name.js?path=/home?value=abc&value=def#zzz">'], null, done);
});

it('generates a default index.html file with multiple entry points', done => {
testHtmlPlugin({
mode: 'production',
Expand Down