go.rice is a Go package that makes working with resources such as html,js,css,images,templates, etc very easy.

Overview

go.rice

Build Status Godoc

go.rice is a Go package that makes working with resources such as html,js,css,images and templates easy. During development go.rice will load required files directly from disk. Upon deployment it's easy to add all resource files to a executable using the rice tool, without changing the source code for your package. go.rice provides methods to add resources to a binary in different scenarios.

What does it do

The first thing go.rice does is finding the correct absolute path for your resource files. Say you are executing a binary in your home directory, but your html-files are in $GOPATH/src/yourApplication/html-files. go.rice will lookup the correct path for that directory (relative to the location of yourApplication). All you have to do is include the resources using rice.FindBox("html-files").

This works fine when the source is available to the machine executing the binary, which is the case when installing the executable with go get or go install. But it does not work when you wish to provide a single binary without source. This is where the rice tool comes in. It analyses source code and finds call's to rice.FindBox(..). Then it adds the required directories to the executable binary, There are two strategies to do this. You can 'embed' the assets by generating go source code and then compile them into the executable binary, or you can 'append' the assets to the executable binary after compiling. In both cases the rice.FindBox(..) call detects the embedded or appended resources and load those, instead of looking up files from disk.

Installation

Use go get to install the package the rice tool.

go get github.com/GeertJohan/go.rice
go get github.com/GeertJohan/go.rice/rice

Package usage

Import the package: import "github.com/GeertJohan/go.rice"

Serving a static content folder over HTTP with a rice Box:

http.Handle("/", http.FileServer(rice.MustFindBox("http-files").HTTPBox()))
http.ListenAndServe(":8080", nil)

Serve a static content folder over HTTP at a non-root location:

box := rice.MustFindBox("cssfiles")
cssFileServer := http.StripPrefix("/css/", http.FileServer(box.HTTPBox()))
http.Handle("/css/", cssFileServer)
http.ListenAndServe(":8080", nil)

Note the trailing slash in /css/ in both the call to http.StripPrefix and http.Handle.

Loading a template:

// find a rice.Box
templateBox, err := rice.FindBox("example-templates")
if err != nil {
	log.Fatal(err)
}
// get file contents as string
templateString, err := templateBox.String("message.tmpl")
if err != nil {
	log.Fatal(err)
}
// parse and execute the template
tmplMessage, err := template.New("message").Parse(templateString)
if err != nil {
	log.Fatal(err)
}
tmplMessage.Execute(os.Stdout, map[string]string{"Message": "Hello, world!"})

Never call FindBox() or MustFindBox() from an init() function, as there is no guarantee the boxes are loaded at that time.

Calling FindBox and MustFindBox

Always call FindBox() or MustFindBox() with string literals e.g. FindBox("example"). Do not use string constants or variables. This will prevent the rice tool to fail with error Error: found call to rice.FindBox, but argument must be a string literal..

Tool usage

The rice tool lets you add the resources to a binary executable so the files are not loaded from the filesystem anymore. This creates a 'standalone' executable. There are multiple strategies to add the resources and assets to a binary, each has pro's and con's but all will work without requiring changes to the way you load the resources.

rice embed-go: Embed resources by generating Go source code

Execute this method before building. It generates a single Go source file called rice-box.go for each package. The generated go file contains all assets. The Go tool compiles this into the binary.

The downside with this option is that the generated go source file can become large, which may slow down compilation and requires more memory to compile.

Execute the following commands:

rice embed-go
go build

A Note on Symbolic Links: embed-go uses the os.Walk function from the standard library. The os.Walk function does not follow symbolic links. When creating a box, be aware that any symbolic links inside your box's directory are not followed. When the box itself is a symbolic link, the rice tool resolves its actual location before adding the contents.

rice append: Append resources to executable as zip file

This method changes an already built executable. It appends the resources as zip file to the binary. It makes compilation a lot faster. Using the append method works great for adding large assets to an executable binary.

A downside for appending is that it does not provide a working Seek method.

Run the following commands to create a standalone executable.

go build -o example
rice append --exec example

Help information

Run rice --help for information about all flags and subcommands.

You can use the --help flag on each sub-command. For example: rice append --help.

Order of precedence

When opening a new box, the rice.FindBox(..) tries to locate the resources in the following order:

  • embedded (generated as rice-box.go)
  • appended (appended to the binary executable after compiling)
  • 'live' from filesystem

