mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-23 14:15:13 +00:00
fix: encoding issues with payload paths (#8738)
- fix(generator): decode full static filesystem paths - fix(vue-app): check decoded path against manifest - fix(vue-app): prevent double encoding for urls Co-authored-by: Pooya Parsa <pyapar@gmail.com>
This commit is contained in:
parent
f917297a70
commit
6a8339e4c4
@ -343,7 +343,7 @@ export default class Generator {
|
|||||||
// Save Static Assets
|
// Save Static Assets
|
||||||
if (this.staticAssetsDir && renderContext.staticAssets) {
|
if (this.staticAssetsDir && renderContext.staticAssets) {
|
||||||
for (const asset of renderContext.staticAssets) {
|
for (const asset of renderContext.staticAssets) {
|
||||||
const assetPath = path.join(this.staticAssetsDir, asset.path)
|
const assetPath = path.join(this.staticAssetsDir, decodeURI(asset.path))
|
||||||
await fsExtra.ensureDir(path.dirname(assetPath))
|
await fsExtra.ensureDir(path.dirname(assetPath))
|
||||||
await fsExtra.writeFile(assetPath, asset.src, 'utf-8')
|
await fsExtra.writeFile(assetPath, asset.src, 'utf-8')
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { parsePath, withoutTrailingSlash } from 'ufo'
|
import { parsePath, withoutTrailingSlash, normalizeURL } from 'ufo'
|
||||||
<% utilsImports = [
|
<% utilsImports = [
|
||||||
...(features.asyncData || features.fetch) ? [
|
...(features.asyncData || features.fetch) ? [
|
||||||
'getMatchedComponentsInstances',
|
'getMatchedComponentsInstances',
|
||||||
@ -317,7 +317,7 @@ export default {
|
|||||||
},
|
},
|
||||||
<% if (nuxtOptions.generate.manifest) { %>
|
<% if (nuxtOptions.generate.manifest) { %>
|
||||||
async fetchStaticManifest() {
|
async fetchStaticManifest() {
|
||||||
return window.__NUXT_IMPORT__('manifest.js', encodeURI(urlJoin(this.getStaticAssetsPath(), 'manifest.js')))
|
return window.__NUXT_IMPORT__('manifest.js', normalizeURL(urlJoin(this.getStaticAssetsPath(), 'manifest.js')))
|
||||||
},
|
},
|
||||||
<% } %>
|
<% } %>
|
||||||
setPagePayload(payload) {
|
setPagePayload(payload) {
|
||||||
@ -328,14 +328,14 @@ export default {
|
|||||||
<% if (nuxtOptions.generate.manifest) { %>
|
<% if (nuxtOptions.generate.manifest) { %>
|
||||||
const manifest = await this.fetchStaticManifest()
|
const manifest = await this.fetchStaticManifest()
|
||||||
const path = this.getRoutePath(route)
|
const path = this.getRoutePath(route)
|
||||||
if (!manifest.routes.includes(path)) {
|
if (!manifest.routes.includes(decodeURI(path))) {
|
||||||
if (!prefetch) { this.setPagePayload(false) }
|
if (!prefetch) { this.setPagePayload(false) }
|
||||||
throw new Error(`Route ${path} is not pre-rendered`)
|
throw new Error(`Route ${path} is not pre-rendered`)
|
||||||
}
|
}
|
||||||
<% } %>
|
<% } %>
|
||||||
const src = urlJoin(this.getStaticAssetsPath(route), 'payload.js')
|
const src = urlJoin(this.getStaticAssetsPath(route), 'payload.js')
|
||||||
try {
|
try {
|
||||||
const payload = await window.__NUXT_IMPORT__(decodeURI(route), encodeURI(src))
|
const payload = await window.__NUXT_IMPORT__(decodeURI(route), normalizeURL(src))
|
||||||
if (!prefetch) { this.setPagePayload(payload) }
|
if (!prefetch) { this.setPagePayload(payload) }
|
||||||
return payload
|
return payload
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import http from 'http'
|
import http from 'http'
|
||||||
import { resolve } from 'path'
|
import { join, resolve } from 'path'
|
||||||
import serveStatic from 'serve-static'
|
import serveStatic from 'serve-static'
|
||||||
import finalhandler from 'finalhandler'
|
import finalhandler from 'finalhandler'
|
||||||
|
import glob from 'glob'
|
||||||
import { Builder, Generator, getPort, loadFixture, Nuxt, rp } from '../utils'
|
import { Builder, Generator, getPort, loadFixture, Nuxt, rp } from '../utils'
|
||||||
|
|
||||||
let port
|
let port
|
||||||
@ -43,7 +44,21 @@ describe('full-static', () => {
|
|||||||
const { body: html } = await rp(url('/payload'))
|
const { body: html } = await rp(url('/payload'))
|
||||||
|
|
||||||
expect(html).toContain('<script src="https://cdn.nuxtjs.org/test/')
|
expect(html).toContain('<script src="https://cdn.nuxtjs.org/test/')
|
||||||
expect(html).toContain('<link rel="preload" href="https://cdn.nuxtjs.org/test/_nuxt/static/')
|
expect(html).toContain(
|
||||||
|
'<link rel="preload" href="https://cdn.nuxtjs.org/test/_nuxt/static/'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('/encoding/中文', async () => {
|
||||||
|
const { body: html } = await rp(url('/encoding/中文'))
|
||||||
|
|
||||||
|
const paths = ['encoding/中文/state.js', 'encoding/中文/payload.js']
|
||||||
|
|
||||||
|
paths.forEach((path) => {
|
||||||
|
const files = glob.sync(join(distDir, '**', path))
|
||||||
|
expect(html).toContain(encodeURI(path))
|
||||||
|
expect(files).toContainEqual(expect.stringContaining(path))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Close server and ask nuxt to stop listening to file changes
|
// Close server and ask nuxt to stop listening to file changes
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
<NLink to="/store">
|
<NLink to="/store">
|
||||||
Store
|
Store
|
||||||
</NLink>
|
</NLink>
|
||||||
|
<NLink to="/encoding/中文">
|
||||||
|
Encoding
|
||||||
|
</NLink>
|
||||||
<NLink to="/pagination/1">
|
<NLink to="/pagination/1">
|
||||||
Pagination
|
Pagination
|
||||||
</NLink>
|
</NLink>
|
||||||
|
5
test/fixtures/full-static/pages/encoding/中文.vue
vendored
Normal file
5
test/fixtures/full-static/pages/encoding/中文.vue
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>Encoded path</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
Loading…
Reference in New Issue
Block a user