From 5687f8ec6480f20bccf7065b02d6fffe97d44d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Sat, 23 Nov 2024 18:05:32 +0100 Subject: [PATCH] ci: Switch linters --- .github/workflows/audit.yml | 30 --------------------- .github/workflows/lint-test-vet.yml | 27 +++++++++++++++++++ .golangci.yml | 17 ++++++++++++ Makefile | 6 +++++ cmd/server/main.go | 2 -- docs/develop.md | 15 ++++++++--- go.mod | 2 +- go.sum | 30 +++++++++++++++++++++ internal/api/api_test.go | 2 +- internal/api/handle_get_health.go | 7 +++-- internal/api/handle_get_metrics.go | 6 ----- internal/api/handle_get_protected_{slug}.go | 15 +++++++---- internal/api/handle_get_{slug}.go | 4 ++- internal/api/responses.go | 6 +++-- 14 files changed, 115 insertions(+), 54 deletions(-) delete mode 100644 .github/workflows/audit.yml create mode 100644 .github/workflows/lint-test-vet.yml create mode 100644 .golangci.yml diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml deleted file mode 100644 index 854f1f2..0000000 --- a/.github/workflows/audit.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Lint, test, vet - -on: - push: - pull_request: - -jobs: - audit: - name: Audit - timeout-minutes: 20 - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: 1.22 - - - name: Install dependencies - run: | - go mod download - go install golang.org/x/lint/golint@latest - - - name: Lint, test and vet - run: | - golint ./... - go test -v ./... - go vet ./... \ No newline at end of file diff --git a/.github/workflows/lint-test-vet.yml b/.github/workflows/lint-test-vet.yml new file mode 100644 index 0000000..0239c00 --- /dev/null +++ b/.github/workflows/lint-test-vet.yml @@ -0,0 +1,27 @@ +name: Lint, test, vet + +on: + push: + pull_request: + +jobs: + checks: + timeout-minutes: 5 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.2.2 + + - uses: actions/setup-go@v5.1.0 + with: + go-version: 1.23.3 + + - name: Lint + uses: golangci/golangci-lint-action@v6.1.1 + with: + version: latest + + - name: Format check + run: go fmt ./... + + - name: Static analysis + run: go vet ./... diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..bd09eb1 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,17 @@ +linters: + enable: + - govet # correctness + - errcheck # error handling + - staticcheck # static analysis + - gosec # security + - revive # best practices + +linters-settings: + gosec: + excludes: + - G104 # disregard errors not requiring explicit handling + - G204 # allow subprocess launching with validated config inputs + +run: + timeout: 5m + tests: true \ No newline at end of file diff --git a/Makefile b/Makefile index 4276f80..f2b469d 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,12 @@ live: air .PHONY: live +lint: + golangci-lint run + +lintfix: + golangci-lint run --fix + # ------------ # audit # ------------ diff --git a/cmd/server/main.go b/cmd/server/main.go index 5007b07..3e8a012 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -26,8 +26,6 @@ var ( buildTime string ) -var startTime = time.Now() - func main() { cfg := config.NewConfig(commitSha) diff --git a/docs/develop.md b/docs/develop.md index b24af16..0671e7d 100644 --- a/docs/develop.md +++ b/docs/develop.md @@ -1,16 +1,16 @@ # Development -Install Go 1.22.5: +Install Go 1.23.3: ```sh -brew install go@1.22.5 +brew install go@1.23.3 ``` Install Go tooling: ```sh go install gotest.tools/gotestsum@latest -go install golang.org/x/lint/golint@latest +go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest go install github.com/air-verse/air@latest go install -tags 'sqlite3' github.com/golang-migrate/migrate/v4/cmd/migrate@latest ``` @@ -27,7 +27,14 @@ Create an alias: echo "alias s.go='cd $(pwd)'" >> ~/.zshrc && source ~/.zshrc ``` -Refer to the [Makefile](../Makefile): +Create a DB and run migrations: + +```sh +make db/create +make db/mig/up +``` + +For more commands, refer to the [Makefile](../Makefile): ```sh make help diff --git a/go.mod b/go.mod index f8e33bc..58874fc 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ivov/n8n-shortlink -go 1.22.5 +go 1.23.3 require ( github.com/felixge/httpsnoop v1.0.4 diff --git a/go.sum b/go.sum index 7256daf..8f7e5b4 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -11,12 +13,16 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/getsentry/sentry-go v0.28.1 h1:zzaSm/vHmGllRM6Tpx1492r0YDzauArdBfkJRtY6P5k= github.com/getsentry/sentry-go v0.28.1/go.mod h1:1fQZ+7l7eeJ3wYi82q5Hg8GqAPgefRq+FP/QhafYVgg= +github.com/getsentry/sentry-go v0.29.1 h1:DyZuChN8Hz3ARxGVV8ePaNXh1dQ7d76AiB117xcREwA= +github.com/getsentry/sentry-go v0.29.1/go.mod h1:x3AtIzN01d6SiWkderzaH28Tm0lgkafpJ5Bm3li39O0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4= github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM= +github.com/golang-migrate/migrate/v4 v4.18.1 h1:JML/k+t4tpHCpQTCAD62Nu43NUFzHY4CV3uAuvHGC+Y= +github.com/golang-migrate/migrate/v4 v4.18.1/go.mod h1:HAX6m3sQgcdO81tdjn5exv20+3Kb13cmGli1hrD6hks= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -34,6 +40,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= +github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -42,22 +50,34 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -66,14 +86,24 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/api/api_test.go b/internal/api/api_test.go index 67e5f6e..874a09d 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -83,7 +83,7 @@ func TestAPI(t *testing.T) { } noFollowRedirectClient := http.Client{ - CheckRedirect: func(req *http.Request, via []*http.Request) error { + CheckRedirect: func(_ *http.Request, _ []*http.Request) error { return http.ErrUseLastResponse // do not follow redirect so we can inspect it }, } diff --git a/internal/api/handle_get_health.go b/internal/api/handle_get_health.go index 181308a..8d0bda1 100644 --- a/internal/api/handle_get_health.go +++ b/internal/api/handle_get_health.go @@ -6,7 +6,7 @@ import ( ) // HandleGetHealth returns the health status of the API. -func (api *API) HandleGetHealth(w http.ResponseWriter, r *http.Request) { +func (api *API) HandleGetHealth(w http.ResponseWriter, _ *http.Request) { health := fmt.Sprintf( `{"status": "ok", "environment": %q, "version": %q}`, api.Config.Env, @@ -14,5 +14,8 @@ func (api *API) HandleGetHealth(w http.ResponseWriter, r *http.Request) { ) w.Header().Set("Content-Type", "application/json") - w.Write([]byte(health)) + + if _, err := w.Write([]byte(health)); err != nil { + api.Logger.Error(err) + } } diff --git a/internal/api/handle_get_metrics.go b/internal/api/handle_get_metrics.go index 85b338b..1afaafb 100644 --- a/internal/api/handle_get_metrics.go +++ b/internal/api/handle_get_metrics.go @@ -47,12 +47,6 @@ var ( ) ) -var ( - lastTotalRequestsReceived float64 - lastTotalResponsesSent float64 - lastTotalProcessingTimeMs float64 -) - func init() { prometheus.MustRegister(totalRequestsReceived) prometheus.MustRegister(totalResponsesSent) diff --git a/internal/api/handle_get_protected_{slug}.go b/internal/api/handle_get_protected_{slug}.go index dd3f16f..dd0b165 100644 --- a/internal/api/handle_get_protected_{slug}.go +++ b/internal/api/handle_get_protected_{slug}.go @@ -22,20 +22,20 @@ func (api *API) HandleGetProtectedSlug(w http.ResponseWriter, r *http.Request, s } if !strings.HasPrefix(authHeader, "Basic ") { - api.Unauthorized(errors.ErrAuthHeaderMalformed, "MALFORMED_AUTHORIZATION_HEADER", w) + api.Unauthorized(errors.ErrAuthHeaderMalformed, w) return } encodedPassword := strings.TrimPrefix(authHeader, "Basic ") decodedBytes, err := base64.StdEncoding.DecodeString(encodedPassword) if err != nil { - api.Unauthorized(errors.ErrAuthHeaderMalformed, "MALFORMED_AUTHORIZATION_HEADER", w) + api.Unauthorized(errors.ErrAuthHeaderMalformed, w) return } decodedPassword := string(decodedBytes) if !api.ShortlinkService.VerifyPassword(shortlink.Password, decodedPassword) { - api.Unauthorized(errors.ErrPasswordInvalid, "INVALID_PASSWORD", w) + api.Unauthorized(errors.ErrPasswordInvalid, w) return } @@ -49,10 +49,15 @@ func (api *API) HandleGetProtectedSlug(w http.ResponseWriter, r *http.Request, s switch shortlink.Kind { case "workflow": w.Header().Set("Content-Type", "application/json") - w.Write([]byte(shortlink.Content)) + if _, err := w.Write([]byte(shortlink.Content)); err != nil { + api.Logger.Error(err) + } case "url": w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{"url": shortlink.Content}) + if err := json.NewEncoder(w).Encode(map[string]string{"url": shortlink.Content}); err != nil { + api.Logger.Error(err) + api.InternalServerError(err, w) + } default: api.BadRequest(errors.ErrKindUnsupported, w) } diff --git a/internal/api/handle_get_{slug}.go b/internal/api/handle_get_{slug}.go index ddf71b6..65b6203 100644 --- a/internal/api/handle_get_{slug}.go +++ b/internal/api/handle_get_{slug}.go @@ -61,7 +61,9 @@ func (api *API) HandleGetSlug(w http.ResponseWriter, r *http.Request) { } w.Header().Set("Content-Type", "application/json") - w.Write([]byte(shortlink.Content)) + if _, err := w.Write([]byte(shortlink.Content)); err != nil { + api.Logger.Error(err) + } case "url": http.Redirect(w, r, shortlink.Content, http.StatusMovedPermanently) default: diff --git a/internal/api/responses.go b/internal/api/responses.go index 57e0b27..19d35eb 100644 --- a/internal/api/responses.go +++ b/internal/api/responses.go @@ -17,7 +17,9 @@ func (api *API) jsonResponse(w http.ResponseWriter, status int, payload interfac w.WriteHeader(status) w.Header().Set("Content-Type", "application/json") - w.Write(json) + if _, err := w.Write(json); err != nil { + api.Logger.Error(err) + } } // CreatedSuccesfully responds with a 201. @@ -88,7 +90,7 @@ func (api *API) RateLimitExceeded(w http.ResponseWriter, ip string) { } // Unauthorized responds with a 401. -func (api *API) Unauthorized(err error, code string, w http.ResponseWriter) { +func (api *API) Unauthorized(err error, w http.ResponseWriter) { payload := ErrorResponse{ Error: ErrorField{ Message: "Missing valid authentication credentials.",