http: Error template documents are supported
This commit is contained in:
parent
62885b2e37
commit
a7b360cc09
@ -11,11 +11,18 @@ import "path/filepath"
|
||||
import "git.tebibyte.media/sashakoshka/step"
|
||||
import "git.tebibyte.media/sashakoshka/goutil/container"
|
||||
|
||||
type ErrorData struct {
|
||||
Status int
|
||||
Message any
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
Environment *step.Environment
|
||||
Directories bool
|
||||
StepExt ucontainer.Set[string]
|
||||
Index []string
|
||||
ErrorDocument string
|
||||
DirectoryDocument string
|
||||
}
|
||||
|
||||
func (this *Handler) ServeHTTP (res http.ResponseWriter, req *http.Request) {
|
||||
@ -39,9 +46,7 @@ func (this *Handler) ServeHTTP (res http.ResponseWriter, req *http.Request) {
|
||||
|
||||
info, err := statFile(filesystem, pathToName(pat))
|
||||
if err != nil {
|
||||
// TODO need more detailed error, should allow specifying error
|
||||
// documents
|
||||
this.serveError(res, req, http.StatusNotFound, req.URL)
|
||||
this.serveError(res, req, http.StatusNotFound, req.URL, false)
|
||||
return
|
||||
}
|
||||
if info.IsDir() {
|
||||
@ -57,12 +62,12 @@ func (this *Handler) ServeHTTP (res http.ResponseWriter, req *http.Request) {
|
||||
info, err := statFile(filesystem, pathToName(currentPath))
|
||||
if err != nil { continue }
|
||||
if info.IsDir() { continue }
|
||||
this.serveFile(res, req, filesystem, currentPath)
|
||||
this.serveFile(res, req, currentPath)
|
||||
return
|
||||
}
|
||||
|
||||
if !this.Directories {
|
||||
this.serveError(res, req, http.StatusForbidden, req.URL)
|
||||
this.serveError(res, req, http.StatusForbidden, req.URL, false)
|
||||
return
|
||||
}
|
||||
|
||||
@ -72,21 +77,32 @@ func (this *Handler) ServeHTTP (res http.ResponseWriter, req *http.Request) {
|
||||
// as data
|
||||
}
|
||||
|
||||
this.serveFile(res, req, filesystem, pat)
|
||||
this.serveFile(res, req, pat)
|
||||
}
|
||||
|
||||
func (this *Handler) serveFile (res http.ResponseWriter, req *http.Request, filesystem fs.FS, pat string) {
|
||||
func (this *Handler) serveFile (
|
||||
res http.ResponseWriter,
|
||||
req *http.Request,
|
||||
pat string,
|
||||
) {
|
||||
name := pathToName(pat)
|
||||
if !this.StepExt.Has(filepath.Ext(name)) {
|
||||
// just a normal file
|
||||
http.ServeFileFS(res, req, this.Environment.GetFS(), name)
|
||||
return
|
||||
}
|
||||
this.serveDocument(res, req, name)
|
||||
}
|
||||
|
||||
func (this *Handler) serveDocument (
|
||||
res http.ResponseWriter,
|
||||
req *http.Request,
|
||||
name string,
|
||||
) {
|
||||
// parse
|
||||
document, err := this.Environment.Parse(name)
|
||||
if err != nil {
|
||||
this.serveError(res, req, http.StatusInternalServerError, err)
|
||||
this.serveError(res, req, http.StatusInternalServerError, err, false)
|
||||
return
|
||||
}
|
||||
|
||||
@ -115,7 +131,7 @@ func (this *Handler) serveFile (res http.ResponseWriter, req *http.Request, file
|
||||
Data: data,
|
||||
})
|
||||
if err != nil {
|
||||
this.serveError(res, req, http.StatusInternalServerError, err)
|
||||
this.serveError(res, req, http.StatusInternalServerError, err, false)
|
||||
return
|
||||
}
|
||||
|
||||
@ -126,16 +142,41 @@ func (this *Handler) serveFile (res http.ResponseWriter, req *http.Request, file
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Handler) serveError (res http.ResponseWriter, req *http.Request, status int, message any) {
|
||||
res.Header().Add("Content-Type", "text/plain")
|
||||
res.WriteHeader(status)
|
||||
// TODO: allow customization with templates
|
||||
if message == nil {
|
||||
fmt.Fprintf(res, "%d %s\n", status, http.StatusText(status))
|
||||
} else {
|
||||
fmt.Fprintf(res, "%d %s: %v\n", status, http.StatusText(status), message)
|
||||
}
|
||||
func (this *Handler) serveError (
|
||||
res http.ResponseWriter,
|
||||
req *http.Request,
|
||||
status int,
|
||||
message any,
|
||||
safeMode bool,
|
||||
) {
|
||||
log.Printf("ERR %d %s: %v\n", status, http.StatusText(status), message)
|
||||
if safeMode || this.ErrorDocument == "" {
|
||||
res.Header().Add("Content-Type", "text/plain")
|
||||
res.WriteHeader(status)
|
||||
// TODO: allow customization with templates
|
||||
if message == nil {
|
||||
fmt.Fprintf(res, "%d %s\n", status, http.StatusText(status))
|
||||
} else {
|
||||
fmt.Fprintf(res, "%d %s: %v\n", status, http.StatusText(status), message)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
document, err := this.Environment.Parse(this.ErrorDocument)
|
||||
if err != nil {
|
||||
this.serveError(res, req, http.StatusInternalServerError, err, true)
|
||||
return
|
||||
}
|
||||
err = document.Execute(res, step.ExecutionData {
|
||||
Data: ErrorData {
|
||||
Status: status,
|
||||
Message: message,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
this.serveError(res, req, http.StatusInternalServerError, err, true)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Handler) logErr (name string, err error) {
|
||||
|
Loading…
Reference in New Issue
Block a user