Skip to content
/ vault Public

A simple tool to embed resource files into a go binary.

License

Notifications You must be signed in to change notification settings

go-sharp/vault

Repository files navigation

Vault

Vault is a simple tool to embed resource and asset files into a go binary. It generates go source files containing encoded and compressed resource files. The generated source code provides an api to retrieve the embedded resources without any additional dependencies and therefore the vault package is only needed to generate those source files.

Requirements

go 1.9.7+

Installation

Install tool with go get:

go get -u github.com/go-sharp/vault/vault-cli

Usage

Assuming a project folder like this:

webapp
    |- dist
    |   |- js
    |   |   |- app.js
    |   |   '- moment.js
    |   |- css
    |   |   '- app.css
    |   |- index.html
    |   '- bg.jpeg
    |- handlers.go
    |- models.go
    '- main.go

Generating embedded resources

#vault-cli [options] source destination
 vault-cli ./dist ./res

This command will generate source files containing index.html and bg.jpeg as resources. Now the project folder looks like this:

webapp
    |- dist
    |   |- js
    |   |   |- app.js
    |   |   '- moment.js
    |   |- css
    |   |   '- app.css
    |   |- index.html
    |   '- bg.jpeg
    |- res
    |   |- debug_dist_vault.go
    |   |- release_dist_vault.go
    |   '- shared_dist_vault.go
    |- handlers.go
    |- models.go
    '- main.go

To include files in subdirectories use the -s flag.

Include / Exclude files

Use the -i and -e flags to include or exclude files. Both flags expecting a regular expression as input (see regexp) and can be specified multiple times.

Include only specified files
vault-cli -s -i "[.]js$" -i "[.]html$" ./dist ./res

This will include only app.js, moment.js and index.html.

Exclude files
vault-cli -s -e "app.js$" - ./dist ./res

This will include all files except app.js. It is also possible to use both flags, so one could define a more general include pattern and then exclude some specific files. For example:

vault-cli -s -i "[.]js$" -e "test[.]js$" - ./dist ./res

This will include all javascript files but exclude test files.

Compression

Per default all included files will be compressed. If required, compression can be disabled with the -no-comp flag.

Go generate

The most straight forward way to invoke the vault-cli is to use the go:generate directive in the main.go file.

//go:generate vault-cli -s ./dist ./res

Then invoke the go generate command to generate the resource files.

Use the resource file

Create and use the asset loader in your program as shown below:

package main

import (
    "fmt"
    "log"

    "github.com/example/webapp/res"
)

func main() {
    // Create a loader (default: New{source folder name}Loader() -> can be changed with ResourceNameOption)
    loader := res.NewDistLoader()
    f, err := loader.Open("/bg.jpg")
    if err != nil {
        log.Fatalln(err)
    }

    // Check for error omitted, but you definitely should check for errors.
    defer f.Close()

    // Read content
    data, err := ioutil.ReadAll(f)
    if err != nil {
       log.Fatalln(err)
    }


    // Write content to a file
    if err := ioutil.WriteFile("bg.jpg", data, 0755); err != nil {
        log.Fatalln(err)
    }

    f2, err := loader.Open("/js/app.js")
    if err != nil {
        log.Fatalln(err)
    }

    // Check for error omitted, but you definitely should check for errors.
    defer f2.Close()

     // Read content
    data, err = ioutil.ReadAll(f2)
    if err != nil {
       log.Fatalln(err)
    }

    // Write to console
    fmt.Println(data)
}

AssetLoader uses the relative path to the file within the source directory to lookup the file in the vault. The loader uses slashes / as path separator on all platforms (macOS, Linux and Windows).

The asset loader implements only one method:

// AssetLoader implements a function to load an asset from the vault
type AssetLoader interface {
	// Open loads a file from the vault.
	Open(name string) (File, error)
}

Load returns a file instance with the following interface (see http.File) or an error:

// File is the interface definition in the http package.
type File interface {
        io.Closer
        io.Reader
        io.Seeker
        Readdir(count int) ([]os.FileInfo, error)
        Stat() (os.FileInfo, error)
}

Use Loader in the http.FileServer handler

The asset loader implements the http.FileSystem interface and can be used with the http.FileServer handler. Just pass the loader to the FileServer function as follows:

http.Handle("/", http.FileServer(res.NewDistLoader()))

Development Mode

Run or build a program with go run -tags debug main.go to enable the development mode. In development mode the loader bypasses the embedded files and reads directly from the source directory. Therefore it is important to run the program in the same folder as the vault-cli tool was invoked. Otherwise invoke vault-cli with the flag -rp and specify the relative path to the source directory from the directory where the program will be executed. For example (folder structure as above):

# WorkingDir WebApp/dist
$~/workspace/src/webapp/dist> vault-cli -s -rp "./dist" ./ ../res
# WorkingDir  WebApp
$~/workspace/src/webapp> go run -tags debug main.go

A simple webapp example

See Example folder

License

This software is licensed under the MIT License.