all repos

onasty @ c685a65

a one-time notes service
13 files changed, 96 insertions(+), 32 deletions(-)
feat: add cors (#115)

* feat(config): add CORS options

* chore: go get gin's cors middlware

* feat(http): add cors middleware

* fixup! feat(config): add CORS options

* fixup! feat(http): add cors middleware

* fix: e2e tests

* fix: ignore cors.Config struct

* chore(golangci-lint): disable exhaustruct for more cases
Author: Smirnov Oleksandr ss2316544@gmail.com
Committed by: GitHub noreply@github.com
Committed at: 2025-05-23 16:59:35 +0300
Parent: a705387
M .env.example

@@ -5,6 +5,9 @@ NOTE_PASSWORD_SALT=secret

HTTP_PORT=8000 +CORS_ALLOWED_ORIGINS=http://localhost:3000,http://onasty.localhost +CORS_MAX_AGE=12h + METRICS_ENABLED=true METRICS_PORT=8001
M .golangci.yaml

@@ -79,8 +79,10 @@

exhaustruct: exclude: - log/slog\.HandlerOptions - - net/http\.Server + - net/http\.(Server|Client|Response) - github.com/golang-jwt/jwt/v5\.RegisteredClaims + - github.com/gin-contrib/cors\.Config + - github.com/prometheus/client_golang/prometheus\.(CounterOpts|HistogramOpts) funlen: lines: 100
M cmd/server/main.go

@@ -129,6 +129,8 @@

handler := httptransport.NewTransport( usersrv, notesrv, + cfg.CORSAllowedOrigins, + cfg.CORSMaxAge, rateLimiterConfig, )
M e2e/e2e_test.go

@@ -137,7 +137,13 @@ TTL: time.Millisecond,

Burst: 1000, } - handler := httptransport.NewTransport(usersrv, notesrv, ratelimitCfg) + handler := httptransport.NewTransport( + usersrv, + notesrv, + cfg.CORSAllowedOrigins, + cfg.CORSMaxAge, + ratelimitCfg, + ) e.router = handler.Handler() }
M go.mod

@@ -27,11 +27,11 @@ dario.cat/mergo v1.0.1 // indirect

github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bytedance/sonic v1.11.6 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/bytedance/sonic v1.13.2 // indirect + github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/base64x v0.1.5 // indirect github.com/cloudwego/iasm v0.2.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect

@@ -44,16 +44,17 @@ github.com/docker/go-connections v0.5.0 // indirect

github.com/docker/go-units v0.5.0 // indirect github.com/ebitengine/purego v0.8.2 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/cors v1.7.5 // indirect + github.com/gin-contrib/sse v1.0.0 // indirect github.com/go-chi/chi/v5 v5.2.1 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.20.0 // indirect - github.com/goccy/go-json v0.10.2 // indirect + github.com/go-playground/validator/v10 v10.26.0 // indirect + github.com/goccy/go-json v0.10.5 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect

@@ -71,7 +72,7 @@ github.com/jackc/pgx/v4 v4.18.2 // indirect

github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.18.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect

@@ -93,7 +94,7 @@ github.com/nats-io/nkeys v0.4.11 // indirect

github.com/nats-io/nuid v1.0.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect

@@ -113,12 +114,12 @@ go.opentelemetry.io/otel v1.35.0 // indirect

go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect go.uber.org/atomic v1.9.0 // indirect - golang.org/x/arch v0.8.0 // indirect + golang.org/x/arch v0.15.0 // indirect golang.org/x/crypto v0.37.0 // indirect golang.org/x/net v0.38.0 // indirect golang.org/x/sync v0.13.0 // indirect golang.org/x/sys v0.32.0 // indirect golang.org/x/text v0.24.0 // indirect - google.golang.org/protobuf v1.36.5 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect )
M go.sum

@@ -19,14 +19,20 @@ github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=

github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= +github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= +github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 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/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= +github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=

@@ -63,8 +69,14 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=

