The handler returned by http.FileServer()
unconditionally sets the "Last-Modified"
header in the http.serveFile()
and http.serveContent()
unexported functions:
func serveFile(w ResponseWriter, r *Request, fs FileSystem,
name string, redirect bool) {
// ...
f, err := fs.Open(name)
// ...
d, err := f.Stat()
// ...
// serveContent will check modification time
sizeFunc := func() (int64, error) { return d.Size(), nil }
serveContent(w, r, d.Name(), d.ModTime(), sizeFunc, f)
}
func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
sizeFunc func() (int64, error), content io.ReadSeeker) {
setLastModified(w, modtime)
// ...
}
func setLastModified(w ResponseWriter, modtime time.Time) {
if !isZeroTime(modtime) {
w.Header().Set("Last-Modified", modtime.UTC().Format(TimeFormat))
}
}
So what you set prior to calling the file server handler will get overwritten. You can't really do anything about this.
If you need to serve the content of a file with custom last-modified time, you may use http.ServeContent()
:
func ServeContent(w ResponseWriter, req *Request, name string,
modtime time.Time, content io.ReadSeeker)
Where you can pass the last-modified time to be used, but then of course you lose all the convenient features provided by http.FileServer()
.
If you want to keep using http.FileServer()
, another option would be to not use the http.Dir
type, but create your own http.FileSystem
implementation that you pass to http.FileServer()
, in which you could report any last-modified timestamp you wish.
This would require you to implement the following interface:
type FileSystem interface {
Open(name string) (File, error)
}
So you need a method which opens a file by its name, and returns a value which implements http.File
, which is:
type File interface {
io.Closer
io.Reader
io.Seeker
Readdir(count int) ([]os.FileInfo, error)
Stat() (os.FileInfo, error)
}
And the value you return (that implements http.File
) could have a Stat() (os.FileInfo, error)
method implementation, whose os.FileInfo
returned value contains the last-modified time of your choosing. Note that you should also implement the Readdir()
method to return custom last-modified timestamps consistent with the timestamps returned by Stat()
's fileinfo. See related question how to do that: Simples way to make a []byte into a "virtual" File object in golang?