0
votes

So I am new to Go and trying it out to build a simple web server. One part I am having trouble with is that I want to serve static files with dynamic static urls (to enable long caching by the browser). For example, I might have this url:

/static/876dsf5g87s6df5gs876df5g/application.js

But I want to serve the file located at:

/build/application.js

How would I go about this with Go / Negroni / Gorilla Mux?

2

2 Answers

4
votes

Have you already decided on how to record/persist the "random" part of the URL? DB? In memory (i.e. not across restarts)? If not, crypto/sha1 the file(s) on start-up, and store the resultant SHA-1 hash in a map/slice.

Otherwise, a route like (assuming Gorilla) r.Handle("/static/{cache_id}/{filename}", YourFileHandler) would work.

package main

import (
    "log"
    "mime"
    "net/http"
    "path/filepath"

    "github.com/gorilla/mux"
)

func FileServer(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    id := vars["cache_id"]

    // Logging for the example
    log.Println(id)

    // Check if the id is valid, else 404, 301 to the new URL, etc - goes here!
    // (this is where you'd look up the SHA-1 hash)

    // Assuming it's valid
    file := vars["filename"]

    // Logging for the example
    log.Println(file)

    // Super simple. Doesn't set any cache headers, check existence, avoid race conditions, etc.
    w.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(file)))
    http.ServeFile(w, r, "/Users/matt/Desktop/"+file)
}

func IndexHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello!\n"))
}

func main() {

    r := mux.NewRouter()

    r.HandleFunc("/", IndexHandler)
    r.HandleFunc("/static/{cache_id}/{filename}", FileServer)

    log.Fatal(http.ListenAndServe(":4000", r))
}

That should work out of the box, but I can't promise it's production ready. Personally, I just use nginx to serve my static files and benefit from it's file handler cache, solid gzip implementation, etc, etc.

1
votes

I know it's too late but maybe my answer will help someone too. I've found a library go-staticfiles which implements static files caching and versioning by adding a hash to the file names. Thus it is possible to set long time cache for assets files and when they changes get fresh copy instantly. Also it is easy to implement template function to convert link to static file {{static "css/style.css"}} to a real path /static/css/style.d41d8cd98f00b204e9800998ecf8427e.css. Read more examples in README