Alexander Richey
Alexander Richey

Reputation: 174

Google App Engine is not finding files in go runtime

After adding a go.mod file, I am not able to access HTML template files from golang on App Engine. Everything works locally.

I have verified that the HTML files exist on App Engine using Stackdriver Debug, but the runtime is not seeing them. Here is the code I have.

var templates map[string]*htmltpl.Template

func init() {
    if templates == nil {
        templates = make(map[string]*htmltpl.Template)
    }

    templatesDir := getTemplatesDir()

    layouts, err := filepath.Glob(templatesDir + "/layouts/*.html")
    if err != nil {
        panic(err)
    }

    includes, err := filepath.Glob(templatesDir + "/includes/*.html")
    if err != nil {
        panic(err)
    }

    // Generate our templates map from our layouts/ and includes/ directories
    for _, layout := range layouts {
        files := append(includes, layout)
        templates[filepath.Base(layout)] = htmltpl.Must(htmltpl.ParseFiles(files...))
    }
}

func getTemplatesDir() string {
    _, filename, _, ok := runtime.Caller(1)
    if !ok {
        panic("Could not get filename")
    }
    dirpath := path.Join(path.Dir(filename), "../../templates")
    return dirpath
}

Here is my app.yaml:

runtime: go111

main: ./main

handlers:
  - url: .*
    script: auto
    secure: always

And here is my directory structure:

.
├── app.yaml
├── db/
├── go.mod
├── go.sum
├── handlers/
├── main
│   └── main.go
├── middleware/
├── models/
├── static/
├── templates/
│   ├── includes
│   │   ├── base.html
│   │   ├── button.html
│   │   ├── message.html
│   │   └── profile.html
│   └── layouts
│       └── thread.html
└── utils
    └── template
        └── template.go

I don't understand why, on App Engine, the call to filepath.Glob(templatesDir + "/layouts/*.html") returns an empty slice, whereas it returns a slice containing the path to thread.html when running locally.

Upvotes: 0

Views: 153

Answers (1)

Thundercat
Thundercat

Reputation: 120931

The function runtime.Caller() returns the compile time source file path. The application is not run in the same directory as where it was compiled.

The application runs with the current working directory set to the directory containing app.yaml. Use this function to get the templates directory:

func getTemplatesDir() string {
    return "templates"
}

Upvotes: 2

Related Questions