Skip to content

Commit 399543d

Browse files
authored
Fix using multiple view instances in production mode (#476)
Include the property name in the cache key to avoid clashes when multiple view instances with different settings and root directories are registered. Signed-off-by: Dagfinn Ilmari Mannsåker <[email protected]>
1 parent c7f1cb0 commit 399543d

File tree

6 files changed

+55
-9
lines changed

6 files changed

+55
-9
lines changed

index.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ async function fastifyView (fastify, opts) {
187187
return result
188188
}
189189

190+
function getCacheKey (key) {
191+
return [propertyName, key].join('|')
192+
}
193+
190194
function getDefaultExtension (type) {
191195
const mappedExtensions = {
192196
handlebars: 'hbs',
@@ -223,7 +227,7 @@ async function fastifyView (fastify, opts) {
223227
if (type === 'handlebars') {
224228
data = engine.compile(data, globalOptions.compileOptions)
225229
}
226-
fastify[viewCache].set(file, data)
230+
fastify[viewCache].set(getCacheKey(file), data)
227231
return data
228232
}
229233

@@ -238,7 +242,7 @@ async function fastifyView (fastify, opts) {
238242
isRaw = true
239243
file = file.raw
240244
}
241-
const data = fastify[viewCache].get(file)
245+
const data = fastify[viewCache].get(getCacheKey(file))
242246
if (data && prod) {
243247
return data
244248
}
@@ -270,7 +274,7 @@ async function fastifyView (fastify, opts) {
270274
}
271275

272276
function getPartialsCacheKey (page, partials, requestedPath) {
273-
let cacheKey = page
277+
let cacheKey = getCacheKey(page)
274278

275279
for (const key of Object.keys(partials)) {
276280
cacheKey += `|${key}:${partials[key]}`
@@ -295,7 +299,7 @@ async function fastifyView (fastify, opts) {
295299

296300
const compiledPage = engine.compile(html, localOptions)
297301

298-
fastify[viewCache].set(page, compiledPage)
302+
fastify[viewCache].set(getCacheKey(page), compiledPage)
299303
return compiledPage
300304
}
301305

@@ -345,7 +349,7 @@ async function fastifyView (fastify, opts) {
345349
// append view extension
346350
page = getPage(page, type)
347351
}
348-
const toHtml = fastify[viewCache].get(page)
352+
const toHtml = fastify[viewCache].get(getCacheKey(page))
349353

350354
if (toHtml && prod) {
351355
return toHtml(data)
@@ -376,7 +380,7 @@ async function fastifyView (fastify, opts) {
376380
// append view extension
377381
page = getPage(page, type)
378382
}
379-
const toHtml = fastify[viewCache].get(page)
383+
const toHtml = fastify[viewCache].get(getCacheKey(page))
380384

381385
if (toHtml && prod) {
382386
return toHtml(data)
@@ -630,7 +634,7 @@ async function fastifyView (fastify, opts) {
630634
}
631635

632636
function hasAccessToLayoutFile (fileName, ext) {
633-
const layoutKey = `layout-${fileName}-${ext}`
637+
const layoutKey = getCacheKey(`layout-${fileName}-${ext}`)
634638
let result = fastify[viewCache].get(layoutKey)
635639

636640
if (typeof result === 'boolean') {

templates/root-bar/body.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
body bar

templates/root-bar/index.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Index bar {{> body}}

templates/root-foo/body.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
body foo

templates/root-foo/index.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Index foo {{> body}}

test/test-handlebars.js

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -597,10 +597,10 @@ test('reply.view with handlebars engine with partials in production mode should
597597
const POV = require('..')
598598
fastify.decorate(POV.fastifyViewCache, {
599599
get: (key) => {
600-
t.assert.strictEqual(key, 'handlebars|body:./templates/body.hbs|null-Partials')
600+
t.assert.strictEqual(key, 'view|handlebars|body:./templates/body.hbs|null-Partials')
601601
},
602602
set: (key, value) => {
603-
t.assert.strictEqual(key, 'handlebars|body:./templates/body.hbs|null-Partials')
603+
t.assert.strictEqual(key, 'view|handlebars|body:./templates/body.hbs|null-Partials')
604604
t.assert.deepStrictEqual(value, { body: fs.readFileSync('./templates/body.hbs', 'utf8') })
605605
}
606606
})
@@ -1019,6 +1019,44 @@ test('fastify.view with handlebars engine and callback in production mode and he
10191019
await fastify.close()
10201020
})
10211021

1022+
test('reply.view with multiple handlebars instances in production mode', async t => {
1023+
t.plan(8)
1024+
const fastify = Fastify()
1025+
const handlebars = require('handlebars')
1026+
1027+
const view = require('../index')
1028+
for (const name of ['foo', 'bar']) {
1029+
fastify.register(view, {
1030+
propertyName: name,
1031+
engine: {
1032+
handlebars: handlebars.create(),
1033+
},
1034+
root: `./templates/root-${name}`,
1035+
options: {
1036+
partials: { body: 'body.hbs' },
1037+
},
1038+
production: true,
1039+
})
1040+
1041+
fastify.get(`/${name}`, (_req, reply) => {
1042+
reply.header('Content-Type', 'text/plain')[name]('index.hbs', null)
1043+
})
1044+
}
1045+
1046+
await fastify.listen({ port: 0 })
1047+
t.after(() => fastify.close())
1048+
1049+
for (const name of ['foo', 'bar']) {
1050+
const result = await fetch(`http://127.0.0.1:${fastify.server.address().port}/${name}`)
1051+
const responseContent = await result.text()
1052+
1053+
t.assert.strictEqual(result.status, 200)
1054+
t.assert.strictEqual(result.headers.get('content-length'), '' + responseContent.length)
1055+
t.assert.strictEqual(result.headers.get('content-type'), 'text/plain')
1056+
t.assert.strictEqual(responseContent, `Index ${name} body ${name}\n\n`)
1057+
}
1058+
})
1059+
10221060
test('fastify.view with handlebars engine and both layout', async t => {
10231061
t.plan(1)
10241062
const fastify = Fastify()

0 commit comments

Comments
 (0)