github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +github.com/gin-contrib/cors v1.7.5 h1:cXC9SmofOrRg0w9PigwGlHG3ztswH6bqq4vJVXnvYMk= +github.com/gin-contrib/cors v1.7.5/go.mod h1:4q3yi7xBEDDWKapjT2o1V7mScKDDr8k+jZ0fSquGoy0= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E= +github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=

@@ -86,9 +98,13 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=

github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k= +github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid/v5 v5.3.2 h1:2jfO8j3XgSwlz/wHqemAEugfnTlikAYHhnqQ8Xh4fE0=

@@ -177,6 +193,8 @@ github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=

github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=

@@ -248,6 +266,8 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=

github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

@@ -353,6 +373,8 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=

golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= +golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

@@ -447,6 +469,8 @@ google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=

google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
M internal/config/config.go

@@ -4,6 +4,7 @@ import (

"errors" "os" "strconv" + "strings" "time" )

@@ -11,6 +12,9 @@ type Config struct {

AppEnv string AppURL string NatsURL string + + CORSAllowedOrigins []string + CORSMaxAge time.Duration HTTPPort int HTTPWriteTimeout time.Duration

@@ -60,6 +64,9 @@ return &Config{

AppEnv: getenvOrDefault("APP_ENV", "debug"), AppURL: getenvOrDefault("APP_URL", ""), NatsURL: getenvOrDefault("NATS_URL", ""), + + CORSAllowedOrigins: strings.Split(getenvOrDefault("CORS_ALLOWED_ORIGINS", "*"), ","), + CORSMaxAge: mustParseDuration(getenvOrDefault("CORS_MAX_AGE", "12h")), HTTPPort: mustGetenvOrDefaultInt("HTTP_PORT", 3000), HTTPWriteTimeout: mustParseDuration(getenvOrDefault("HTTP_WRITE_TIMEOUT", "10s")),
M internal/metrics/http_metrics.go

@@ -8,19 +8,19 @@ "github.com/prometheus/client_golang/prometheus/promauto"

) var ( - successfulHTTPRequest = promauto.NewCounterVec(prometheus.CounterOpts{ //nolint:exhaustruct + successfulHTTPRequest = promauto.NewCounterVec(prometheus.CounterOpts{ Name: "http_successful_requests_total", Help: "the total number of successful http requests", ConstLabels: map[string]string{"status": "success"}, }, []string{"method", "uri"}) - failedHTTPRequest = promauto.NewCounterVec(prometheus.CounterOpts{ //nolint:exhaustruct + failedHTTPRequest = promauto.NewCounterVec(prometheus.CounterOpts{ Name: "http_failed_requests_total", Help: "the total number of failed http requests", ConstLabels: map[string]string{"status": "failure"}, }, []string{"method", "uri"}) - latencyHTTPRequest = promauto.NewHistogramVec(prometheus.HistogramOpts{ //nolint:exhaustruct + latencyHTTPRequest = promauto.NewHistogramVec(prometheus.HistogramOpts{ Name: "http_request_latency_seconds", Help: "the latency of http requests in seconds", Buckets: prometheus.DefBuckets,
M internal/oauth/github_test.go

@@ -35,10 +35,10 @@ userEmail := "test@testing.org"

userLogin := "testing" resp := fmt.Sprintf(`{"id":%s, "email":"%s", "login":"%s"}`, userID, userEmail, userLogin) - client := &http.Client{ //nolint:exhaustruct + client := &http.Client{ Transport: mockClient(func(req *http.Request) (*http.Response, error) { if req.Method == http.MethodPost { - return &http.Response{ //nolint:exhaustruct + return &http.Response{ StatusCode: http.StatusOK, Header: http.Header{"Content-Type": []string{"application/json"}}, Body: io.NopCloser(

@@ -48,7 +48,7 @@ "expires_in":3600}`),

), }, nil } - return &http.Response{ //nolint:exhaustruct + return &http.Response{ StatusCode: http.StatusOK, Header: http.Header{"Content-Type": []string{"application/json"}}, Body: io.NopCloser(strings.NewReader(resp)),

@@ -67,10 +67,10 @@ assert.Equal(t, userEmail, info.Email)

} func TestGitHubProvider_ExchangeCode_tokenExcahnge_error(t *testing.T) { - client := &http.Client{ //nolint:exhaustruct + client := &http.Client{ Transport: mockClient(func(req *http.Request) (*http.Response, error) { if req.Method == http.MethodPost { - return &http.Response{ //nolint:exhaustruct + return &http.Response{ StatusCode: http.StatusBadRequest, Body: io.NopCloser(strings.NewReader("")), }, nil
M internal/oauth/google_test.go

@@ -28,10 +28,10 @@ func TestGoogleProvider_ExchangeCode(t *testing.T) {

sub := "1234567890" email := "testemail@mail.com" resp := fmt.Sprintf(`{"sub":"%s", "email":"%s","email_verified":true}`, sub, email) - client := &http.Client{ //nolint:exhaustruct + client := &http.Client{ Transport: mockClient(func(req *http.Request) (*http.Response, error) { if req.Method == http.MethodPost { - return &http.Response{ //nolint:exhaustruct + return &http.Response{ StatusCode: http.StatusOK, Header: http.Header{"Content-Type": []string{"application/json"}}, Body: io.NopCloser(

@@ -41,7 +41,7 @@ "expires_in":3600}`),

), }, nil } - return &http.Response{ //nolint:exhaustruct + return &http.Response{ StatusCode: http.StatusOK, Header: http.Header{"Content-Type": []string{"application/json"}}, Body: io.NopCloser(strings.NewReader(resp)),
M internal/transport/http/http.go

@@ -2,6 +2,7 @@ package http

import ( "net/http" + "time" "github.com/gin-gonic/gin" "github.com/olexsmir/onasty/internal/service/notesrv"

@@ -15,18 +16,24 @@ type Transport struct {

usersrv usersrv.UserServicer notesrv notesrv.NoteServicer - ratelimitCfg ratelimit.Config + corsAllowedOrigins []string + corsMaxAge time.Duration + ratelimitCfg ratelimit.Config } func NewTransport( us usersrv.UserServicer, ns notesrv.NoteServicer, + corsAllowedOrigins []string, + corsMaxAge time.Duration, ratelimitCfg ratelimit.Config, ) *Transport { return &Transport{ - usersrv: us, - notesrv: ns, - ratelimitCfg: ratelimitCfg, + usersrv: us, + notesrv: ns, + corsAllowedOrigins: corsAllowedOrigins, + corsMaxAge: corsMaxAge, + ratelimitCfg: ratelimitCfg, } }

@@ -35,7 +42,8 @@ r := gin.New()

r.Use( gin.Recovery(), reqid.Middleware(), - t.logger(), + t.loggerMiddleware(), + t.corsMiddleware(), ratelimit.MiddlewareWithConfig(t.ratelimitCfg), )
M internal/transport/http/middlewares.go

@@ -4,10 +4,21 @@ import (

"log/slog" "time" + "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" ) -func (t *Transport) logger() gin.HandlerFunc { +func (t *Transport) corsMiddleware() gin.HandlerFunc { + return cors.New(cors.Config{ + AllowOrigins: t.corsAllowedOrigins, + AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, + AllowHeaders: []string{"Authorization", "Content-Type"}, + AllowCredentials: true, + MaxAge: t.corsMaxAge, + }) +} + +func (t *Transport) loggerMiddleware() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() path := c.Request.URL.Path
M mailer/metrics.go

@@ -9,12 +9,12 @@ "github.com/prometheus/client_golang/prometheus/promhttp"

) var ( - emailSentSuccessfully = promauto.NewCounter(prometheus.CounterOpts{ //nolint:exhaustruct + emailSentSuccessfully = promauto.NewCounter(prometheus.CounterOpts{ Name: "mail_sent_total", Help: "the total number of successfully sent email", }) - emailFailedToSend = promauto.NewCounterVec(prometheus.CounterOpts{ //nolint:exhaustruct + emailFailedToSend = promauto.NewCounterVec(prometheus.CounterOpts{ Name: "mail_failed_total", Help: "the total number of email that failed to send", }, []string{"request_id"})