filestash/vendor/github.com/crewjam/httperr/value.go
2023-03-14 18:12:08 +11:00

67 lines
1.9 KiB
Go

// Package httperr implements an error object that speaks HTTP.
package httperr
import (
"fmt"
"net/http"
)
// Value is an Error that returns that status and code
// provided, and reveals the underlying wrapper error to
// the caller. The text of the error is rendered to the
// client in the body of the response, as well as in
// the X-Error header.
type Value struct {
Err error // the underlying error
StatusCode int // the HTTP status code. If not supplied, http.StatusInternalServerError is used.
Status string // the HTTP status text. If not supplied, http.StatusText(http.StatusCode) is used.
Public bool
Header http.Header // extra headers to add to the response (optional)
}
// StatusCodeAndText returns the status code and text of the error
func (e Value) StatusCodeAndText() (int, string) {
if e.StatusCode == 0 {
e.StatusCode = http.StatusInternalServerError
}
if e.Status == "" {
if e.Err != nil && e.Public {
e.Status = e.Err.Error()
} else {
e.Status = http.StatusText(e.StatusCode)
}
}
return e.StatusCode, e.Status
}
func (e Value) Error() string {
statusCode, statusText := StatusCodeAndText(e)
if e.Public {
return fmt.Sprintf("%d %s", statusCode, statusText)
}
return fmt.Sprintf("%d %s: %s", statusCode, statusText, e.Err.Error())
}
// WriteError writes an error response to w using the specified status code.
func (e Value) WriteError(w http.ResponseWriter, r *http.Request) {
for key, values := range e.Header {
w.Header().Del(key) // overwrite headers already in the response with the ones specified
for _, value := range values {
w.Header().Add(key, value)
}
}
code, message := e.StatusCodeAndText()
http.Error(w, message, code)
}
// Unwrap unwraps the Value error and returns the underlying error`
func (e Value) Unwrap() error {
return e.Err
}
var _ error = Value{}
var _ Writer = Value{}
var _ statusCodeAndTexter = Value{}