Skip to content

Commit

Permalink
api/render: implemented statusCodeFromError
Browse files Browse the repository at this point in the history
  • Loading branch information
azazeal committed Mar 28, 2022
1 parent e19169f commit 881f342
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 13 deletions.
33 changes: 28 additions & 5 deletions api/render/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"encoding/json"
"net/http"

"github.com/pkg/errors"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"

Expand Down Expand Up @@ -85,12 +84,36 @@ func Error(w http.ResponseWriter, err error) {
return
}

code := http.StatusInternalServerError
JSONStatus(w, err, statusCodeFromError(err))
}

func statusCodeFromError(err error) (code int) {
code = http.StatusInternalServerError

// if the error implements err
if sc, ok := err.(errs.StatusCoder); ok {
code = sc.StatusCode()
} else if sc, ok := errors.Cause(err).(errs.StatusCoder); ok {
code = sc.StatusCode()

return
}

type causer interface {
Cause() error
}

for err != nil {
cause, ok := err.(causer)
if !ok {
break
}
err = cause.Cause()

if sc, ok := err.(errs.StatusCoder); ok {
code = sc.StatusCode()

break
}
}

JSONStatus(w, err, code)
return
}
41 changes: 33 additions & 8 deletions api/render/render_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package render

import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"strconv"
Expand Down Expand Up @@ -30,28 +32,28 @@ func TestJSONPanics(t *testing.T) {
})
}

type renderableTestError struct {
type renderableError struct {
Code int `json:"-"`
Message string `json:"message"`
}

func (err renderableTestError) Error() string {
func (err renderableError) Error() string {
return err.Message
}

func (err renderableTestError) Render(w http.ResponseWriter) {
func (err renderableError) Render(w http.ResponseWriter) {
w.Header().Set("Content-Type", "something/custom")

JSONStatus(w, err, err.Code)
}

type codedTestError struct {
type statusedError struct {
Contents string
}

func (err codedTestError) Error() string { return err.Contents }
func (err statusedError) Error() string { return err.Contents }

func (codedTestError) StatusCode() int { return 432 }
func (statusedError) StatusCode() int { return 432 }

func TestError(t *testing.T) {
cases := []struct {
Expand All @@ -61,13 +63,13 @@ func TestError(t *testing.T) {
header string
}{
0: {
err: renderableTestError{532, "some string"},
err: renderableError{532, "some string"},
code: 532,
body: "{\"message\":\"some string\"}\n",
header: "something/custom",
},
1: {
err: codedTestError{"123"},
err: statusedError{"123"},
code: 432,
body: "{\"Contents\":\"123\"}\n",
header: "application/json",
Expand All @@ -88,3 +90,26 @@ func TestError(t *testing.T) {
})
}
}

type causedError struct {
cause error
}

func (err causedError) Error() string { return fmt.Sprintf("cause: %s", err.cause) }
func (err causedError) Cause() error { return err.cause }

func TestStatusCodeFromError(t *testing.T) {
cases := []struct {
err error
exp int
}{
0: {nil, http.StatusInternalServerError},
1: {io.EOF, http.StatusInternalServerError},
2: {statusedError{"123"}, 432},
3: {causedError{statusedError{"432"}}, 432},
}

for caseIndex, kase := range cases {
assert.Equal(t, kase.exp, statusCodeFromError(kase.err), "case: %d", caseIndex)
}
}

0 comments on commit 881f342

Please sign in to comment.