gofiber/template

๐Ÿ› [Bug]: When multiple files use the same layout and define the same template, the last file is rendered on any request (Go templates)

Closed this issue ยท 4 comments

Bug Description

I have to say this is a weird one. When using Go's template engine, only the last file in views/ get rendered. The file structure is as follows:

.
โ”œโ”€โ”€ views
โ”‚   โ”œโ”€โ”€ layouts
โ”‚   โ”‚   โ””โ”€โ”€ main.html
โ”‚   โ”œโ”€โ”€ index.html
โ”‚   โ””โ”€โ”€ z.html
โ””โ”€โ”€ main.go

where main.html contains the following (note that the bug arises even when not using {{ embed }}, but including the layout template with {{ template "views/layouts/main" }} in the index template):

<!DOCTYPE html>
<html>

<head>
  <title>Main</title>
</head>

<body>
  {{ embed }}

  {{ template "content" . }}
</body>

</html>

while index.html and z.html are simply

{{ define "content" }}
<div>This is index.html</div>
{{ end }}

and

{{ define "content" }}
<div>This is z.html</div>
{{ end }}

Running go run main.go results in the following:

image

Removing z.html or renaming it to something like a.html (so that index.html comes last in the file list) fixes the problem but that's not a solution. Fiber should render the requested template, not z.html (which should never even be served since it's never even mentioned in the handler).

I think something like this... bug? or whatever it is can be a security problem in some circumstances since it basically leaks template data.

How to Reproduce

Steps to reproduce the behavior:

  1. Run main.go
  2. Open browser
  3. Profit? Only the last template in the views/ folder is rendered.

Expected Behavior

Fiber should render the correct template instead of the last file in the folder.

Fiber Version

v2.39.0

Code Snippet (optional)

package main

import (
	"log"

	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/template/html"
)

func main() {
	engine := html.New("./views", ".html")

	app := fiber.New(fiber.Config{
		Views: engine,
	})

	app.Get("/", func(c *fiber.Ctx) error {
		return c.Render("index", nil, "layouts/main")
	})

	log.Fatal(app.Listen(":3000"))
}

Checklist:

  • I agree to follow Fiber's Code of Conduct.
  • I have checked for existing issues that describe my problem prior to opening this one.
  • I understand that improperly formatted bug reports may be closed without explanation.

Thanks for opening your first issue here! ๐ŸŽ‰ Be sure to follow the issue template! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord

This is known and an expected behavior

For performance reasons we parse all templates in the folder which would be specified in the view engine

So you should avoid creating definitions with the same names and use the embed tag

Thanks for the quick response! If it's for performance then I suppose I get it, but it should be documented because it's a project-specific decision and can generate a lot of confusion, not to add that it makes templates quite redundant because of the "same name renders the last one" thing. Thank you for your time anyways.

thanks for the feedback
c57f5fb