License

This project is licensed under a Simplified BSD license. Please read the LICENSE file.

Package documentation

You will find package documentation at godoc.org/github.com/GeertJohan/go.rice.

Comments
  • Fails to locate box when cross-compiling in go 1.5

    Fails to locate box when cross-compiling in go 1.5

    When cross compiling using go 1.5 the resultant binary fails with:

    panic: could not locate box "../assets/templates"
    
    goroutine 1 [running]:
    github.com/GeertJohan/go%2erice.MustFindBox(0x820abdfc0, 0x13, 0x9)
        /go/src/github.com/GeertJohan/go.rice/box.go:110 +0x9a
    

    This is true for multiple target architectures. I've verified that it works fine when compiling natively on multiple targets.

    I'm using commit ada95a01c963696fb73320ee662195af68be81ae of this repository; this is the tip of master branch.

    I'm cross compiling with e.g. GOOS=linux GOARCH=arm GOARM=7 go build main.go

    Do you know what would be different about cross compiling vs compiling natively?

    opened by robdimsdale 24
  • Append shows zip exit status 3 on windows, but binary works as expected

    Append shows zip exit status 3 on windows, but binary works as expected

    On Windows 7, after executing

    $ rice append --exec app.exe
    

    I got this:

    Error setting zip offset: exit status 3
    

    However, the result binary did increase in size and it appears to contain the correct static files intended and works as expected.

    opened by paradite 23
  • fix

    fix "assignment count mismatch: 3 = 2"

    This fixes the "Assignment count mismatch: 3 = 2" compilation error introduced in 368fb46cb7fec929d69b5c865baa81b5598b3966

    Now the situation is back to what it was before that pull-request: the zip file does not get closed, but at least it compiles.

    Would you want me to create a wercker CI configuration so that the code is compiled and tested after each commit to master?

    opened by nwolff 12
  • Getting list of filenames in the box

    Getting list of filenames in the box

    A method like (*File).Readdirnames(n int) ([]string, error) would be helpful:

    box := rice.MustFindBox("html")
    names, _ := box.Readdirnames(-1)
    for _, name := range names {
        tmpl, err := template.New(name).Parse(box.MustString(name))
        ...
    }
    

    I can send a PR once details are agreed upon.

    opened by opennota 12
  • Add a Way to Retrive List of Files and Directories

    Add a Way to Retrive List of Files and Directories

    We are using rice at drone/drone. There are places where we have to process templates. We load the templates from the box and parse them in the init function. To accomplish this we need a massive list of files in the source code. It would be great if we can avoid this list. Would it be if I implemented a way to get a list of embedded file names and possibly directory names? Does anyone have any suggestions about the implementation?

    func(b *Box) Files() []string {
      //...
    }
    
    func(b *Box) Dirs() []string {
      //...
    }
    
    opened by 0xcaff 11
  • zip command is required for appending to binary

    zip command is required for appending to binary

    The proposed hack (https://github.com/tgulacsi/csv2pdf/commit/8b9f4289881940fa9b1879f213b1277d046a314e#) for "zip -A" replacement: https://github.com/tgulacsi/go/blob/master/zipA/main.go Iff acceptable, the inner workings can be refactored into a function/library.

    Another solution (not using unsafe) needs to copy archive/zip, and modify as needed.

    opened by tgulacsi 11
  • File does not exist on Windows Platform

    File does not exist on Windows Platform

    When walking an embedded box on a windows platform, the error file does not exist is returned due to a wrong slash.

    The file in question is accessed via the \ slash, not via the / slash that is generated from the rice tool (on windows and linux equally).

    bug help wanted 
    opened by tscs37 10
  • High Memory Usage

    High Memory Usage

    After running rice embed-go I get 33M *.rice-box.go file. When I run go build after that, I can't get it to build because RAM shoots up to more than 14.5GB. I've tried increasing my swap, but it keeps maxing it out. Any idea what's happening?

    opened by johnjelinek 10
  • go.rice vs. go test -coverprofile

    go.rice vs. go test -coverprofile

    Hi,

    I've encountered a problem combining go.rice with go's test coverage tool:

    $ go test datastore
    ok      datastore   0.028s
    $ go test -coverprofile=foo datastore
    panic: stat datastore/_test/_obj_test/sql: no such file or directory
    
    goroutine 16 [running]:
    runtime.panic(0x3d58c0, 0xc208209ad0)
        /usr/local/Cellar/go/1.3beta1/libexec/src/pkg/runtime/panic.c:279 +0xf5
    github.com/GeertJohan/go%2erice.MustFindBox(0x484db0, 0x3, 0xc2081a29b0)
        /Users/bfallik/sandbox/gillnet/go/src/_vendor/src/github.com/GeertJohan/go.rice/box.go:81 +0x6c
    datastore.init()
        datastore/_test/_obj_test/datastore.go:17 +0xec
    main.init()
        datastore/_test/_testmain.go:206 +0x43
    ...
    FAIL    datastore   0.027s
    

    I know that the cover tool rewrites the sources and runs them from another directory so I can imagine why this would fail for local files. However the tests still fail even when I use 'rice embed' to generate the Go sources containing the data.

    By passing the -work flag to the go tools I can muck around with the artifacts, and using 'strings' it looks like the embedded files are part of the binary so I can't figure out why MustFindBox() can't find them.

    Any ideas? Is there a recommended way to debug/inspect a binary to see which boxes are embedded?

    Thanks, brian

    opened by bfallik 10
  • embed-go performance and memory usage

    embed-go performance and memory usage

    I've optimized embed-go a bit. The trick is that I don't write the file contents into the source code, just a placeholder, format the code with the placeholders, then use fasttemplate to replace the placeholders with the contents of the files, streaming it directly from the original files to the destination go file.

    This means the files are never held in memory completely, so memory usage is much lower. It also avoids running gofmt on a very large source code, which speeds up things a bit and also lowers memory usage.

    Since gofmt doesn't always align struct values depending on their length, I had to add an empty line to make sure the code is always correctly formatted.

    I also had to copy the code behind strconv.Quote, unfortunately the public API was not good enough, and performance was pretty bad with it.

    With a fairly large box of 387 files, mostly javascript, the numbers are: before: Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.18 Maximum resident set size (kbytes): 264668 after: Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.56 Maximum resident set size (kbytes): 9144

    With a single, 80Mb file: before: Elapsed (wall clock) time (h:mm:ss or m:ss): 0:06.59 Maximum resident set size (kbytes): 2213800 after: Elapsed (wall clock) time (h:mm:ss or m:ss): 0:03.03 Maximum resident set size (kbytes): 10192

    I haven't tested it thoroughly and I still need to escape the fasttemplate placeholders in case they show up somewhere else in the generated code.

    The code is in this branch: https://github.com/nkovacs/go.rice/tree/fasttemplate

    What do you think?

    opened by nkovacs 9
  • `ReadFile()` implementation that works on Windows.

    `ReadFile()` implementation that works on Windows.

    The Bytes() implementation breaks under Windows. This ReadFile could eventually simply replace it. It also is more similar to the stdlib's ioutil.ReadFile.

    opened by abourget 9
  • Go install doesn't work

    Go install doesn't work

    Hi guys. I have next issue when try to install go.rice on my machine. I'm using Windows sandbox but actually result is same even I use Ubuntu.

    $ go version
    go version go1.17.3 windows/amd64
    
    $ go install github.com/GeertJohan/go.rice
    
    $ go install github.com/GeertJohan/go.rice/rice
    
    ..\..\go\pkg\mod\github.com\!geert!johan\[email protected]\rice\identifier.go:6:2: missing go.sum entry for module providing package github.com/GeertJohan/go.incremental (imported by github.com/GeertJohan/go.rice/rice); to add:
            go get github.com/GeertJohan/go.rice/[email protected]
    ..\..\go\pkg\mod\github.com\!geert!johan\[email protected]\rice\flags.go:8:2: missing go.sum entry for module providing package github.com/jessevdk/go-flags (imported by github.com/GeertJohan/go.rice/rice); to add:
            go get github.com/GeertJohan/go.rice/[email protected]
    ..\..\go\pkg\mod\github.com\!geert!johan\[email protected]\rice\templates.go:11:2: missing go.sum entry for module providing package github.com/nkovacs/streamquote (imported by github.com/GeertJohan/go.rice/rice); to add:
            go get github.com/GeertJohan/go.rice/[email protected]
    ..\..\go\pkg\mod\github.com\!geert!johan\[email protected]\rice\templates.go:12:2: missing go.sum entry for module providing package github.com/valyala/fasttemplate (imported by github.com/GeertJohan/go.rice/rice); to add:
            go get github.com/GeertJohan/go.rice/[email protected]
    
    
    opened by atis2345 3
  • Improvement to the README file

    Improvement to the README file

    I read your entire README file. It's pretty good, but at one point I found something very confusing...

    You say, at one point:

    A downside for appending is that it does not provide a working Seek method.
    

    when describing the downside of the second packaging method where you include the resources as a .zip file at the end of the executable.

    This sentence makes no sense. What does it mean that it does not provide a working Seek method? What are the implications of that?

    It's like telling to a person who's never driven a car the downside of not having a steering wheel is the round rubber things won't respond, when in reality the downside is that you will crash and die.

    What are the implications of having no Seek method?

    opened by tjayrush 0
  • Report a coding bug about unused result

    Report a coding bug about unused result

    At https://github.com/GeertJohan/go.rice/blob/master/box.go#L66, the result of function errors.New is not actually used since err is local to case LocateFS such that errors.New("given name/path is not a directory") won't be assigned to the one declared outside the loop var err error.

    var err error
    for _, method := range order {
    	...
    	case LocateFS:
    			// resolve absolute directory path
    			err := b.resolveAbsolutePathFromCaller()
    			...
    			err = errors.New("given name/path is not a directory")
    			continue
    }
    

    while function errors.New has no side effect:

    func New(text string) error {
    	return &errorString{text}
    }
    

    Another instance is at: https://github.com/GeertJohan/go.rice/blob/master/box.go#L83

    A mini bug reproducer is available at: https://play.golang.org/p/FA2ZsZ34zqJ

    A possible fix is not to declare a local err within the cases, e.g.

    	case LocateFS:
    			// resolve absolute directory path
    			err = b.resolveAbsolutePathFromCaller()
    

    Found by static analyzer #deepgo

    opened by guodongli-google 0
  • `rice embed-go` doesn't work for go modules beyond v1?

    `rice embed-go` doesn't work for go modules beyond v1?

    The rice embed-go command worked while my go.mod package was in v1. However, after upgrading my go.mod file so the module is using the /v2 suffix, rice embed-go now fails with "error creating embedded box file: open <v1 package path>/rice-box.go: permission denied", where "v1 package path" would be my package's v1 directory under my $GOPATH/pkg/mod.

    Is this expected or am I missing something obvious?

    opened by arosenberg-fubo 0
  • Able to skip overwrite or omit creation/modification time in embed-go

    Able to skip overwrite or omit creation/modification time in embed-go

    It would be nice to have an option to skip overwrite DirModTime, Time and FileModTime or omit this parameters where they don't make sense. This will cause revises git stage for unchanged files and make sense where this situation is important.

    opened by dmvolod 0
  • rice append violates Mach-O file format

    rice append violates Mach-O file format

    Trying to codesign go binaries with rice appended contents on a Mac fails with:

    <binary>: main executable failed strict validation
    

    I'm guessing appends violates the Mach-O file specification?

    Sample signing command that fails:

    codesign -s <cert-id> -o runtime -v <binary>
    
    
    opened by amirh 0
Owner
Geert-Johan Riemer
Go, k8s, Dart/Flutter
Geert-Johan Riemer
:file_folder: Embeds static resources into go files for single binary compilation + works with http.FileSystem + symlinks

Package statics Package statics embeds static files into your go applications. It provides helper methods and objects to retrieve embeded files and se

Go Playgound 65 Sep 27, 2022
The simple and easy way to embed static files into Go binaries.

NOTICE: Please consider migrating your projects to github.com/markbates/pkger. It has an idiomatic API, minimal dependencies, a stronger test suite (t

Buffalo - The Go Web Eco-System 3.4k Dec 25, 2022
Nuke-Net is a VERY VERY over powered and ridiculous web crawler that is well- very very noisy XD read more here

Nuke-Net is a VERY VERY over powered and ridiculous web crawler that is well- very very noisy XD read more here

RE43P3R 0 Dec 20, 2021
VMail - check the markup (HTML, CSS) of HTML email template compatibility with email clients

VMail - check the markup (HTML, CSS) of HTML email template compatibility with email clients Email clients use different rendering standards. This is

Alexey Vasiliev 22 Dec 17, 2022
A quick and easy password protected web server for your files. httpfolder makes downloading/uploading files from your current working directory easy, even for fairly large files.

httpfolder A quick and easy password protected web server for your files. httpfolder makes downloading/uploading files from your current working direc

null 14 Sep 12, 2022
Package damsel provides html outlining via css-selectors and common template functionality.

Damsel Markup language featuring html outlining via css-selectors, extensible via pkg html/template and others. Library This package expects to exist

Daniel Skinner 24 Oct 23, 2022
Frongo is a Golang package to create HTML/CSS components using only the Go language.

Frongo Frongo is a Go tool to make HTML/CSS document out of Golang code. It was designed with readability and usability in mind, so HTML objects are c

Rewan_ 21 Jul 29, 2021
lambda-go-api-proxy makes it easy to port APIs written with Go frameworks such as Gin to AWS Lambda and Amazon API Gateway.

aws-lambda-go-api-proxy makes it easy to run Golang APIs written with frameworks such as Gin with AWS Lambda and Amazon API Gateway.

Amazon Web Services - Labs 755 Jan 6, 2023
This command line converts .html file into .html with images embed.

embed-html This command line converts .html file into .html with images embed. Install > go get github.com/gonejack/embed-html Usage > embed-html *.ht

会有猫的 1 Oct 6, 2022
Go implementation for Soy templates (Google Closure templates)

soy Go implementation for Soy templates aka Google Closure Templates. See godoc for more details and usage examples. This project requires Go 1.12 or

Rob Figueiredo 167 Dec 1, 2022
Community edition nuclei templates, a simple tool that allows you to organize all the Nuclei templates offered by the community in one place

cent Community edition nuclei templates, a simple tool that allows you to organize all the Nuclei templates offered by the community in one place Inst

null 461 Jan 9, 2023
Go package for easily rendering JSON, XML, binary data, and HTML templates responses.

Render Render is a package that provides functionality for easily rendering JSON, XML, text, binary data, and HTML templates. This package is based on

Cory Jacobsen 1.7k Jan 8, 2023
Super fast static photo and video gallery generator (written in Go and HTML/CSS/native JS)

fastgallery Fast static photo and video gallery generator Super fast (written in Go and C, concurrent, uses fastest image/video libraries, 4-8 times f

Toni Melisma 26 Dec 4, 2022
Build cross platform GUI apps with GO and HTML/JS/CSS (powered by Electron)

Thanks to go-astilectron build cross platform GUI apps with GO and HTML/JS/CSS. It is the official GO bindings of astilectron and is powered by Electr

Quentin Renard 4.6k Jan 9, 2023
Golang bindings of Sciter: the Embeddable HTML/CSS/script engine for modern UI development

Go bindings for Sciter Check this page for other language bindings (Delphi / D / Go / .NET / Python / Rust). Attention The ownership of project is tra

Terra Informatica Software, Inc 2.5k Dec 23, 2022
Build cross platform GUI apps with GO and HTML/JS/CSS (powered by nwjs)

gowd Build cross platform GUI apps with GO and HTML/JS/CSS (powered by nwjs) How to use this library: Download and install nwjs Install this library g

Danny 388 Dec 11, 2022
:link: Generate HTML and CSS together, on the fly

On The Fly Package for generating HTML and CSS together, on the fly. Can also be used for generating HTML, XML or CSS (or templates). HTML and CSS can

Alexander F. Rødseth 43 Oct 12, 2022
HTML, CSS and SVG static renderer in pure Go

Web render This module implements a static renderer for the HTML, CSS and SVG formats. It consists for the main part of a Golang port of the awesome W

Benoit KUGLER 7 Apr 19, 2022
Arche - Smart Hybrid Workforce Manager: A system that aims to provide companies an easy to use platform for managing company resources by allowing employees to book company spaces and resources.

Description Smart Hybrid Workforce Manager is a system that aims to provide companies an easy to use system for managing company resources by allowing

COS 301 - 2022 26 Dec 8, 2022
Snackbox - Snackbox can make it easier for customers to order snacks and rice boxes and do tracking

Catering Ecommerce Platform API Docs · Wireflow · Use Case Diagram · Entity Rela

Muhammad Arif Furqon 0 Dec 5, 2022