From f238adb134197f2856f28fa2cf16e35adc722f34 Mon Sep 17 00:00:00 2001 From: Lars Trieloff Date: Fri, 26 Apr 2019 10:23:27 +0000 Subject: [PATCH] fix(static): normalize URLs in rewritten CSS and JS --- static.js | 98 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/static.js b/static.js index 2c9c0b5d..f3f1dcf9 100644 --- a/static.js +++ b/static.js @@ -97,53 +97,54 @@ function isBinary(type) { return true; } -function rewriteImports(tree) { - tree.walkAtRules('import', (rule) => { - if (rule.name === 'import') { - const [url, queries] = space(rule.params); - const parsedurl = parser(url); - if (parsedurl.nodes - && parsedurl.nodes.length === 1 - && parsedurl.nodes[0].value === 'url' - && parsedurl.nodes[0].nodes - && parsedurl.nodes[0].nodes.length === 1 - && parsedurl.nodes[0].nodes[0].type === 'string' - && typeof parsedurl.nodes[0].nodes[0].value === 'string' - && typeof parsedurl.nodes[0].nodes[0].quote === 'string') { - const importuri = uri.parse(parsedurl.nodes[0].nodes[0].value); - const { quote } = parsedurl.nodes[0].nodes[0]; - if (importuri.reference === 'relative' && !importuri.query) { - rule.replaceWith(postcss.atRule({ - name: 'import', - params: `url(${quote}${importuri.path}${quote}) ${queries}`, - })); - } - } else if (parsedurl.nodes - && parsedurl.nodes[0].type === 'string' - && typeof parsedurl.nodes[0].value === 'string' - && typeof parsedurl.nodes[0].quote === 'string') { - const importuri = uri.parse(parsedurl.nodes[0].value); - const { quote } = parsedurl.nodes[0]; - if (importuri.reference === 'relative' && !importuri.query) { - rule.replaceWith(postcss.atRule({ - name: 'import', - params: `${quote}${importuri.path}${quote} ${queries}`, - })); +function rewriteCSS(css, base = '') { + function rewriteImports(tree) { + tree.walkAtRules('import', (rule) => { + if (rule.name === 'import') { + const [url, queries] = space(rule.params); + const parsedurl = parser(url); + if (parsedurl.nodes + && parsedurl.nodes.length === 1 + && parsedurl.nodes[0].value === 'url' + && parsedurl.nodes[0].nodes + && parsedurl.nodes[0].nodes.length === 1 + && parsedurl.nodes[0].nodes[0].type === 'string' + && typeof parsedurl.nodes[0].nodes[0].value === 'string' + && typeof parsedurl.nodes[0].nodes[0].quote === 'string') { + const importuri = uri.parse(parsedurl.nodes[0].nodes[0].value); + const { quote } = parsedurl.nodes[0].nodes[0]; + if (importuri.reference === 'relative' && !importuri.query) { + rule.replaceWith(postcss.atRule({ + name: 'import', + params: `url(${quote}${importuri.path}${quote}) ${queries}`, + })); + } + } else if (parsedurl.nodes + && parsedurl.nodes[0].type === 'string' + && typeof parsedurl.nodes[0].value === 'string' + && typeof parsedurl.nodes[0].quote === 'string') { + const importuri = uri.parse(parsedurl.nodes[0].value); + const { quote } = parsedurl.nodes[0]; + if (importuri.reference === 'relative' && !importuri.query) { + rule.replaceWith(postcss.atRule({ + name: 'import', + params: `${quote}${importuri.path}${quote} ${queries}`, + })); + } } } - } - }); - return tree; -} + }); + return tree; + } + -function rewriteCSS(css) { const processor = postcss() .use(rewriteImports) .use(postcssurl({ url: (asset) => { // TODO pass in request URL and make it absolute. if (asset.search === '' && asset.absolutePath !== '.' && asset.relativePath !== '.') { - return `${asset.relativePath}`; + return `${asset.relativePath}`; } return asset.url; }, @@ -151,7 +152,7 @@ function rewriteCSS(css) { return processor.process(css, { from: undefined }).then(result => result.css); } -function rewriteJavaScript(javascript) { +function rewriteJavaScript(javascript, base = '') { const importmap = {}; function rewriteJSImports(bab) { @@ -169,7 +170,7 @@ function rewriteJavaScript(javascript) { const { specifiers } = path.node; // console.log(srcuri); const h = ohash(srcuri.path); - importmap[h] = `${path.node.source.value}`; + importmap[h] = `${path.node.source.value}`; path.replaceWith(t.importDeclaration(specifiers, t.stringLiteral(h))); } } @@ -194,7 +195,7 @@ function isJSON(type) { return !!type.match(/json/); } -function getBody(type, responsebody, esi = false) { +function getBody(type, responsebody, esi = false, entry) { if (isBinary(type)) { return Buffer.from(responsebody).toString('base64'); } @@ -202,10 +203,10 @@ function getBody(type, responsebody, esi = false) { return JSON.parse(responsebody); } if (esi && isCSS(type)) { - return rewriteCSS(responsebody.toString()); + return rewriteCSS(responsebody.toString(), entry); } if (esi && isJavaScript(type)) { - return rewriteJavaScript(responsebody.toString()); + return rewriteJavaScript(responsebody.toString(), entry); } return responsebody.toString(); } @@ -229,6 +230,7 @@ function deliverPlain(owner, repo, ref, entry, root, esi = false) { const cleanentry = (`${root}/${entry}`).replace(/^\//, '').replace(/[/]+/g, '/'); console.log('deliverPlain()', owner, repo, ref, cleanentry); const url = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${cleanentry}`; + console.log(url); const rawopts = { url, headers: { @@ -243,14 +245,14 @@ function deliverPlain(owner, repo, ref, entry, root, esi = false) { const size = parseInt(response.headers['content-length'], 10); console.log('size', size); if (size < REDIRECT_LIMIT) { - const body = await getBody(type, response.body, esi); + const body = await getBody(type, response.body, esi, entry); console.log(`delivering file ${cleanentry} type ${type} binary: ${isBinary(type)}`); return { statusCode: 200, headers: addHeaders({ 'Content-Type': type, 'X-Static': 'Raw/Static', - 'X-ESI': esi ? 'enabled' : undefined + 'X-ESI': esi ? 'enabled' : undefined, }, ref, response.body), body, }; @@ -324,12 +326,14 @@ async function main({ }) { console.log('main()', owner, repo, ref, path, entry, strain, plain, allow, deny, root); - if (blacklisted(path, allow, deny) || blacklisted(entry, allow, deny)) { + const file = uri.normalize(entry); + console.log(file); + if (blacklisted(file, allow, deny) || blacklisted(file, allow, deny)) { return forbidden(); } if (plain) { - return deliverPlain(owner, repo, ref, entry, root, esi); + return deliverPlain(owner, repo, ref, file, root, esi); } return forbidden();