LoginSignup
21
19

More than 5 years have passed since last update.

go-bindataでまとめたファイルをhttp.FileServerで配信する

Last updated at Posted at 2015-01-22

Goはアプリケーションを1バイナリで配布できて楽なのですが、webアプリケーションの場合は大抵静的ファイルを配信する必要があり、これが外部ファイルになってしまいます。CSSとか。

そこで go-bindata を使うとファイルをバイナリに同梱できて便利ですが、これを http.FileServer で配信できたら更に楽になるのでは…と思ってこんな風にしてみました。

http.FileServer interfaceを実装した AssetFileSystem と、http.File interfaceを実装した AssetFile を適当に定義して、go-bindata で作った Assets() から取得したデータを配信してやるサンプルです。

ただし、http.serveFile() がindex.htmlへのアクセスをリダイレクトしてくれるという気の効かせ方 をするため、現状は index.html というファイルへのアクセスのみができない(404になる)、という辛い状態です。

実行例

$ go-bindata -prefix=pubic public/...
$ go build
package main

import (
    "bytes"
    "log"
    "net/http"
    "os"
    "strings"
)

func main() {
    http.Handle("/", http.FileServer(AssetFileSystem{}))
    log.Fatal(http.ListenAndServe(":3000", nil))
}

type AssetFileSystem struct {
}

type AssetFile struct {
    *bytes.Reader
    os.FileInfo
}

func (fs AssetFileSystem) Open(name string) (http.File, error) {
    path := name
    path = strings.TrimLeft(path, "/")
    log.Println("open asset", path)
    data, err := Asset(path)
    if err != nil {
        log.Println(err)
        return nil, err
    }
    info, _ := AssetInfo(path)
    file := &AssetFile{
        bytes.NewReader(data),
        info,
    }
    log.Printf("%#v", file)
    return file, nil
}

func (f *AssetFile) Close() error {
    return nil
}

func (f *AssetFile) Readdir(count int) ([]os.FileInfo, error) {
    return []os.FileInfo{}, nil
}

func (f *AssetFile) Stat() (os.FileInfo, error) {
    return f, nil
}
21
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
19