62 lines
1.4 KiB
Go
62 lines
1.4 KiB
Go
package middlewares
|
|
|
|
import (
|
|
"bytes"
|
|
"io/fs"
|
|
"log"
|
|
"net/http"
|
|
)
|
|
|
|
// FallbackFile serves a fallback file if the next handler returns a 404.
|
|
// fs: The file system to serve the fallback file from.
|
|
// name: The name of the fallback file.
|
|
// next: The next handler to serve.
|
|
func FallbackFile(fs fs.FS, name string, next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
bw := &buffedResponseWriter{
|
|
w,
|
|
0,
|
|
bytes.NewBuffer([]byte{}),
|
|
}
|
|
next.ServeHTTP(bw, r)
|
|
|
|
if bw.statusCode == http.StatusNotFound {
|
|
bw.Clear()
|
|
|
|
http.ServeFileFS(bw, r, fs, name)
|
|
bw.WriteHeader(http.StatusOK)
|
|
bw.Header().Add("Content-Type", "text/html; charset=utf-8")
|
|
}
|
|
bw.Apply()
|
|
})
|
|
}
|
|
|
|
type buffedResponseWriter struct {
|
|
http.ResponseWriter
|
|
statusCode int
|
|
buff *bytes.Buffer
|
|
}
|
|
|
|
func (b *buffedResponseWriter) WriteHeader(code int) {
|
|
b.statusCode = code
|
|
}
|
|
|
|
func (b *buffedResponseWriter) Write(p []byte) (int, error) {
|
|
return b.buff.Write(p)
|
|
}
|
|
|
|
func (b *buffedResponseWriter) Clear() {
|
|
b.buff.Reset()
|
|
}
|
|
|
|
func (b *buffedResponseWriter) Apply() {
|
|
_, err := b.ResponseWriter.Write(b.buff.Bytes())
|
|
if err != nil {
|
|
log.Println("Error while applying buffedResponseWriter: ", err)
|
|
b.ResponseWriter.WriteHeader(http.StatusInternalServerError)
|
|
}
|
|
if b.statusCode != 200 {
|
|
b.ResponseWriter.WriteHeader(b.statusCode)
|
|
}
|
|
}
|