Skip to content

Commit

Permalink
Improved error page
Browse files Browse the repository at this point in the history
  • Loading branch information
evg4b committed Jan 4, 2024
1 parent c3a0a47 commit e2df7d1
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 4 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
)

require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
Expand Down
26 changes: 23 additions & 3 deletions internal/infra/http_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package infra

import (
"net/http"
"runtime"
"runtime/debug"

"github.com/dustin/go-humanize"
"github.com/evg4b/uncors/internal/helpers"
"github.com/go-http-utils/headers"
"github.com/pterm/pterm"
Expand All @@ -14,18 +17,35 @@ var style = pterm.Style{}
func HTTPError(writer http.ResponseWriter, err error) {
header := writer.Header()
header.Set(headers.ContentType, "text/plain; charset=utf-8")
header.Set(headers.ContentEncoding, "identity")
header.Set(headers.CacheControl, "no-cache, no-store, max-age=0, must-revalidate")
header.Set(headers.Pragma, "no-cache")
header.Set(headers.XContentTypeOptions, "nosniff")

header.Del(headers.SetCookie)

writer.WriteHeader(http.StatusInternalServerError)
message := helpers.Sprintf("%d Error", http.StatusInternalServerError)
pageHeader := helpers.Sprintf("%d Error", http.StatusInternalServerError)

helpers.FPrintln(writer)
helpers.FPrintln(writer, pageHeader(message))
helpers.FPrintln(writer, pageHeaderFormatter(pageHeader))
helpers.FPrintln(writer)
helpers.FPrintln(writer, helpers.Sprintf("Occurred error: %s", err))
helpers.FPrintln(writer)

helpers.FPrint(writer, "Stack trace: ")
helpers.FPrintln(writer, string(debug.Stack()))

var memStats runtime.MemStats
runtime.ReadMemStats(&memStats)
helpers.FPrintln(writer, "Memory usage:")
helpers.FPrintf(writer, "Alloc = %v\n", humanize.Bytes(memStats.Alloc))
helpers.FPrintf(writer, "TotalAlloc = %v\n", humanize.Bytes(memStats.TotalAlloc))
helpers.FPrintf(writer, "Sys = %v\n", humanize.Bytes(memStats.Sys))
helpers.FPrintf(writer, "NumGC = %v\n", memStats.NumGC)
}

func pageHeader(message string) string {
func pageHeaderFormatter(message string) string {
letters := putils.LettersFromStringWithStyle(message, &style)
text, err := pterm.DefaultBigText.WithLetters(letters).Srender()
if err != nil {
Expand Down
19 changes: 18 additions & 1 deletion internal/infra/http_error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,32 @@ Occurred error: net/http: abort Handler
func TestHttpError(t *testing.T) {
recorder := httptest.NewRecorder()
infra.HTTPError(recorder, http.ErrAbortHandler)
body := testutils.ReadBody(t, recorder)

t.Run("write correct page", func(t *testing.T) {
assert.Equal(t, expectedPage, testutils.ReadBody(t, recorder))
assert.Contains(t, body, expectedPage)
})

t.Run("write correct headers", func(t *testing.T) {
header := recorder.Header()

assert.NotNil(t, header[headers.ContentType])
assert.NotNil(t, header[headers.ContentEncoding])
assert.NotNil(t, header[headers.CacheControl])
assert.NotNil(t, header[headers.Pragma])
assert.NotNil(t, header[headers.XContentTypeOptions])
assert.Nil(t, header[headers.SetCookie])
})

t.Run("Should include stack trace", func(t *testing.T) {
assert.Regexp(t, "Stack trace: goroutine \\d+ \\[running\\]:", body)
})

t.Run("Should include memory usage", func(t *testing.T) {
assert.Contains(t, body, "Memory usage:")
assert.Regexp(t, "Alloc = [\\d\\.]+ [Mk]B", body)
assert.Regexp(t, "TotalAlloc = [\\d\\.]+ [Mk]B", body)
assert.Regexp(t, "Sys = [\\d\\.]+ [Mk]B", body)
assert.Regexp(t, "NumGC = [\\d\\.]+", body)
})
}

0 comments on commit e2df7d1

Please sign in to comment.