英文:
Serving files from static url with Go / Negroni / Gorilla Mux
问题
我是你的中文翻译助手,以下是你要翻译的内容:
我是Go的新手,正在尝试使用它构建一个简单的Web服务器。我遇到的一个问题是,我想要使用动态静态URL(以便浏览器可以进行长时间缓存)来提供静态文件。例如,我可能有以下URL:
/static/876dsf5g87s6df5gs876df5g/application.js
但我想要提供位于以下位置的文件:
/build/application.js
在Go / Negroni / Gorilla Mux中,我该如何实现这一点?
英文:
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?
答案1
得分: 4
你已经决定如何记录/持久化URL中的“随机”部分了吗?是使用数据库吗?还是在内存中(即不跨重启)?如果没有,可以在启动时使用crypto/sha1
对文件进行哈希处理,并将结果的SHA-1哈希存储在一个映射/切片中。
否则,可以使用类似以下的路由(假设使用Gorilla):r.Handle("/static/{cache_id}/{filename}", YourFileHandler)
。
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"]
// 用于示例的日志记录
log.Println(id)
// 检查id是否有效,否则返回404,301到新的URL等 - 在这里处理!
// (这是您查找SHA-1哈希的地方)
// 假设id有效
file := vars["filename"]
// 用于示例的日志记录
log.Println(file)
// 非常简单。不设置任何缓存头,不检查文件是否存在,不避免竞态条件等。
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))
}
这段代码应该可以直接使用,但我不能保证它适用于生产环境。个人而言,我只是使用nginx来提供静态文件,并从中受益于其文件处理程序缓存、可靠的gzip实现等等。
英文:
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.
答案2
得分: 1
我知道现在已经很晚了,但也许我的回答对其他人有所帮助。我找到了一个名为go-staticfiles的库,它通过在文件名中添加哈希值来实现静态文件缓存和版本控制。因此,可以为资产文件设置长时间缓存,并在其更改时立即获取最新副本。此外,还可以轻松实现模板函数,将链接转换为静态文件的真实路径,例如{{static "css/style.css"}}
转换为/static/css/style.d41d8cd98f00b204e9800998ecf8427e.css
。在README中可以阅读更多示例。
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论