|
|
@ -4,6 +4,7 @@ import ( |
|
|
|
"crypto/sha1" |
|
|
|
"fmt" |
|
|
|
"io/ioutil" |
|
|
|
"mime" |
|
|
|
"net/http" |
|
|
|
"os" |
|
|
|
"path" |
|
|
@ -13,23 +14,23 @@ import ( |
|
|
|
|
|
|
|
const assetsFolder = "templates/assets" |
|
|
|
|
|
|
|
var compiledAssetsFolder string |
|
|
|
var assetFiles map[string]string |
|
|
|
var assetFileNames map[string]string = map[string]string{} |
|
|
|
var assetFiles map[string]*assetFile = map[string]*assetFile{} |
|
|
|
|
|
|
|
type assetFile struct { |
|
|
|
contentType string |
|
|
|
body []byte |
|
|
|
} |
|
|
|
|
|
|
|
func initTemplateAssets() (err error) { |
|
|
|
compiledAssetsFolder, err = ioutil.TempDir("", "goblog-assets-*") |
|
|
|
if err != nil { |
|
|
|
return |
|
|
|
} |
|
|
|
assetFiles = map[string]string{} |
|
|
|
err = filepath.Walk(assetsFolder, func(path string, info os.FileInfo, err error) error { |
|
|
|
if info.Mode().IsRegular() { |
|
|
|
compiled, err := compileAssets(path) |
|
|
|
compiled, err := compileAsset(path) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
if compiled != "" { |
|
|
|
assetFiles[strings.TrimPrefix(path, assetsFolder+"/")] = compiled |
|
|
|
assetFileNames[strings.TrimPrefix(path, assetsFolder+"/")] = compiled |
|
|
|
} |
|
|
|
} |
|
|
|
return nil |
|
|
@ -40,7 +41,7 @@ func initTemplateAssets() (err error) { |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
func compileAssets(name string) (compiledFileName string, err error) { |
|
|
|
func compileAsset(name string) (compiledFileName string, err error) { |
|
|
|
originalContent, err := ioutil.ReadFile(name) |
|
|
|
if err != nil { |
|
|
|
return |
|
|
@ -67,21 +68,21 @@ func compileAssets(name string) (compiledFileName string, err error) { |
|
|
|
sha.Write(compiledContent) |
|
|
|
hash := fmt.Sprintf("%x", sha.Sum(nil)) |
|
|
|
compiledFileName = hash + compiledExt |
|
|
|
err = ioutil.WriteFile(path.Join(compiledAssetsFolder, compiledFileName), compiledContent, 0644) |
|
|
|
if err != nil { |
|
|
|
return |
|
|
|
assetFiles[compiledFileName] = &assetFile{ |
|
|
|
contentType: mime.TypeByExtension(compiledExt), |
|
|
|
body: compiledContent, |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// Function for templates
|
|
|
|
func assetFile(fileName string) string { |
|
|
|
return "/" + assetFiles[fileName] |
|
|
|
func assetFileName(fileName string) string { |
|
|
|
return "/" + assetFileNames[fileName] |
|
|
|
} |
|
|
|
|
|
|
|
func allAssetPaths() []string { |
|
|
|
var paths []string |
|
|
|
for _, name := range assetFiles { |
|
|
|
for _, name := range assetFileNames { |
|
|
|
paths = append(paths, "/"+name) |
|
|
|
} |
|
|
|
return paths |
|
|
@ -89,6 +90,13 @@ func allAssetPaths() []string { |
|
|
|
|
|
|
|
// Gets only called by registered paths
|
|
|
|
func serveAsset(w http.ResponseWriter, r *http.Request) { |
|
|
|
w.Header().Add("Cache-Control", "public,max-age=31536000,immutable") |
|
|
|
http.ServeFile(w, r, filepath.Join(compiledAssetsFolder, r.URL.Path)) |
|
|
|
f := strings.TrimPrefix(r.URL.Path, "/") |
|
|
|
af, ok := assetFiles[f] |
|
|
|
if !ok { |
|
|
|
serve404(w, r) |
|
|
|
return |
|
|
|
} |
|
|
|
w.Header().Set("Cache-Control", "public,max-age=31536000,immutable") |
|
|
|
w.Header().Set(contentType, af.contentType) |
|
|
|
w.Write(af.body) |
|
|
|
} |