From 598ec463bcaac6f8d9a9f2e34d0f6fcf1582b1e8 Mon Sep 17 00:00:00 2001 From: Will Norris Date: Tue, 31 Jan 2023 16:01:02 -0800 Subject: [PATCH] fixup! util/vizerror: add new package for visible errors Signed-off-by: Will Norris --- tsweb/tsweb.go | 12 +++++++++++- tsweb/tsweb_test.go | 18 ++++++++++++++++++ util/vizerror/vizerror.go | 31 ++++++++++++++++++++++++------- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/tsweb/tsweb.go b/tsweb/tsweb.go index 21ea23cb6..4f80f915d 100644 --- a/tsweb/tsweb.go +++ b/tsweb/tsweb.go @@ -32,6 +32,7 @@ import ( "tailscale.com/net/tsaddr" "tailscale.com/types/logger" "tailscale.com/util/strs" + "tailscale.com/util/vizerror" "tailscale.com/version" ) @@ -263,7 +264,16 @@ func (h retHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { lw := &loggingResponseWriter{ResponseWriter: w, logf: h.opts.Logf} err := h.rh.ServeHTTPReturn(lw, r) - hErr, hErrOK := err.(HTTPError) + + var hErr HTTPError + var vizErr vizerror.Error + var hErrOK bool + if errors.As(err, &hErr) { + hErrOK = true + } else if errors.As(err, &vizErr) { + hErrOK = true + hErr = HTTPError{Msg: vizErr.Error()} + } if lw.code == 0 && err == nil && !lw.hijacked { // If the handler didn't write and didn't send a header, that still means 200. diff --git a/tsweb/tsweb_test.go b/tsweb/tsweb_test.go index 132e35052..c19c2c5bf 100644 --- a/tsweb/tsweb_test.go +++ b/tsweb/tsweb_test.go @@ -21,6 +21,7 @@ import ( "github.com/google/go-cmp/cmp" "tailscale.com/metrics" "tailscale.com/tstest" + "tailscale.com/util/vizerror" "tailscale.com/version" ) @@ -151,6 +152,23 @@ func TestStdHandler(t *testing.T) { }, }, + { + name: "handler returns user visible error", + rh: handlerErr(0, vizerror.New("visible error")), + r: req(bgCtx, "http://example.com/foo"), + wantCode: 500, + wantLog: AccessLogRecord{ + When: clock.Start, + Seconds: 1.0, + Proto: "HTTP/1.1", + Host: "example.com", + Method: "GET", + RequestURI: "/foo", + Err: "visible error", + Code: 500, + }, + }, + { name: "handler returns generic error", rh: handlerErr(0, testErr), diff --git a/util/vizerror/vizerror.go b/util/vizerror/vizerror.go index 2e0713847..bc3f8e90c 100644 --- a/util/vizerror/vizerror.go +++ b/util/vizerror/vizerror.go @@ -11,14 +11,31 @@ import ( ) // Error is an error that is safe to display to end users. -type Error error +type Error struct { + err error +} + +// Error implements the error interface. +func (e Error) Error() string { + return e.err.Error() +} + +// New returns an Error that formats as the given text. +func New(text string) Error { + return Error{errors.New(text)} +} + +// Errorf returns an Error with the specified format and values. +func Errorf(format string, a ...any) Error { + return Error{fmt.Errorf(format, a...)} +} -// New returns an error that formats as the given text. -func New(text string) error { - return Error(errors.New(text)) +// Unwrap returns the underlying error. +func (e Error) Unwrap() error { + return e.err } -// Errorf returns an error with the specified format and values. -func Errorf(format string, a ...any) error { - return Error(fmt.Errorf(format, a...)) +// Wrap err with a vizerror.Error. +func Wrap(err error) Error { + return Error{err} }