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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user