diff --git a/.gitignore b/.gitignore index 94b72508e..6beef828b 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,7 @@ tus/upload-cli upload_download/upload_download upload_download/upload_download-cli basic/cmd/calc/calc +interceptors/cmd/example/example +.vscode/settings.json +interceptors/cmd/tokgen/tokgen +interceptors/bin/ diff --git a/basic/Makefile b/basic/Makefile index 29226cc96..3d27821a9 100644 --- a/basic/Makefile +++ b/basic/Makefile @@ -1,100 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=calc - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! - -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: clean - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" +# Makefile for Goa interceptors example -test: - @echo TESTING... - @go test ./... > /dev/null +APP=basic -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../common.mk diff --git a/basic/go.mod b/basic/go.mod index 15fc62a44..385a8ea43 100644 --- a/basic/go.mod +++ b/basic/go.mod @@ -21,7 +21,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/basic/go.sum b/basic/go.sum index 87bea91b1..dc6c81857 100644 --- a/basic/go.sum +++ b/basic/go.sum @@ -1,5 +1,6 @@ github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE= github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -22,15 +23,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -72,7 +76,7 @@ google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40Rmc 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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cellar/Makefile b/cellar/Makefile index 282ca6466..339203ac4 100644 --- a/cellar/Makefile +++ b/cellar/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=cellar - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 cellar example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=cellar -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../common.mk diff --git a/cellar/go.mod b/cellar/go.mod index 9da69fc95..a5f66834f 100644 --- a/cellar/go.mod +++ b/cellar/go.mod @@ -18,7 +18,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/cellar/go.sum b/cellar/go.sum index 8867286df..9ad4308af 100644 --- a/cellar/go.sum +++ b/cellar/go.sum @@ -1,5 +1,6 @@ github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -20,15 +21,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -64,7 +68,7 @@ google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40Rmc 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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/common.mk b/common.mk new file mode 100644 index 000000000..7cc0bcf28 --- /dev/null +++ b/common.mk @@ -0,0 +1,85 @@ +# Common variables +GO_FILES=$(shell find . -type f -name '*.go') +MODULE=$(shell head -n1 go.mod | cut -d ' ' -f2) + +# Dependencies +DEPEND=\ + github.com/hashicorp/go-getter \ + github.com/cheggaaa/pb \ + github.com/golang/protobuf/protoc-gen-go \ + github.com/golang/protobuf/proto \ + goa.design/goa/... \ + golang.org/x/lint/golint \ + golang.org/x/tools/cmd/goimports \ + honnef.co/go/tools/cmd/staticcheck + +# Protoc setup +GOOS=$(shell go env GOOS) +PROTOC_VERSION=28.3 +ifeq ($(GOOS),linux) +PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 +PROTOC_EXEC=$(PROTOC)/bin/protoc +GOBIN=$(GOPATH)/bin +else + ifeq ($(GOOS),darwin) +PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 +PROTOC_EXEC=$(PROTOC)/bin/protoc +GOBIN=$(GOPATH)/bin + else + ifeq ($(GOOS),windows) +PROTOC=protoc-$(PROTOC_VERSION)-win32 +PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" +GOBIN="$(GOPATH)\bin" + endif + endif +endif + +# Common targets +.PHONY: all depend lint test build clean gen check-freshness + +all: gen lint test + @echo DONE! + +depend: + @echo INSTALLING DEPENDENCIES... + @go get -v $(DEPEND) + @go install github.com/hashicorp/go-getter/cmd/go-getter && \ + go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ + cp $(PROTOC_EXEC) $(GOBIN) && \ + rm -r $(PROTOC) + @go install github.com/golang/protobuf/protoc-gen-go + @go get -t -v ./... + +lint: + @echo LINTING CODE... + @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ + echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ + fi + @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ + echo "^ - staticcheck errors!" && echo && exit 1; \ + fi + +gen: + @echo GENERATING CODE... + @goa gen "$(MODULE)/design" && \ + goa example "$(MODULE)/design" + +build: + @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" + +clean: + @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" + +test: + @echo TESTING... + @go test ./... > /dev/null + +check-freshness: + @if [ "`git diff | wc -l`" -gt "0" ]; then \ + echo "[ERROR] generated code not in-sync with design:"; \ + echo; \ + git status -s; \ + git --no-pager diff; \ + echo; \ + exit 1; \ + fi diff --git a/cookies/Makefile b/cookies/Makefile index 262e87880..329c06106 100644 --- a/cookies/Makefile +++ b/cookies/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=cookies - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 cookies example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=cookies -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../common.mk diff --git a/cookies/go.mod b/cookies/go.mod index 81e5af6ed..49431a2ce 100644 --- a/cookies/go.mod +++ b/cookies/go.mod @@ -16,7 +16,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/cookies/go.sum b/cookies/go.sum index ccefce09b..7b0e9db9c 100644 --- a/cookies/go.sum +++ b/cookies/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -12,17 +13,23 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -38,7 +45,7 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/encodings/cbor/Makefile b/encodings/cbor/Makefile index 07b48f086..6b7c6e921 100644 --- a/encodings/cbor/Makefile +++ b/encodings/cbor/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=concat - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 CBOR example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=concat -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../../common.mk diff --git a/encodings/cbor/go.mod b/encodings/cbor/go.mod index ccc5e56a0..5c439b18f 100644 --- a/encodings/cbor/go.mod +++ b/encodings/cbor/go.mod @@ -16,7 +16,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/encodings/cbor/go.sum b/encodings/cbor/go.sum index c2223b950..07af77ae7 100644 --- a/encodings/cbor/go.sum +++ b/encodings/cbor/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -14,15 +15,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -40,7 +44,7 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/encodings/text/Makefile b/encodings/text/Makefile index e1baef21d..4d54a19f7 100644 --- a/encodings/text/Makefile +++ b/encodings/text/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=text - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 text example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=text -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../../common.mk diff --git a/encodings/text/go.mod b/encodings/text/go.mod index d4e335df0..93d503def 100644 --- a/encodings/text/go.mod +++ b/encodings/text/go.mod @@ -13,7 +13,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/encodings/text/go.sum b/encodings/text/go.sum index 4a6d9c950..e77c6890c 100644 --- a/encodings/text/go.sum +++ b/encodings/text/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -12,15 +13,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -36,7 +40,7 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/error/Makefile b/error/Makefile index a0c3eb506..fec25538c 100644 --- a/error/Makefile +++ b/error/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=calc - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 error example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=calc -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../common.mk diff --git a/error/cmd/calc-cli/grpc.go b/error/cmd/calc-cli/grpc.go index 3c174fddd..fa0bae99e 100644 --- a/error/cmd/calc-cli/grpc.go +++ b/error/cmd/calc-cli/grpc.go @@ -8,10 +8,13 @@ import ( goa "goa.design/goa/v3/pkg" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + + // See: https://github.com/googleapis/google-api-go-client/issues/2559. + _ "google.golang.org/genproto/googleapis/type/datetime" ) -func doGRPC(scheme, host string, timeout int, debug bool) (goa.Endpoint, any, error) { - conn, err := grpc.Dial(host, grpc.WithTransportCredentials(insecure.NewCredentials())) +func doGRPC(_, host string, _ int, _ bool) (goa.Endpoint, any, error) { + conn, err := grpc.NewClient(host, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { fmt.Fprintf(os.Stderr, "could not connect to gRPC server at %s: %v\n", host, err) } diff --git a/error/go.mod b/error/go.mod index 8788e5f9f..82ca1bd37 100644 --- a/error/go.mod +++ b/error/go.mod @@ -17,7 +17,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/error/go.sum b/error/go.sum index 3cdabe2cd..5df8b738d 100644 --- a/error/go.sum +++ b/error/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -18,15 +19,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -62,7 +66,7 @@ google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40Rmc 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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/files/Makefile b/files/Makefile index 99a2ca1c5..87a9ee847 100644 --- a/files/Makefile +++ b/files/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=openapi - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 files example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=openapi -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../common.mk diff --git a/files/go.mod b/files/go.mod index e4a738ac0..c44e521ad 100644 --- a/files/go.mod +++ b/files/go.mod @@ -13,7 +13,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/files/go.sum b/files/go.sum index 4a6d9c950..e77c6890c 100644 --- a/files/go.sum +++ b/files/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -12,15 +13,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -36,7 +40,7 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go.sum b/go.sum deleted file mode 100644 index c0423dc32..000000000 --- a/go.sum +++ /dev/null @@ -1,173 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/AnatolyRugalev/goregen v0.1.0 h1:xrdXkLaskMnbxW0x4FWNj2yoednv0X2bcTBWpuJGYfE= -github.com/AnatolyRugalev/goregen v0.1.0/go.mod h1:sVlY1tjcirqLBRZnCcIq1+7/Lwmqz5g7IK8AStjOVzI= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -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= -github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= -github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598/go.mod h1:0FpDmbrt36utu8jEmeU05dPC9AB5tsLYVVi+ZHfyuwI= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= -github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= -github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= -github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= -github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= -github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -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= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -goa.design/goa/v3 v3.13.2 h1:RclNIpo7891ZqGRVO4fpBjT7Fs7LjBNm78i8J41KHrI= -goa.design/goa/v3 v3.13.2/go.mod h1:VvZsuC8CSIUQOHVqk6Ep3MFSFz21OjOv87UPqCHiB94= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I= -google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -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-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/go.work b/go.work new file mode 100644 index 000000000..b45211a4b --- /dev/null +++ b/go.work @@ -0,0 +1,20 @@ +go 1.23.3 + +use ( + ./basic + ./cellar + ./cookies + ./encodings/cbor + ./encodings/text + ./error + ./files + ./httpstatus + ./interceptors + ./multipart + ./security/hierarchy + ./security/multiauth + ./streaming + ./tracing + ./tus + ./upload_download +) diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 000000000..1e113fe19 --- /dev/null +++ b/go.work.sum @@ -0,0 +1,308 @@ +cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= +cel.dev/expr v0.16.1/go.mod h1:AsGA5zb3WruAEQeQng1RZdGEXmBj0jvMWh6l5SnNuC8= +cel.dev/expr v0.16.2/go.mod h1:gXngZQMkWJoSbE8mOzehJlXQyubn/Vg0vR9/F3W7iw8= +cel.dev/expr v0.19.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= +cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= +cloud.google.com/go/accessapproval v1.8.2/go.mod h1:aEJvHZtpjqstffVwF/2mCXXSQmpskyzvw6zKLvLutZM= +cloud.google.com/go/accesscontextmanager v1.9.2/go.mod h1:T0Sw/PQPyzctnkw1pdmGAKb7XBA84BqQzH0fSU7wzJU= +cloud.google.com/go/aiplatform v1.68.0/go.mod h1:105MFA3svHjC3Oazl7yjXAmIR89LKhRAeNdnDKJczME= +cloud.google.com/go/analytics v0.25.2/go.mod h1:th0DIunqrhI1ZWVlT3PH2Uw/9ANX8YHfFDEPqf/+7xM= +cloud.google.com/go/apigateway v1.7.2/go.mod h1:+weId+9aR9J6GRwDka7jIUSrKEX60XGcikX7dGU8O7M= +cloud.google.com/go/apigeeconnect v1.7.2/go.mod h1:he/SWi3A63fbyxrxD6jb67ak17QTbWjva1TFbT5w8Kw= +cloud.google.com/go/apigeeregistry v0.9.2/go.mod h1:A5n/DwpG5NaP2fcLYGiFA9QfzpQhPRFNATO1gie8KM8= +cloud.google.com/go/appengine v1.9.2/go.mod h1:bK4dvmMG6b5Tem2JFZcjvHdxco9g6t1pwd3y/1qr+3s= +cloud.google.com/go/area120 v0.9.2/go.mod h1:Ar/KPx51UbrTWGVGgGzFnT7hFYQuk/0VOXkvHdTbQMI= +cloud.google.com/go/artifactregistry v1.16.0/go.mod h1:LunXo4u2rFtvJjrGjO0JS+Gs9Eco2xbZU6JVJ4+T8Sk= +cloud.google.com/go/asset v1.20.3/go.mod h1:797WxTDwdnFAJzbjZ5zc+P5iwqXc13yO9DHhmS6wl+o= +cloud.google.com/go/assuredworkloads v1.12.2/go.mod h1:/WeRr/q+6EQYgnoYrqCVgw7boMoDfjXZZev3iJxs2Iw= +cloud.google.com/go/auth v0.9.9/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= +cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go/automl v1.14.2/go.mod h1:mIat+Mf77W30eWQ/vrhjXsXaRh8Qfu4WiymR0hR6Uxk= +cloud.google.com/go/baremetalsolution v1.3.2/go.mod h1:3+wqVRstRREJV/puwaKAH3Pnn7ByreZG2aFRsavnoBQ= +cloud.google.com/go/batch v1.11.2/go.mod h1:ehsVs8Y86Q4K+qhEStxICqQnNqH8cqgpCxx89cmU5h4= +cloud.google.com/go/beyondcorp v1.1.2/go.mod h1:q6YWSkEsSZTU2WDt1qtz6P5yfv79wgktGtNbd0FJTLI= +cloud.google.com/go/bigquery v1.64.0/go.mod h1:gy8Ooz6HF7QmA+TRtX8tZmXBKH5mCFBwUApGAb3zI7Y= +cloud.google.com/go/bigtable v1.33.0/go.mod h1:HtpnH4g25VT1pejHRtInlFPnN5sjTxbQlsYBjh9t5l0= +cloud.google.com/go/billing v1.19.2/go.mod h1:AAtih/X2nka5mug6jTAq8jfh1nPye0OjkHbZEZgU59c= +cloud.google.com/go/binaryauthorization v1.9.2/go.mod h1:T4nOcRWi2WX4bjfSRXJkUnpliVIqjP38V88Z10OvEv4= +cloud.google.com/go/certificatemanager v1.9.2/go.mod h1:PqW+fNSav5Xz8bvUnJpATIRo1aaABP4mUg/7XIeAn6c= +cloud.google.com/go/channel v1.19.1/go.mod h1:ungpP46l6XUeuefbA/XWpWWnAY3897CSRPXUbDstwUo= +cloud.google.com/go/cloudbuild v1.19.0/go.mod h1:ZGRqbNMrVGhknIIjwASa6MqoRTOpXIVMSI+Ew5DMPuY= +cloud.google.com/go/clouddms v1.8.2/go.mod h1:pe+JSp12u4mYOkwXpSMouyCCuQHL3a6xvWH2FgOcAt4= +cloud.google.com/go/cloudtasks v1.13.2/go.mod h1:2pyE4Lhm7xY8GqbZKLnYk7eeuh8L0JwAvXx1ecKxYu8= +cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.28.3/go.mod h1:HFlsDurE5DpQZClAGf/cYh+gxssMhBxBovZDYkEn/Og= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= +cloud.google.com/go/contactcenterinsights v1.15.1/go.mod h1:cFGxDVm/OwEVAHbU9UO4xQCtQFn0RZSrSUcF/oJ0Bbs= +cloud.google.com/go/container v1.41.0/go.mod h1:YL6lDgCUi3frIWNIFU9qrmF7/6K1EYrtspmFTyyqJ+k= +cloud.google.com/go/containeranalysis v0.13.2/go.mod h1:AiKvXJkc3HiqkHzVIt6s5M81wk+q7SNffc6ZlkTDgiE= +cloud.google.com/go/datacatalog v1.22.2/go.mod h1:9Wamq8TDfL2680Sav7q3zEhBJSPBrDxJU8WtPJ25dBM= +cloud.google.com/go/dataflow v0.10.2/go.mod h1:+HIb4HJxDCZYuCqDGnBHZEglh5I0edi/mLgVbxDf0Ag= +cloud.google.com/go/dataform v0.10.2/go.mod h1:oZHwMBxG6jGZCVZqqMx+XWXK+dA/ooyYiyeRbUxI15M= +cloud.google.com/go/datafusion v1.8.2/go.mod h1:XernijudKtVG/VEvxtLv08COyVuiYPraSxm+8hd4zXA= +cloud.google.com/go/datalabeling v0.9.2/go.mod h1:8me7cCxwV/mZgYWtRAd3oRVGFD6UyT7hjMi+4GRyPpg= +cloud.google.com/go/dataplex v1.19.2/go.mod h1:vsxxdF5dgk3hX8Ens9m2/pMNhQZklUhSgqTghZtF1v4= +cloud.google.com/go/dataproc/v2 v2.10.0/go.mod h1:HD16lk4rv2zHFhbm8gGOtrRaFohMDr9f0lAUMLmg1PM= +cloud.google.com/go/dataqna v0.9.2/go.mod h1:WCJ7pwD0Mi+4pIzFQ+b2Zqy5DcExycNKHuB+VURPPgs= +cloud.google.com/go/datastore v1.20.0/go.mod h1:uFo3e+aEpRfHgtp5pp0+6M0o147KoPaYNaPAKpfh8Ew= +cloud.google.com/go/datastream v1.11.2/go.mod h1:RnFWa5zwR5SzHxeZGJOlQ4HKBQPcjGfD219Qy0qfh2k= +cloud.google.com/go/deploy v1.24.0/go.mod h1:h9uVCWxSDanXUereI5WR+vlZdbPJ6XGy+gcfC25v5rM= +cloud.google.com/go/dialogflow v1.59.0/go.mod h1:PjsrI+d2FI4BlGThxL0+Rua/g9vLI+2A1KL7s/Vo3pY= +cloud.google.com/go/dlp v1.20.0/go.mod h1:nrGsA3r8s7wh2Ct9FWu69UjBObiLldNyQda2RCHgdaY= +cloud.google.com/go/documentai v1.35.0/go.mod h1:ZotiWUlDE8qXSUqkJsGMQqVmfTMYATwJEYqbPXTR9kk= +cloud.google.com/go/domains v0.10.2/go.mod h1:oL0Wsda9KdJvvGNsykdalHxQv4Ri0yfdDkIi3bzTUwk= +cloud.google.com/go/edgecontainer v1.4.0/go.mod h1:Hxj5saJT8LMREmAI9tbNTaBpW5loYiWFyisCjDhzu88= +cloud.google.com/go/errorreporting v0.3.1/go.mod h1:6xVQXU1UuntfAf+bVkFk6nld41+CPyF2NSPCyXE3Ztk= +cloud.google.com/go/essentialcontacts v1.7.2/go.mod h1:NoCBlOIVteJFJU+HG9dIG/Cc9kt1K9ys9mbOaGPUmPc= +cloud.google.com/go/eventarc v1.15.0/go.mod h1:PAd/pPIZdJtJQFJI1yDEUms1mqohdNuM1BFEVHHlVFg= +cloud.google.com/go/filestore v1.9.2/go.mod h1:I9pM7Hoetq9a7djC1xtmtOeHSUYocna09ZP6x+PG1Xw= +cloud.google.com/go/firestore v1.17.0/go.mod h1:69uPx1papBsY8ZETooc71fOhoKkD70Q1DwMrtKuOT/Y= +cloud.google.com/go/functions v1.19.2/go.mod h1:SBzWwWuaFDLnUyStDAMEysVN1oA5ECLbP3/PfJ9Uk7Y= +cloud.google.com/go/gkebackup v1.6.2/go.mod h1:WsTSWqKJkGan1pkp5dS30oxb+Eaa6cLvxEUxKTUALwk= +cloud.google.com/go/gkeconnect v0.11.2/go.mod h1:+Sj47chrbFMON1wjG6DA4KJKi85/7ON7GQZXEo0cbaQ= +cloud.google.com/go/gkehub v0.15.2/go.mod h1:8YziTOpwbM8LM3r9cHaOMy2rNgJHXZCrrmGgcau9zbQ= +cloud.google.com/go/gkemulticloud v1.4.1/go.mod h1:KRvPYcx53bztNwNInrezdfNF+wwUom8Y3FuJBwhvFpQ= +cloud.google.com/go/grafeas v0.3.11/go.mod h1:dcQyG2+T4tBgG0MvJAh7g2wl/xHV2w+RZIqivwuLjNg= +cloud.google.com/go/gsuiteaddons v1.7.2/go.mod h1:GD32J2rN/4APilqZw4JKmwV84+jowYYMkEVwQEYuAWc= +cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= +cloud.google.com/go/iap v1.10.2/go.mod h1:cClgtI09VIfazEK6VMJr6bX8KQfuQ/D3xqX+d0wrUlI= +cloud.google.com/go/ids v1.5.2/go.mod h1:P+ccDD96joXlomfonEdCnyrHvE68uLonc7sJBPVM5T0= +cloud.google.com/go/iot v1.8.2/go.mod h1:UDwVXvRD44JIcMZr8pzpF3o4iPsmOO6fmbaIYCAg1ww= +cloud.google.com/go/kms v1.20.1/go.mod h1:LywpNiVCvzYNJWS9JUcGJSVTNSwPwi0vBAotzDqn2nc= +cloud.google.com/go/language v1.14.2/go.mod h1:dviAbkxT9art+2ioL9AM05t+3Ql6UPfMpwq1cDsF+rg= +cloud.google.com/go/lifesciences v0.10.2/go.mod h1:vXDa34nz0T/ibUNoeHnhqI+Pn0OazUTdxemd0OLkyoY= +cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= +cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= +cloud.google.com/go/managedidentities v1.7.2/go.mod h1:t0WKYzagOoD3FNtJWSWcU8zpWZz2i9cw2sKa9RiPx5I= +cloud.google.com/go/maps v1.14.1/go.mod h1:ZFqZS04ucwFiHSNU8TBYDUr3wYhj5iBFJk24Ibvpf3o= +cloud.google.com/go/mediatranslation v0.9.2/go.mod h1:1xyRoDYN32THzy+QaU62vIMciX0CFexplju9t30XwUc= +cloud.google.com/go/memcache v1.11.2/go.mod h1:jIzHn79b0m5wbkax2SdlW5vNSbpaEk0yWHbeLpMIYZE= +cloud.google.com/go/metastore v1.14.2/go.mod h1:dk4zOBhZIy3TFOQlI8sbOa+ef0FjAcCHEnd8dO2J+LE= +cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= +cloud.google.com/go/networkconnectivity v1.15.2/go.mod h1:N1O01bEk5z9bkkWwXLKcN2T53QN49m/pSpjfUvlHDQY= +cloud.google.com/go/networkmanagement v1.15.0/go.mod h1:Yc905R9U5jik5YMt76QWdG5WqzPU4ZsdI/mLnVa62/Q= +cloud.google.com/go/networksecurity v0.10.2/go.mod h1:puU3Gwchd6Y/VTyMkL50GI2RSRMS3KXhcDBY1HSOcck= +cloud.google.com/go/notebooks v1.12.2/go.mod h1:EkLwv8zwr8DUXnvzl944+sRBG+b73HEKzV632YYAGNI= +cloud.google.com/go/optimization v1.7.2/go.mod h1:msYgDIh1SGSfq6/KiWJQ/uxMkWq8LekPyn1LAZ7ifNE= +cloud.google.com/go/orchestration v1.11.1/go.mod h1:RFHf4g88Lbx6oKhwFstYiId2avwb6oswGeAQ7Tjjtfw= +cloud.google.com/go/orgpolicy v1.14.1/go.mod h1:1z08Hsu1mkoH839X7C8JmnrqOkp2IZRSxiDw7W/Xpg4= +cloud.google.com/go/osconfig v1.14.2/go.mod h1:kHtsm0/j8ubyuzGciBsRxFlbWVjc4c7KdrwJw0+g+pQ= +cloud.google.com/go/oslogin v1.14.2/go.mod h1:M7tAefCr6e9LFTrdWRQRrmMeKHbkvc4D9g6tHIjHySA= +cloud.google.com/go/phishingprotection v0.9.2/go.mod h1:mSCiq3tD8fTJAuXq5QBHFKZqMUy8SfWsbUM9NpzJIRQ= +cloud.google.com/go/policytroubleshooter v1.11.2/go.mod h1:1TdeCRv8Qsjcz2qC3wFltg/Mjga4HSpv8Tyr5rzvPsw= +cloud.google.com/go/privatecatalog v0.10.2/go.mod h1:o124dHoxdbO50ImR3T4+x3GRwBSTf4XTn6AatP8MgsQ= +cloud.google.com/go/pubsub v1.45.1/go.mod h1:3bn7fTmzZFwaUjllitv1WlsNMkqBgGUb3UdMhI54eCc= +cloud.google.com/go/pubsublite v1.8.2/go.mod h1:4r8GSa9NznExjuLPEJlF1VjOPOpgf3IT6k8x/YgaOPI= +cloud.google.com/go/recaptchaenterprise/v2 v2.18.0/go.mod h1:vnbA2SpVPPwKeoFrCQxR+5a0JFRRytwBBG69Zj9pGfk= +cloud.google.com/go/recommendationengine v0.9.2/go.mod h1:DjGfWZJ68ZF5ZuNgoTVXgajFAG0yLt4CJOpC0aMK3yw= +cloud.google.com/go/recommender v1.13.2/go.mod h1:XJau4M5Re8F4BM+fzF3fqSjxNJuM66fwF68VCy/ngGE= +cloud.google.com/go/redis v1.17.2/go.mod h1:h071xkcTMnJgQnU/zRMOVKNj5J6AttG16RDo+VndoNo= +cloud.google.com/go/resourcemanager v1.10.2/go.mod h1:5f+4zTM/ZOTDm6MmPOp6BQAhR0fi8qFPnvVGSoWszcc= +cloud.google.com/go/resourcesettings v1.8.2/go.mod h1:uEgtPiMA+xuBUM4Exu+ZkNpMYP0BLlYeJbyNHfrc+U0= +cloud.google.com/go/retail v1.19.1/go.mod h1:W48zg0zmt2JMqmJKCuzx0/0XDLtovwzGAeJjmv6VPaE= +cloud.google.com/go/run v1.6.1/go.mod h1:IvJOg2TBb/5a0Qkc6crn5yTy5nkjcgSWQLhgO8QL8PQ= +cloud.google.com/go/scheduler v1.11.2/go.mod h1:GZSv76T+KTssX2I9WukIYQuQRf7jk1WI+LOcIEHUUHk= +cloud.google.com/go/secretmanager v1.14.2/go.mod h1:Q18wAPMM6RXLC/zVpWTlqq2IBSbbm7pKBlM3lCKsmjw= +cloud.google.com/go/security v1.18.2/go.mod h1:3EwTcYw8554iEtgK8VxAjZaq2unFehcsgFIF9nOvQmU= +cloud.google.com/go/securitycenter v1.35.2/go.mod h1:AVM2V9CJvaWGZRHf3eG+LeSTSissbufD27AVBI91C8s= +cloud.google.com/go/servicedirectory v1.12.2/go.mod h1:F0TJdFjqqotiZRlMXgIOzszaplk4ZAmUV8ovHo08M2U= +cloud.google.com/go/shell v1.8.2/go.mod h1:QQR12T6j/eKvqAQLv6R3ozeoqwJ0euaFSz2qLqG93Bs= +cloud.google.com/go/spanner v1.72.0/go.mod h1:mw98ua5ggQXVWwp83yjwggqEmW9t8rjs9Po1ohcUGW4= +cloud.google.com/go/speech v1.25.2/go.mod h1:KPFirZlLL8SqPaTtG6l+HHIFHPipjbemv4iFg7rTlYs= +cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= +cloud.google.com/go/storagetransfer v1.11.2/go.mod h1:FcM29aY4EyZ3yVPmW5SxhqUdhjgPBUOFyy4rqiQbias= +cloud.google.com/go/talent v1.7.2/go.mod h1:k1sqlDgS9gbc0gMTRuRQpX6C6VB7bGUxSPcoTRWJod8= +cloud.google.com/go/texttospeech v1.10.0/go.mod h1:215FpCOyRxxrS7DSb2t7f4ylMz8dXsQg8+Vdup5IhP4= +cloud.google.com/go/tpu v1.7.2/go.mod h1:0Y7dUo2LIbDUx0yQ/vnLC6e18FK6NrDfAhYS9wZ/2vs= +cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= +cloud.google.com/go/translate v1.12.2/go.mod h1:jjLVf2SVH2uD+BNM40DYvRRKSsuyKxVvs3YjTW/XSWY= +cloud.google.com/go/video v1.23.2/go.mod h1:rNOr2pPHWeCbW0QsOwJRIe0ZiuwHpHtumK0xbiYB1Ew= +cloud.google.com/go/videointelligence v1.12.2/go.mod h1:8xKGlq0lNVyT8JgTkkCUCpyNJnYYEJVWGdqzv+UcwR8= +cloud.google.com/go/vision/v2 v2.9.2/go.mod h1:WuxjVQdAy4j4WZqY5Rr655EdAgi8B707Vdb5T8c90uo= +cloud.google.com/go/vmmigration v1.8.2/go.mod h1:FBejrsr8ZHmJb949BSOyr3D+/yCp9z9Hk0WtsTiHc1Q= +cloud.google.com/go/vmwareengine v1.3.2/go.mod h1:JsheEadzT0nfXOGkdnwtS1FhFAnj4g8qhi4rKeLi/AU= +cloud.google.com/go/vpcaccess v1.8.2/go.mod h1:4yvYKNjlNjvk/ffgZ0PuEhpzNJb8HybSM1otG2aDxnY= +cloud.google.com/go/webrisk v1.10.2/go.mod h1:c0ODT2+CuKCYjaeHO7b0ni4CUrJ95ScP5UFl9061Qq8= +cloud.google.com/go/websecurityscanner v1.7.2/go.mod h1:728wF9yz2VCErfBaACA5px2XSYHQgkK812NmHcUsDXA= +cloud.google.com/go/workflows v1.13.2/go.mod h1:l5Wj2Eibqba4BsADIRzPLaevLmIuYF2W+wfFBkRG3vU= +github.com/AnatolyRugalev/goregen v0.1.0/go.mod h1:sVlY1tjcirqLBRZnCcIq1+7/Lwmqz5g7IK8AStjOVzI= +github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.1/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.2/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA= +github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/bazelbuild/rules_go v0.49.0/go.mod h1:Dhcz716Kqg1RHNWos+N6MlXNkjNP2EwZQ0LukRKJfMs= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= +github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw= +github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/getkin/kin-openapi v0.127.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM= +github.com/getkin/kin-openapi v0.128.0 h1:jqq3D9vC9pPq1dGcOCv7yOp1DaEe7c/T1vzcLbITSp4= +github.com/getkin/kin-openapi v0.128.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM= +github.com/getkin/kin-openapi v0.129.0 h1:QGYTNcmyP5X0AtFQ2Dkou9DGBJsUETeLH9rFrJXZh30= +github.com/getkin/kin-openapi v0.129.0/go.mod h1:gmWI+b/J45xqpyK5wJmRRZse5wefA5H0RDMK46kLUtI= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/gohugoio/hashstructure v0.3.0/go.mod h1:8ohPTAfQLTs2WdzB6k9etmQYclDUeNsIHGPAFejbsEA= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.3/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= +github.com/googleapis/cloud-bigtable-clients-test v0.0.2/go.mod h1:mk3CrkrouRgtnhID6UZQDK3DrFFa7cYCAJcEmNsHYrY= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= +github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 h1:nZspmSkneBbtxU9TopEAE0CY+SBJLxO8LPUlw2vG4pU= +github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8= +github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 h1:t05Ww3DxZutOqbMN+7OIuqDwXbhl32HiZGpLy26BAPc= +github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +go.einride.tech/aip v0.68.0/go.mod h1:7y9FF8VtPWqpxuAxl0KQWqaULxW4zFIesD6zF5RIHHg= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/detectors/gcp v1.29.0/go.mod h1:GW2aWZNwR2ZxDLdv8OyC2G8zkRoQBuURgV7RPQgcPoU= +go.opentelemetry.io/contrib/detectors/gcp v1.31.0/go.mod h1:tzQL6E1l+iV44YFTkcAeNQqzXUiekSYP9jjJjXwEd00= +go.opentelemetry.io/contrib/detectors/gcp v1.32.0/go.mod h1:TVqo0Sda4Cv8gCIixd7LuLwW4EylumVWfhjZJjDD4DU= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0/go.mod h1:xJntEd2KL6Qdg5lwp97HMLQDVeAhrYxmzFseAMDPQ8I= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0/go.mod h1:MdEu/mC6j3D+tTEfvI15b5Ci2Fn7NneJ71YMoiS3tpI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0/go.mod h1:TNupZ6cxqyFEpLXAZW7On+mLFL0/g0TE3unIYL91xWc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.31.0/go.mod h1:hg1zaDMpyZJuUzjFxFsRYBoccE86tM9Uf4IqNMUxvrY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.27.0/go.mod h1:bmToOGOBZ4hA9ghphIc1PAf66VA8KOtsuy3+ScStG20= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.31.0/go.mod h1:RDRhvt6TDG0eIXmonAx5bd9IcwpqCkziwkOClzWKwAQ= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +goa.design/goa/v3 v3.20.0-rc1.0.20250211061628-8b56a61ddd45 h1:f+5OzpZIvCKrk+yAtuzkE48TuYsMngO12yRmDlQx+0c= +goa.design/goa/v3 v3.20.0-rc1.0.20250211061628-8b56a61ddd45/go.mod h1:YFTHST5DUS9dPdL42h3o/Wtdb9VU6tKbytBxc5hOeLU= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +google.golang.org/api v0.203.0/go.mod h1:BuOVyCSYEPwJb3npWvDnNmFI92f3GeRnHNkETneT3SI= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215 h1:0Uz5jLJQioKgVozXa1gzGbzYxbb/rhQEVvSWxzw5oUs= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53/go.mod h1:fheguH3Am2dGp1LfXkrvwqC/KlFq8F0nLq3LryOMrrE= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= +google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a/go.mod h1:jehYqy3+AhJU9ve55aNOaSml7wUXjF9x6z2LcCfpAhY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 h1:Z7FRVJPSMaHQxD0uXU8WdgFh8PseLM8Q8NzhnpMrBhQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= +google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ= +google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/httpstatus/go.mod b/httpstatus/go.mod index addab22c8..2a3181eb3 100644 --- a/httpstatus/go.mod +++ b/httpstatus/go.mod @@ -2,19 +2,23 @@ module goa.design/examples/httpstatus go 1.22.2 -require goa.design/goa/v3 v3.15.2 +require goa.design/goa/v3 v3.19.1 require ( - github.com/AnatolyRugalev/goregen v0.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 // indirect - github.com/go-chi/chi/v5 v5.0.12 // indirect + github.com/go-chi/chi/v5 v5.1.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect - github.com/sergi/go-diff v1.3.1 // indirect - golang.org/x/mod v0.16.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.19.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/stretchr/testify v1.9.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/tools v0.27.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/httpstatus/go.sum b/httpstatus/go.sum index 6ee812b82..b6e70f0c1 100644 --- a/httpstatus/go.sum +++ b/httpstatus/go.sum @@ -1,49 +1,30 @@ -github.com/AnatolyRugalev/goregen v0.1.0 h1:xrdXkLaskMnbxW0x4FWNj2yoednv0X2bcTBWpuJGYfE= -github.com/AnatolyRugalev/goregen v0.1.0/go.mod h1:sVlY1tjcirqLBRZnCcIq1+7/Lwmqz5g7IK8AStjOVzI= -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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598/go.mod h1:0FpDmbrt36utu8jEmeU05dPC9AB5tsLYVVi+ZHfyuwI= -github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= -github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= 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= -goa.design/goa/v3 v3.15.2 h1:ziyJuVR+GSBBmQ/Nkr7FDZx9qtEBpRA6wle3hYqJT9Q= -goa.design/goa/v3 v3.15.2/go.mod h1:zZLxqfk8mZu0Q6fmnnflXYbIJ6BA3SVSB6LSz7Tzcv4= -golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= -golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= -golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +goa.design/goa/v3 v3.19.1 h1:jpV3LEy7YANzPMwm++Lu17RoThRJgXrPxdEM0A1nlOE= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/interceptors/.vscode/settings.json b/interceptors/.vscode/settings.json new file mode 100644 index 000000000..082b19437 --- /dev/null +++ b/interceptors/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "makefile.configureOnOpen": false +} \ No newline at end of file diff --git a/interceptors/Makefile b/interceptors/Makefile new file mode 100644 index 000000000..0958a1396 --- /dev/null +++ b/interceptors/Makefile @@ -0,0 +1,7 @@ +#! /usr/bin/make +# +# Makefile for Goa interceptors example + +APP=interceptors + +include ../common.mk diff --git a/interceptors/README.md b/interceptors/README.md new file mode 100644 index 000000000..375ba279b --- /dev/null +++ b/interceptors/README.md @@ -0,0 +1,121 @@ +# Interceptors Example + +This example demonstrates how to structure and organize interceptors in a Goa service. It provides skeleton implementations that show the basic patterns for both client-side and server-side interceptors. Note that these are educational examples and not production-ready implementations. + +## Design Overview + +The example shows how to organize different types of interceptors: + +### Server-Side Interceptors + +```go +// Example interceptor chain - implementations are skeleton/logging only +ServerInterceptor(TraceRequest) // Shows where to add trace context +ServerInterceptor(RequestAudit) // Shows where to add timing/logging +ServerInterceptor(JWTAuth) // Shows where to add auth checks +ServerInterceptor(SetDeadline) // Shows where to add timeouts +ServerInterceptor(Cache) // Shows where to add caching +``` + +### Client-Side Interceptors + +```go +// Example client interceptors - implementations are skeleton/logging only +ClientInterceptor(EncodeTenant) // Shows where to modify auth tokens +ClientInterceptor(Retry) // Shows where to add retry logic +``` + +## Example Patterns Demonstrated + +The example shows common interceptor patterns (note: implementations are skeleton only): + +1. **Authentication Pattern** + - Where to add JWT token validation + - How to pass tenant information + - Structure for auth checks + +2. **Observability Pattern** + - Where to add request tracing + - How to structure audit logging + - Points for adding metrics + +3. **Caching Pattern** + - Where to add cache checks + - Structure for cache updates + - Points for cache invalidation + +4. **Resilience Pattern** + - Where to add timeouts + - Structure for retry logic + - Error handling points + +## Running the Example + +1. Start the service: + ```bash + ./run-service.sh + ``` + This builds and starts both the service and CLI on port 8088. + +2. In another terminal, run the demo: + ```bash + ./demo.sh + ``` + +## Demo Scenarios + +The demo script shows the interceptor chain in action with test scenarios: + +1. **Basic Request Flow** + ```bash + # Shows the complete interceptor chain with logging + interceptors-cli create --tenant-id --auth "Bearer " + ``` + +2. **Cache Structure** + ```bash + # Shows where cache checks would happen + interceptors-cli get --record-id --tenant-id --auth "Bearer " + ``` + +3. **Retry Pattern** + ```bash + # Shows where retry logic would be implemented + interceptors-cli get --record-id "00000000-0000-0000-0000-000000000000" + ``` + +4. **Timeout Pattern** + ```bash + # Shows where deadline handling would occur + interceptors-cli get --record-id "00000000-0000-0000-0000-000000000001" + ``` + +5. **Auth Pattern** + ```bash + # Shows where token validation would happen + interceptors-cli get --record-id --auth "Bearer wrong-token" + ``` + +## Implementation Notes + +The interceptors in this example are skeleton implementations that only log their execution. They demonstrate: + +1. How to structure interceptors in the design +2. Where to place different types of middleware logic +3. How to chain interceptors in a specific order +4. How client and server interceptors interact + +Key Files: +- `design/design.go`: Shows how to define interceptors in Goa DSL +- `interceptors/interceptors_server.go`: Shows server interceptor structure +- `interceptors/interceptors_client.go`: Shows client interceptor structure +- `demo.sh`: Shows how to test interceptor patterns + +## Service Endpoints + +The service runs on both HTTP on `http://localhost:8088` and gRPC on `localhost:8080`. +The HTTP service provides two endpoints: +- `POST /records/{tenantID}` - Create a new record +- `GET /records/{tenantID}/{recordID}` - Retrieve a record by ID + +Each endpoint is protected by various interceptors that demonstrate different aspects of the middleware functionality. diff --git a/interceptors/cmd/interceptors-cli/grpc.go b/interceptors/cmd/interceptors-cli/grpc.go new file mode 100644 index 000000000..c3c4d4970 --- /dev/null +++ b/interceptors/cmd/interceptors-cli/grpc.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + "os" + + cli "goa.design/examples/interceptors/gen/grpc/cli/interceptors" + "goa.design/examples/interceptors/interceptors" + goa "goa.design/goa/v3/pkg" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +func doGRPC(_, host string, _ int, _ bool) (goa.Endpoint, any, error) { + conn, err := grpc.NewClient(host, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + fmt.Fprintf(os.Stderr, "could not connect to gRPC server at %s: %v\n", host, err) + } + interceptorsInterceptors := interceptors.NewInterceptorsClientInterceptors() + return cli.ParseEndpoint( + conn, + interceptorsInterceptors, + ) +} diff --git a/interceptors/cmd/interceptors-cli/http.go b/interceptors/cmd/interceptors-cli/http.go new file mode 100644 index 000000000..a05db46ea --- /dev/null +++ b/interceptors/cmd/interceptors-cli/http.go @@ -0,0 +1,54 @@ +package main + +import ( + "net/http" + "time" + + "github.com/gorilla/websocket" + cli "goa.design/examples/interceptors/gen/http/cli/interceptors" + "goa.design/examples/interceptors/gen/interceptors" + interceptorsex "goa.design/examples/interceptors/interceptors" + goahttp "goa.design/goa/v3/http" + goa "goa.design/goa/v3/pkg" +) + +func doHTTP(scheme, host string, timeout int, debug bool) (goa.Endpoint, any, error) { + var ( + doer goahttp.Doer + interceptorsInterceptors interceptors.ClientInterceptors + ) + { + doer = &http.Client{Timeout: time.Duration(timeout) * time.Second} + if debug { + doer = goahttp.NewDebugDoer(doer) + } + interceptorsInterceptors = interceptorsex.NewInterceptorsClientInterceptors() + } + + var ( + dialer *websocket.Dialer + ) + { + dialer = websocket.DefaultDialer + } + + return cli.ParseEndpoint( + scheme, + host, + doer, + goahttp.RequestEncoder, + goahttp.ResponseDecoder, + debug, + dialer, + nil, + interceptorsInterceptors, + ) +} + +func httpUsageCommands() string { + return cli.UsageCommands() +} + +func httpUsageExamples() string { + return cli.UsageExamples() +} diff --git a/interceptors/cmd/interceptors-cli/main.go b/interceptors/cmd/interceptors-cli/main.go new file mode 100644 index 000000000..413b3c66e --- /dev/null +++ b/interceptors/cmd/interceptors-cli/main.go @@ -0,0 +1,122 @@ +package main + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "net/url" + "os" + "strings" + + goa "goa.design/goa/v3/pkg" +) + +func main() { + var ( + hostF = flag.String("host", "localhost", "Server host (valid values: localhost)") + addrF = flag.String("url", "", "URL to service host") + + verboseF = flag.Bool("verbose", false, "Print request and response details") + vF = flag.Bool("v", false, "Print request and response details") + timeoutF = flag.Int("timeout", 30, "Maximum number of seconds to wait for response") + ) + flag.Usage = usage + flag.Parse() + var ( + addr string + timeout int + debug bool + ) + { + addr = *addrF + if addr == "" { + switch *hostF { + case "localhost": + addr = "http://localhost:80" + default: + fmt.Fprintf(os.Stderr, "invalid host argument: %q (valid hosts: localhost)\n", *hostF) + os.Exit(1) + } + } + timeout = *timeoutF + debug = *verboseF || *vF + } + + var ( + scheme string + host string + ) + { + u, err := url.Parse(addr) + if err != nil { + fmt.Fprintf(os.Stderr, "invalid URL %#v: %s\n", addr, err) + os.Exit(1) + } + scheme = u.Scheme + host = u.Host + } + var ( + endpoint goa.Endpoint + payload any + err error + ) + { + switch scheme { + case "http", "https": + endpoint, payload, err = doHTTP(scheme, host, timeout, debug) + case "grpc", "grpcs": + endpoint, payload, err = doGRPC(scheme, host, timeout, debug) + default: + fmt.Fprintf(os.Stderr, "invalid scheme: %q (valid schemes: grpc|http)\n", scheme) + os.Exit(1) + } + } + if err != nil { + if err == flag.ErrHelp { + os.Exit(0) + } + fmt.Fprintln(os.Stderr, err.Error()) + fmt.Fprintln(os.Stderr, "run '"+os.Args[0]+" --help' for detailed usage.") + os.Exit(1) + } + + data, err := endpoint(context.Background(), payload) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } + + if data != nil { + m, _ := json.MarshalIndent(data, "", " ") + fmt.Println(string(m)) + } +} + +func usage() { + fmt.Fprintf(os.Stderr, `%s is a command line client for the interceptors API. + +Usage: + %s [-host HOST][-url URL][-timeout SECONDS][-verbose|-v] SERVICE ENDPOINT [flags] + + -host HOST: server host (localhost). valid values: localhost + -url URL: specify service URL overriding host URL (http://localhost:8080) + -timeout: maximum number of seconds to wait for response (30) + -verbose|-v: print request and response details (false) + +Commands: +%s +Additional help: + %s SERVICE [ENDPOINT] --help + +Example: +%s +`, os.Args[0], os.Args[0], indent(httpUsageCommands()), os.Args[0], indent(httpUsageExamples())) +} + +func indent(s string) string { + if s == "" { + return "" + } + return " " + strings.Replace(s, "\n", "\n ", -1) +} diff --git a/interceptors/cmd/interceptors/grpc.go b/interceptors/cmd/interceptors/grpc.go new file mode 100644 index 000000000..56be70196 --- /dev/null +++ b/interceptors/cmd/interceptors/grpc.go @@ -0,0 +1,78 @@ +package main + +import ( + "context" + "fmt" + "net" + "net/url" + "sync" + + "goa.design/clue/debug" + "goa.design/clue/log" + interceptorspb "goa.design/examples/interceptors/gen/grpc/interceptors/pb" + interceptorssvr "goa.design/examples/interceptors/gen/grpc/interceptors/server" + interceptors "goa.design/examples/interceptors/gen/interceptors" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +// handleGRPCServer starts configures and starts a gRPC server on the given +// URL. It shuts down the server if any error is received in the error channel. +func handleGRPCServer(ctx context.Context, u *url.URL, interceptorsEndpoints *interceptors.Endpoints, wg *sync.WaitGroup, errc chan error, dbg bool) { + + // Wrap the endpoints with the transport specific layers. The generated + // server packages contains code generated from the design which maps + // the service input and output data structures to gRPC requests and + // responses. + var ( + interceptorsServer *interceptorssvr.Server + ) + { + interceptorsServer = interceptorssvr.New(interceptorsEndpoints, nil) + } + + // Create interceptor which sets up the logger in each request context. + chain := grpc.ChainUnaryInterceptor(log.UnaryServerInterceptor(ctx)) + if dbg { + // Log request and response content if debug logs are enabled. + chain = grpc.ChainUnaryInterceptor(log.UnaryServerInterceptor(ctx), debug.UnaryServerInterceptor()) + } + + // Initialize gRPC server + srv := grpc.NewServer(chain) + + // Register the servers. + interceptorspb.RegisterInterceptorsServer(srv, interceptorsServer) + + for svc, info := range srv.GetServiceInfo() { + for _, m := range info.Methods { + log.Printf(ctx, "serving gRPC method %s", svc+"/"+m.Name) + } + } + + // Register the server reflection service on the server. + // See https://grpc.github.io/grpc/core/md_doc_server-reflection.html. + reflection.Register(srv) + + (*wg).Add(1) + go func() { + defer (*wg).Done() + + // Start gRPC server in a separate goroutine. + go func() { + lis, err := net.Listen("tcp", u.Host) + if err != nil { + errc <- err + } + if lis == nil { + errc <- fmt.Errorf("failed to listen on %q", u.Host) + } + log.Printf(ctx, "gRPC server listening on %q", u.Host) + errc <- srv.Serve(lis) + }() + + <-ctx.Done() + log.Printf(ctx, "shutting down gRPC server at %q", u.Host) + srv.Stop() + }() +} diff --git a/interceptors/cmd/interceptors/http.go b/interceptors/cmd/interceptors/http.go new file mode 100644 index 000000000..59ebc07b1 --- /dev/null +++ b/interceptors/cmd/interceptors/http.go @@ -0,0 +1,105 @@ +package main + +import ( + "context" + "net/http" + "net/url" + "sync" + "time" + + "github.com/gorilla/websocket" + "goa.design/clue/debug" + "goa.design/clue/log" + interceptorssvr "goa.design/examples/interceptors/gen/http/interceptors/server" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goahttp "goa.design/goa/v3/http" +) + +// handleHTTPServer starts configures and starts a HTTP server on the given +// URL. It shuts down the server if any error is received in the error channel. +func handleHTTPServer(ctx context.Context, u *url.URL, interceptorsEndpoints *interceptors.Endpoints, wg *sync.WaitGroup, errc chan error, dbg bool) { + + // Provide the transport specific request decoder and response encoder. + // The goa http package has built-in support for JSON, XML and gob. + // Other encodings can be used by providing the corresponding functions, + // see goa.design/implement/encoding. + var ( + dec = goahttp.RequestDecoder + enc = goahttp.ResponseEncoder + ) + + // Build the service HTTP request multiplexer and mount debug and profiler + // endpoints in debug mode. + var mux goahttp.Muxer + { + mux = goahttp.NewMuxer() + if dbg { + // Mount pprof handlers for memory profiling under /debug/pprof. + debug.MountPprofHandlers(debug.Adapt(mux)) + // Mount /debug endpoint to enable or disable debug logs at runtime. + debug.MountDebugLogEnabler(debug.Adapt(mux)) + } + } + + // Wrap the endpoints with the transport specific layers. The generated + // server packages contains code generated from the design which maps + // the service input and output data structures to HTTP requests and + // responses. + var ( + interceptorsServer *interceptorssvr.Server + ) + { + eh := errorHandler(ctx) + upgrader := &websocket.Upgrader{} + interceptorsServer = interceptorssvr.New(interceptorsEndpoints, mux, dec, enc, eh, nil, upgrader, nil) + } + + // Configure the mux. + interceptorssvr.Mount(mux, interceptorsServer) + + var handler http.Handler = mux + if dbg { + // Log query and response bodies if debug logs are enabled. + handler = debug.HTTP()(handler) + } + handler = log.HTTP(ctx)(handler) + + // Start HTTP server using default configuration, change the code to + // configure the server as required by your service. + srv := &http.Server{Addr: u.Host, Handler: handler, ReadHeaderTimeout: time.Second * 60} + for _, m := range interceptorsServer.Mounts { + log.Printf(ctx, "HTTP %q mounted on %s %s", m.Method, m.Verb, m.Pattern) + } + + (*wg).Add(1) + go func() { + defer (*wg).Done() + + // Start HTTP server in a separate goroutine. + go func() { + log.Printf(ctx, "HTTP server listening on %q", u.Host) + errc <- srv.ListenAndServe() + }() + + <-ctx.Done() + log.Printf(ctx, "shutting down HTTP server at %q", u.Host) + + // Shutdown gracefully with a 30s timeout. + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + err := srv.Shutdown(ctx) + if err != nil { + log.Printf(ctx, "failed to shutdown: %v", err) + } + }() +} + +// errorHandler returns a function that writes and logs the given error. +// The function also writes and logs the error unique ID so that it's possible +// to correlate. +func errorHandler(logCtx context.Context) func(context.Context, http.ResponseWriter, error) { + return func(ctx context.Context, w http.ResponseWriter, err error) { + log.Printf(logCtx, "ERROR: %s", err.Error()) + } +} diff --git a/interceptors/cmd/interceptors/main.go b/interceptors/cmd/interceptors/main.go new file mode 100644 index 000000000..761d67eaf --- /dev/null +++ b/interceptors/cmd/interceptors/main.go @@ -0,0 +1,150 @@ +package main + +import ( + "context" + "flag" + "fmt" + "net" + "net/url" + "os" + "os/signal" + "sync" + "syscall" + + "goa.design/clue/debug" + "goa.design/clue/log" + interceptorsapi "goa.design/examples/interceptors" + interceptors "goa.design/examples/interceptors/gen/interceptors" + interceptorsex "goa.design/examples/interceptors/interceptors" +) + +func main() { + // Define command line flags, add any other flag required to configure the + // service. + var ( + hostF = flag.String("host", "localhost", "Server host (valid values: localhost)") + domainF = flag.String("domain", "", "Host domain name (overrides host domain specified in service design)") + httpPortF = flag.String("http-port", "", "HTTP port (overrides host HTTP port specified in service design)") + grpcPortF = flag.String("grpc-port", "", "gRPC port (overrides host gRPC port specified in service design)") + secureF = flag.Bool("secure", false, "Use secure scheme (https or grpcs)") + dbgF = flag.Bool("debug", false, "Log request and response bodies") + ) + flag.Parse() + + // Setup logger. Replace logger with your own log package of choice. + format := log.FormatJSON + if log.IsTerminal() { + format = log.FormatTerminal + } + ctx := log.Context(context.Background(), log.WithFormat(format)) + if *dbgF { + ctx = log.Context(ctx, log.WithDebug()) + log.Debugf(ctx, "debug logs enabled") + } + log.Print(ctx, log.KV{K: "http-port", V: *httpPortF}) + + // Initialize the services. + var ( + interceptorsSvc interceptors.Service + ) + { + interceptorsSvc = interceptorsapi.NewInterceptors() + } + // Initialize the interceptors. + var ( + interceptorsInterceptors interceptors.ServerInterceptors + ) + { + interceptorsInterceptors = interceptorsex.NewInterceptorsServerInterceptors() + } + + // Wrap the services in endpoints that can be invoked from other services + // potentially running in different processes. + var ( + interceptorsEndpoints *interceptors.Endpoints + ) + { + interceptorsEndpoints = interceptors.NewEndpoints(interceptorsSvc, interceptorsInterceptors) + interceptorsEndpoints.Use(debug.LogPayloads()) + interceptorsEndpoints.Use(log.Endpoint) + } + + // Create channel used by both the signal handler and server goroutines + // to notify the main goroutine when to stop the server. + errc := make(chan error) + + // Setup interrupt handler. This optional step configures the process so + // that SIGINT and SIGTERM signals cause the services to stop gracefully. + go func() { + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + errc <- fmt.Errorf("%s", <-c) + }() + + var wg sync.WaitGroup + ctx, cancel := context.WithCancel(ctx) + + // Start the servers and send errors (if any) to the error channel. + switch *hostF { + case "localhost": + { + addr := "http://localhost:80" + u, err := url.Parse(addr) + if err != nil { + log.Fatalf(ctx, err, "invalid URL %#v\n", addr) + } + if *secureF { + u.Scheme = "https" + } + if *domainF != "" { + u.Host = *domainF + } + if *httpPortF != "" { + h, _, err := net.SplitHostPort(u.Host) + if err != nil { + log.Fatalf(ctx, err, "invalid URL %#v\n", u.Host) + } + u.Host = net.JoinHostPort(h, *httpPortF) + } else if u.Port() == "" { + u.Host = net.JoinHostPort(u.Host, "80") + } + handleHTTPServer(ctx, u, interceptorsEndpoints, &wg, errc, *dbgF) + } + + { + addr := "grpc://localhost:8080" + u, err := url.Parse(addr) + if err != nil { + log.Fatalf(ctx, err, "invalid URL %#v\n", addr) + } + if *secureF { + u.Scheme = "grpcs" + } + if *domainF != "" { + u.Host = *domainF + } + if *grpcPortF != "" { + h, _, err := net.SplitHostPort(u.Host) + if err != nil { + log.Fatalf(ctx, err, "invalid URL %#v\n", u.Host) + } + u.Host = net.JoinHostPort(h, *grpcPortF) + } else if u.Port() == "" { + u.Host = net.JoinHostPort(u.Host, "8080") + } + handleGRPCServer(ctx, u, interceptorsEndpoints, &wg, errc, *dbgF) + } + + default: + log.Fatal(ctx, fmt.Errorf("invalid host argument: %q (valid hosts: localhost)", *hostF)) + } + + // Wait for signal. + log.Printf(ctx, "exiting (%v)", <-errc) + + // Send cancellation signal to the goroutines. + cancel() + + wg.Wait() + log.Printf(ctx, "exited") +} diff --git a/interceptors/demo.sh b/interceptors/demo.sh new file mode 100755 index 000000000..10cd0fa50 --- /dev/null +++ b/interceptors/demo.sh @@ -0,0 +1,53 @@ +#!/bin/bash +set -e + +# Colors for output +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo_step() { + echo -e "\n${GREEN}$1${NC}" + echo -e "${YELLOW}$2${NC}\n" +} + +CLI="./bin/interceptors-cli" + +# Ensure the CLI is built +if [ ! -f "$CLI" ]; then + echo "CLI not found. Please run ./run-service.sh first" + exit 1 +fi + +# Helper function to make requests +make_request() { + $CLI --url http://localhost:8088 --verbose "$@" +} + +# Create JSON payloads +TENANT_ID="bcd44737-a547-4294-8c51-a6665750b1b4" +CREATE_PAYLOAD='{"value": "Hello World"}' +GET_PAYLOAD='{}' + +# Demo scenario +echo_step "1. Create a new record" \ + "This demonstrates the basic flow with authentication and audit logging" +RECORD_ID=$(make_request interceptors create --body "$CREATE_PAYLOAD" --tenant-id "$TENANT_ID" --auth "Bearer ${TENANT_ID}" | grep -o '"id":"[^"]*"' | cut -d'"' -f4) +echo "Created record with ID: $RECORD_ID" + +echo_step "2. Retrieve the created record" \ + "This demonstrates caching interceptor in action" +make_request interceptors get --body "$GET_PAYLOAD" --record-id "$RECORD_ID" --tenant-id "$TENANT_ID" --auth "Bearer ${TENANT_ID}" +make_request interceptors get --body "$GET_PAYLOAD" --record-id "$RECORD_ID" --tenant-id "$TENANT_ID" --auth "Bearer ${TENANT_ID}" + +echo_step "3. Test unavailable service (retry interceptor)" \ + "This demonstrates the retry mechanism when service is temporarily unavailable" +make_request interceptors get --body "$GET_PAYLOAD" --record-id "00000000-0000-0000-0000-000000000000" --tenant-id "$TENANT_ID" --auth "Bearer ${TENANT_ID}" + +echo_step "4. Test timeout (deadline interceptor)" \ + "This demonstrates the deadline interceptor timing out a slow request" +make_request interceptors get --body "$GET_PAYLOAD" --record-id "00000000-0000-0000-0000-000000000001" --tenant-id "$TENANT_ID" --auth "Bearer ${TENANT_ID}" + +echo_step "5. Test invalid tenant ID" \ + "This demonstrates the JWT authentication interceptor rejecting invalid tokens" +make_request interceptors get --body "$GET_PAYLOAD" --record-id "$RECORD_ID" --tenant-id "$TENANT_ID" --auth "Bearer wrong-token" diff --git a/interceptors/design/design.go b/interceptors/design/design.go new file mode 100644 index 000000000..b307c9a34 --- /dev/null +++ b/interceptors/design/design.go @@ -0,0 +1,252 @@ +package design + +import ( + . "goa.design/goa/v3/dsl" +) + +// EncodeTenant is a client-side interceptor that writes the tenant ID to the JWT +var EncodeTenant = Interceptor("EncodeTenant", func() { + Description("Client-side interceptor which writes the tenant ID to the signed JWT contained in the Authorization header") + + ReadPayload(func() { + Attribute("tenantID", String, "Tenant ID to encode") + }) + + WritePayload(func() { + Attribute("auth", String, "Generated JWT auth token") + }) +}) + +// JWTAuth handles authentication and authorization +var JWTAuth = Interceptor("JWTAuth", func() { + Description("Server-side interceptor that validates JWT token and tenant ID") + + ReadPayload(func() { + Attribute("auth", String, "JWT auth token") + Attribute("tenantID", String, "Tenant ID to validate against") + }) +}) + +// TraceRequest handles request tracing +var TraceRequest = Interceptor("TraceRequest", func() { + Description("Server-side interceptor that adds trace context to the request payload") + + WritePayload(func() { + Attribute("traceID", String, "Unique trace ID for request") + Attribute("spanID", String, "Unique span ID for request") + }) +}) + +// TraceBidirectionalStream handles bidirectional streaming trace context +var TraceBidirectionalStream = Interceptor("TraceBidirectionalStream", func() { + Description("Server-side and client-side interceptor that adds trace context to the bidirectional stream payload") + + ReadStreamingPayload(func() { + Attribute("traceID", String, "Unique trace ID for request") + Attribute("spanID", String, "Unique span ID for request") + }) + WriteStreamingPayload(func() { + Attribute("traceID", String, "Unique trace ID for request") + Attribute("spanID", String, "Unique span ID for request") + }) + + ReadStreamingResult(func() { + Attribute("traceID", String, "Unique trace ID for request") + Attribute("spanID", String, "Unique span ID for request") + }) + WriteStreamingResult(func() { + Attribute("traceID", String, "Unique trace ID for request") + Attribute("spanID", String, "Unique span ID for request") + }) +}) + +// RequestAudit handles request/response logging and timing +var RequestAudit = Interceptor("RequestAudit", func() { + Description("Server-side interceptor that provides comprehensive request/response audit logging") + + ReadResult(func() { + Attribute("status", Int, "Response status code") + }) + + WriteResult(func() { + Attribute("processedAt", String, "Timestamp when processed", func() { + Format(FormatDateTime) + }) + Attribute("duration", Int, "Processing duration in ms") + }) +}) + +// Cache implements a transparent cache for loaded records +var Cache = Interceptor("Cache", func() { + Description("Server-side interceptor which implements a transparent cache for loaded records") + + ReadPayload(func() { + Attribute("recordID", String, "Record ID to cache") + }) + + WriteResult(func() { + Attribute("cachedAt", String, "Time at which the record was cached in RFC3339 format") + }) +}) + +// SetDeadline sets request context deadline +var SetDeadline = Interceptor("SetDeadline", func() { + Description("Server-side interceptor which sets the context deadline for the request") +}) + +// Retry implements smart retry logic for failed requests +var Retry = Interceptor("Retry", func() { + Description("Client-side interceptor which implements smart retry logic with exponential backoff") + + ReadResult(func() { + Attribute("status", Int, "Response status code") + }) + + WriteResult(func() { + Attribute("retryCount", Int, "Number of retry attempts made") + Attribute("retryDuration", Int, "Total time spent retrying in ms") + }) +}) + +// Service definition +var _ = Service("interceptors", func() { + Description(`The interceptors service demonstrates a comprehensive use of interceptors combining +authentication, tenant validation, caching, audit logging, and retry mechanisms. It showcases +both client-side and server-side interceptors working together to provide a robust service.`) + + // Server-side interceptors - ordered by execution sequence + ServerInterceptor(JWTAuth) // Then validate authentication + ServerInterceptor(SetDeadline) // Set deadline + + // Client-side interceptors + ClientInterceptor(EncodeTenant) + + // Define a method that uses all the interceptors + Method("get", func() { + Description("Get retrieves a record by ID with all interceptors in action") + + ServerInterceptor(TraceRequest) // Add trace context first + ServerInterceptor(RequestAudit) // Start timing + // Add cache interceptor only for get method + ServerInterceptor(Cache) + + // Add retry interceptor only for get method + ClientInterceptor(Retry) + + Payload(func() { + Field(1, "tenantID", UUID, "Tenant ID for the request") + Field(2, "recordID", UUID, "ID of the record to retrieve") + Field(3, "auth", String, "JWT auth token") + Field(4, "traceID", UUID, "Unique trace ID for request, initialized by the TraceRequest interceptor") + Field(5, "spanID", UUID, "Unique span ID for request, initialized by the TraceRequest interceptor") + Required("recordID", "tenantID", "auth") + }) + + Result(func() { + Field(1, "id", UUID, "ID of the record") + Field(2, "value", String, "Value of the record") + Field(3, "tenant", String, "Tenant the record belongs to") + Field(4, "status", Int, "Response status code") + Field(5, "processedAt", String, "Timestamp when processed, written by the RequestAudit interceptor") + Field(6, "duration", Int, "Processing duration in ms, written by the RequestAudit interceptor") + Field(7, "cachedAt", String, "Time at which the record was cached, written by the Cache interceptor") + Field(8, "retryCount", Int, "Number of retry attempts made, written client-side by the Retry interceptor") + Field(9, "retryDuration", Int, "Total time spent retrying, written client-side by the Retry interceptor") + Required("id", "value", "tenant", "status", "processedAt", "duration") + }) + + Error("NotFound", ErrorResult, "Record not found") + Error("Unavailable", ErrorResult, "Temporary error", func() { + Temporary() + }) + + HTTP(func() { + GET("/records/{tenantID}/{recordID}") + Header("auth:Authorization") + Response("NotFound", StatusNotFound) + Response("Unavailable", StatusServiceUnavailable) + }) + + GRPC(func() { + Response("NotFound", CodeNotFound) + Response("Unavailable", CodeUnavailable) + }) + }) + + // Additional method showcasing write operations + Method("create", func() { + Description("Create a new record with all interceptors in action") + + ServerInterceptor(TraceRequest) // Add trace context first + ServerInterceptor(RequestAudit) // Start timing + // Add retry interceptor only for create method + ClientInterceptor(Retry) + + Payload(func() { + Field(1, "tenantID", UUID, "Tenant ID for the request") + Field(2, "value", String, "Value to store in record") + Field(3, "auth", String, "JWT auth token") + Field(4, "traceID", UUID, "Unique trace ID for request, initialized by the TraceRequest interceptor") + Field(5, "spanID", UUID, "Unique span ID for request, initialized by the TraceRequest interceptor") + Required("value", "tenantID", "auth") + }) + + Result(func() { + Field(1, "id", UUID, "ID of the created record") + Field(2, "value", String, "Value of the record") + Field(3, "tenant", String, "Tenant the record belongs to") + Field(4, "status", Int, "Response status code") + Field(5, "processedAt", String, "Timestamp when processed") + Field(6, "duration", Int, "Processing duration in ms") + Field(7, "retryCount", Int, "Number of retry attempts made") + Field(8, "retryDuration", Int, "Total time spent retrying") + Required("id", "value", "tenant", "status", "processedAt", "duration") + }) + + HTTP(func() { + POST("/records/{tenantID}") + Header("auth:Authorization") + Response(StatusCreated) + }) + }) + + Method("stream", func() { + Description("Stream records") + + ServerInterceptor(TraceBidirectionalStream) + ClientInterceptor(TraceBidirectionalStream) + + Payload(func() { + Field(1, "tenantID", UUID, "Tenant ID for the request") + Field(2, "auth", String, "JWT auth token") + Required("tenantID", "auth") + }) + StreamingPayload(func() { + Field(1, "id", UUID, "ID of the created record") + Field(2, "value", String, "Value of the record") + Field(3, "traceID", UUID, "Unique trace ID for request, initialized by the TraceRequest interceptor") + Field(4, "spanID", UUID, "Unique span ID for request, initialized by the TraceRequest interceptor") + Required("id", "value") + }) + StreamingResult(func() { + Field(1, "id", UUID, "ID of the created record") + Field(2, "value", String, "Value of the record") + Field(3, "tenant", String, "Tenant the record belongs to") + Field(4, "status", Int, "Response status code") + Field(5, "traceID", UUID, "Unique trace ID for request, initialized by the TraceRequest interceptor") + Field(6, "spanID", UUID, "Unique span ID for request, initialized by the TraceRequest interceptor") + Required("id", "value", "tenant", "status") + }) + + HTTP(func() { + GET("/records/{tenantID}/stream") + Header("auth:Authorization") + Response(StatusOK) + }) + }) +}) + +var UUID = Type("UUID", String, func() { + Description("Valid UUID representation as per RFC 4122") + Format(FormatUUID) +}) diff --git a/interceptors/gen/grpc/cli/interceptors/cli.go b/interceptors/gen/grpc/cli/interceptors/cli.go new file mode 100644 index 000000000..b523214b6 --- /dev/null +++ b/interceptors/gen/grpc/cli/interceptors/cli.go @@ -0,0 +1,165 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors gRPC client CLI support package +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package cli + +import ( + "flag" + "fmt" + "os" + + interceptorsc "goa.design/examples/interceptors/gen/grpc/interceptors/client" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goa "goa.design/goa/v3/pkg" + grpc "google.golang.org/grpc" +) + +// UsageCommands returns the set of commands and sub-commands using the format +// +// command (subcommand1|subcommand2|...) +func UsageCommands() string { + return `interceptors get +` +} + +// UsageExamples produces an example of a valid invocation of the CLI tool. +func UsageExamples() string { + return os.Args[0] + ` interceptors get --message '{ + "auth": "Voluptas rerum non iste ducimus et recusandae.", + "recordID": "Aliquid necessitatibus asperiores iure.", + "spanID": "Aliquid necessitatibus asperiores iure.", + "tenantID": "Aliquid necessitatibus asperiores iure.", + "traceID": "Aliquid necessitatibus asperiores iure." + }'` + "\n" + + "" +} + +// ParseEndpoint returns the endpoint and payload as specified on the command +// line. +func ParseEndpoint( + cc *grpc.ClientConn, + inter interceptors.ClientInterceptors, + opts ...grpc.CallOption, +) (goa.Endpoint, any, error) { + var ( + interceptorsFlags = flag.NewFlagSet("interceptors", flag.ContinueOnError) + + interceptorsGetFlags = flag.NewFlagSet("get", flag.ExitOnError) + interceptorsGetMessageFlag = interceptorsGetFlags.String("message", "", "") + ) + interceptorsFlags.Usage = interceptorsUsage + interceptorsGetFlags.Usage = interceptorsGetUsage + + if err := flag.CommandLine.Parse(os.Args[1:]); err != nil { + return nil, nil, err + } + + if flag.NArg() < 2 { // two non flag args are required: SERVICE and ENDPOINT (aka COMMAND) + return nil, nil, fmt.Errorf("not enough arguments") + } + + var ( + svcn string + svcf *flag.FlagSet + ) + { + svcn = flag.Arg(0) + switch svcn { + case "interceptors": + svcf = interceptorsFlags + default: + return nil, nil, fmt.Errorf("unknown service %q", svcn) + } + } + if err := svcf.Parse(flag.Args()[1:]); err != nil { + return nil, nil, err + } + + var ( + epn string + epf *flag.FlagSet + ) + { + epn = svcf.Arg(0) + switch svcn { + case "interceptors": + switch epn { + case "get": + epf = interceptorsGetFlags + + } + + } + } + if epf == nil { + return nil, nil, fmt.Errorf("unknown %q endpoint %q", svcn, epn) + } + + // Parse endpoint flags if any + if svcf.NArg() > 1 { + if err := epf.Parse(svcf.Args()[1:]); err != nil { + return nil, nil, err + } + } + + var ( + data any + endpoint goa.Endpoint + err error + ) + { + switch svcn { + case "interceptors": + c := interceptorsc.NewClient(cc, opts...) + switch epn { + + case "get": + endpoint = c.Get() + endpoint = interceptors.WrapGetClientEndpoint(endpoint, inter) + data, err = interceptorsc.BuildGetPayload(*interceptorsGetMessageFlag) + } + } + } + if err != nil { + return nil, nil, err + } + + return endpoint, data, nil +} + +// interceptorsUsage displays the usage of the interceptors command and its +// subcommands. +func interceptorsUsage() { + fmt.Fprintf(os.Stderr, `The interceptors service demonstrates a comprehensive use of interceptors combining + authentication, tenant validation, caching, audit logging, and retry mechanisms. It showcases + both client-side and server-side interceptors working together to provide a robust service. +Usage: + %[1]s [globalflags] interceptors COMMAND [flags] + +COMMAND: + get: Get retrieves a record by ID with all interceptors in action + +Additional help: + %[1]s interceptors COMMAND --help +`, os.Args[0]) +} +func interceptorsGetUsage() { + fmt.Fprintf(os.Stderr, `%[1]s [flags] interceptors get -message JSON + +Get retrieves a record by ID with all interceptors in action + -message JSON: + +Example: + %[1]s interceptors get --message '{ + "auth": "Voluptas rerum non iste ducimus et recusandae.", + "recordID": "Aliquid necessitatibus asperiores iure.", + "spanID": "Aliquid necessitatibus asperiores iure.", + "tenantID": "Aliquid necessitatibus asperiores iure.", + "traceID": "Aliquid necessitatibus asperiores iure." + }' +`, os.Args[0]) +} diff --git a/interceptors/gen/grpc/interceptors/client/cli.go b/interceptors/gen/grpc/interceptors/client/cli.go new file mode 100644 index 000000000..63dd5691e --- /dev/null +++ b/interceptors/gen/grpc/interceptors/client/cli.go @@ -0,0 +1,46 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors gRPC client CLI support package +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package client + +import ( + "encoding/json" + "fmt" + + interceptorspb "goa.design/examples/interceptors/gen/grpc/interceptors/pb" + interceptors "goa.design/examples/interceptors/gen/interceptors" +) + +// BuildGetPayload builds the payload for the interceptors get endpoint from +// CLI flags. +func BuildGetPayload(interceptorsGetMessage string) (*interceptors.GetPayload, error) { + var err error + var message interceptorspb.GetRequest + { + if interceptorsGetMessage != "" { + err = json.Unmarshal([]byte(interceptorsGetMessage), &message) + if err != nil { + return nil, fmt.Errorf("invalid JSON for message, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"auth\": \"Voluptas rerum non iste ducimus et recusandae.\",\n \"recordID\": \"Aliquid necessitatibus asperiores iure.\",\n \"spanID\": \"Aliquid necessitatibus asperiores iure.\",\n \"tenantID\": \"Aliquid necessitatibus asperiores iure.\",\n \"traceID\": \"Aliquid necessitatibus asperiores iure.\"\n }'") + } + } + } + v := &interceptors.GetPayload{ + TenantID: interceptors.UUID(message.TenantId), + RecordID: interceptors.UUID(message.RecordId), + Auth: message.Auth, + } + if message.TraceId != nil { + traceID := interceptors.UUID(*message.TraceId) + v.TraceID = &traceID + } + if message.SpanId != nil { + spanID := interceptors.UUID(*message.SpanId) + v.SpanID = &spanID + } + + return v, nil +} diff --git a/interceptors/gen/grpc/interceptors/client/client.go b/interceptors/gen/grpc/interceptors/client/client.go new file mode 100644 index 000000000..38e656c3a --- /dev/null +++ b/interceptors/gen/grpc/interceptors/client/client.go @@ -0,0 +1,49 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors gRPC client +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package client + +import ( + "context" + + interceptorspb "goa.design/examples/interceptors/gen/grpc/interceptors/pb" + goagrpc "goa.design/goa/v3/grpc" + goapb "goa.design/goa/v3/grpc/pb" + goa "goa.design/goa/v3/pkg" + "google.golang.org/grpc" +) + +// Client lists the service endpoint gRPC clients. +type Client struct { + grpccli interceptorspb.InterceptorsClient + opts []grpc.CallOption +} // NewClient instantiates gRPC client for all the interceptors service servers. +func NewClient(cc *grpc.ClientConn, opts ...grpc.CallOption) *Client { + return &Client{ + grpccli: interceptorspb.NewInterceptorsClient(cc), + opts: opts, + } +} // Get calls the "Get" function in interceptorspb.InterceptorsClient interface. +func (c *Client) Get() goa.Endpoint { + return func(ctx context.Context, v any) (any, error) { + inv := goagrpc.NewInvoker( + BuildGetFunc(c.grpccli, c.opts...), + EncodeGetRequest, + DecodeGetResponse) + res, err := inv.Invoke(ctx, v) + if err != nil { + resp := goagrpc.DecodeError(err) + switch message := resp.(type) { + case *goapb.ErrorResponse: + return nil, goagrpc.NewServiceError(message) + default: + return nil, goa.Fault(err.Error()) + } + } + return res, nil + } +} diff --git a/interceptors/gen/grpc/interceptors/client/encode_decode.go b/interceptors/gen/grpc/interceptors/client/encode_decode.go new file mode 100644 index 000000000..b860fae99 --- /dev/null +++ b/interceptors/gen/grpc/interceptors/client/encode_decode.go @@ -0,0 +1,54 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors gRPC client encoders and decoders +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package client + +import ( + "context" + + interceptorspb "goa.design/examples/interceptors/gen/grpc/interceptors/pb" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goagrpc "goa.design/goa/v3/grpc" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" +) + +// BuildGetFunc builds the remote method to invoke for "interceptors" service +// "get" endpoint. +func BuildGetFunc(grpccli interceptorspb.InterceptorsClient, cliopts ...grpc.CallOption) goagrpc.RemoteFunc { + return func(ctx context.Context, reqpb any, opts ...grpc.CallOption) (any, error) { + for _, opt := range cliopts { + opts = append(opts, opt) + } + if reqpb != nil { + return grpccli.Get(ctx, reqpb.(*interceptorspb.GetRequest), opts...) + } + return grpccli.Get(ctx, &interceptorspb.GetRequest{}, opts...) + } +} + +// EncodeGetRequest encodes requests sent to interceptors get endpoint. +func EncodeGetRequest(ctx context.Context, v any, md *metadata.MD) (any, error) { + payload, ok := v.(*interceptors.GetPayload) + if !ok { + return nil, goagrpc.ErrInvalidType("interceptors", "get", "*interceptors.GetPayload", v) + } + return NewProtoGetRequest(payload), nil +} + +// DecodeGetResponse decodes responses from the interceptors get endpoint. +func DecodeGetResponse(ctx context.Context, v any, hdr, trlr metadata.MD) (any, error) { + message, ok := v.(*interceptorspb.GetResponse) + if !ok { + return nil, goagrpc.ErrInvalidType("interceptors", "get", "*interceptorspb.GetResponse", v) + } + if err := ValidateGetResponse(message); err != nil { + return nil, err + } + res := NewGetResult(message) + return res, nil +} diff --git a/interceptors/gen/grpc/interceptors/client/types.go b/interceptors/gen/grpc/interceptors/client/types.go new file mode 100644 index 000000000..ed2f153a5 --- /dev/null +++ b/interceptors/gen/grpc/interceptors/client/types.go @@ -0,0 +1,62 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors gRPC client types +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package client + +import ( + interceptorspb "goa.design/examples/interceptors/gen/grpc/interceptors/pb" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goa "goa.design/goa/v3/pkg" +) + +// NewProtoGetRequest builds the gRPC request type from the payload of the +// "get" endpoint of the "interceptors" service. +func NewProtoGetRequest(payload *interceptors.GetPayload) *interceptorspb.GetRequest { + message := &interceptorspb.GetRequest{ + TenantId: string(payload.TenantID), + RecordId: string(payload.RecordID), + Auth: payload.Auth, + } + if payload.TraceID != nil { + traceID := string(*payload.TraceID) + message.TraceId = &traceID + } + if payload.SpanID != nil { + spanID := string(*payload.SpanID) + message.SpanId = &spanID + } + return message +} + +// NewGetResult builds the result type of the "get" endpoint of the +// "interceptors" service from the gRPC response type. +func NewGetResult(message *interceptorspb.GetResponse) *interceptors.GetResult { + result := &interceptors.GetResult{ + ID: interceptors.UUID(message.Id), + Value: message.Value, + Tenant: message.Tenant, + Status: int(message.Status), + ProcessedAt: message.ProcessedAt, + Duration: int(message.Duration), + CachedAt: message.CachedAt, + } + if message.RetryCount != nil { + retryCount := int(*message.RetryCount) + result.RetryCount = &retryCount + } + if message.RetryDuration != nil { + retryDuration := int(*message.RetryDuration) + result.RetryDuration = &retryDuration + } + return result +} + +// ValidateGetResponse runs the validations defined on GetResponse. +func ValidateGetResponse(message *interceptorspb.GetResponse) (err error) { + err = goa.MergeErrors(err, goa.ValidateFormat("message.id", string(message.Id), goa.FormatUUID)) + return +} diff --git a/interceptors/gen/grpc/interceptors/pb/goagen_interceptors_interceptors.pb.go b/interceptors/gen/grpc/interceptors/pb/goagen_interceptors_interceptors.pb.go new file mode 100644 index 000000000..4a6de26ef --- /dev/null +++ b/interceptors/gen/grpc/interceptors/pb/goagen_interceptors_interceptors.pb.go @@ -0,0 +1,327 @@ +// Code generated with goa v3.19.1, DO NOT EDIT. +// +// interceptors protocol buffer definition +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.0 +// protoc v5.29.3 +// source: goagen_interceptors_interceptors.proto + +package interceptorspb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GetRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Tenant ID for the request + TenantId string `protobuf:"bytes,1,opt,name=tenant_id,json=tenantId,proto3" json:"tenant_id,omitempty"` + // ID of the record to retrieve + RecordId string `protobuf:"bytes,2,opt,name=record_id,json=recordId,proto3" json:"record_id,omitempty"` + // JWT auth token + Auth string `protobuf:"bytes,3,opt,name=auth,proto3" json:"auth,omitempty"` + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceId *string `protobuf:"bytes,4,opt,name=trace_id,json=traceId,proto3,oneof" json:"trace_id,omitempty"` + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanId *string `protobuf:"bytes,5,opt,name=span_id,json=spanId,proto3,oneof" json:"span_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetRequest) Reset() { + *x = GetRequest{} + mi := &file_goagen_interceptors_interceptors_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRequest) ProtoMessage() {} + +func (x *GetRequest) ProtoReflect() protoreflect.Message { + mi := &file_goagen_interceptors_interceptors_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetRequest.ProtoReflect.Descriptor instead. +func (*GetRequest) Descriptor() ([]byte, []int) { + return file_goagen_interceptors_interceptors_proto_rawDescGZIP(), []int{0} +} + +func (x *GetRequest) GetTenantId() string { + if x != nil { + return x.TenantId + } + return "" +} + +func (x *GetRequest) GetRecordId() string { + if x != nil { + return x.RecordId + } + return "" +} + +func (x *GetRequest) GetAuth() string { + if x != nil { + return x.Auth + } + return "" +} + +func (x *GetRequest) GetTraceId() string { + if x != nil && x.TraceId != nil { + return *x.TraceId + } + return "" +} + +func (x *GetRequest) GetSpanId() string { + if x != nil && x.SpanId != nil { + return *x.SpanId + } + return "" +} + +type GetResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // ID of the record + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Value of the record + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + // Tenant the record belongs to + Tenant string `protobuf:"bytes,3,opt,name=tenant,proto3" json:"tenant,omitempty"` + // Response status code + Status int32 `protobuf:"zigzag32,4,opt,name=status,proto3" json:"status,omitempty"` + // Timestamp when processed, written by the RequestAudit interceptor + ProcessedAt string `protobuf:"bytes,5,opt,name=processed_at,json=processedAt,proto3" json:"processed_at,omitempty"` + // Processing duration in ms, written by the RequestAudit interceptor + Duration int32 `protobuf:"zigzag32,6,opt,name=duration,proto3" json:"duration,omitempty"` + // Time at which the record was cached, written by the Cache interceptor + CachedAt *string `protobuf:"bytes,7,opt,name=cached_at,json=cachedAt,proto3,oneof" json:"cached_at,omitempty"` + // Number of retry attempts made, written client-side by the Retry interceptor + RetryCount *int32 `protobuf:"zigzag32,8,opt,name=retry_count,json=retryCount,proto3,oneof" json:"retry_count,omitempty"` + // Total time spent retrying, written client-side by the Retry interceptor + RetryDuration *int32 `protobuf:"zigzag32,9,opt,name=retry_duration,json=retryDuration,proto3,oneof" json:"retry_duration,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetResponse) Reset() { + *x = GetResponse{} + mi := &file_goagen_interceptors_interceptors_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResponse) ProtoMessage() {} + +func (x *GetResponse) ProtoReflect() protoreflect.Message { + mi := &file_goagen_interceptors_interceptors_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResponse.ProtoReflect.Descriptor instead. +func (*GetResponse) Descriptor() ([]byte, []int) { + return file_goagen_interceptors_interceptors_proto_rawDescGZIP(), []int{1} +} + +func (x *GetResponse) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *GetResponse) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +func (x *GetResponse) GetTenant() string { + if x != nil { + return x.Tenant + } + return "" +} + +func (x *GetResponse) GetStatus() int32 { + if x != nil { + return x.Status + } + return 0 +} + +func (x *GetResponse) GetProcessedAt() string { + if x != nil { + return x.ProcessedAt + } + return "" +} + +func (x *GetResponse) GetDuration() int32 { + if x != nil { + return x.Duration + } + return 0 +} + +func (x *GetResponse) GetCachedAt() string { + if x != nil && x.CachedAt != nil { + return *x.CachedAt + } + return "" +} + +func (x *GetResponse) GetRetryCount() int32 { + if x != nil && x.RetryCount != nil { + return *x.RetryCount + } + return 0 +} + +func (x *GetResponse) GetRetryDuration() int32 { + if x != nil && x.RetryDuration != nil { + return *x.RetryDuration + } + return 0 +} + +var File_goagen_interceptors_interceptors_proto protoreflect.FileDescriptor + +var file_goagen_interceptors_interceptors_proto_rawDesc = []byte{ + 0x0a, 0x26, 0x67, 0x6f, 0x61, 0x67, 0x65, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, + 0x70, 0x74, 0x6f, 0x72, 0x73, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, + 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, + 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, + 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x64, 0x12, + 0x12, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, + 0x75, 0x74, 0x68, 0x12, 0x1e, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, + 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x07, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x06, 0x73, 0x70, 0x61, 0x6e, 0x49, 0x64, 0x88, 0x01, + 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x42, 0x0a, + 0x0a, 0x08, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0xc7, 0x02, 0x0a, 0x0b, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, + 0x64, 0x41, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x11, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x20, 0x0a, 0x09, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x41, 0x74, 0x88, 0x01, + 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x11, 0x48, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x74, 0x72, 0x79, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x0e, 0x72, 0x65, 0x74, 0x72, 0x79, + 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x11, 0x48, + 0x02, 0x52, 0x0d, 0x72, 0x65, 0x74, 0x72, 0x79, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x64, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x4a, 0x0a, 0x0c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, + 0x74, 0x6f, 0x72, 0x73, 0x12, 0x3a, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, 0x18, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, + 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x11, 0x5a, 0x0f, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, + 0x73, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_goagen_interceptors_interceptors_proto_rawDescOnce sync.Once + file_goagen_interceptors_interceptors_proto_rawDescData = file_goagen_interceptors_interceptors_proto_rawDesc +) + +func file_goagen_interceptors_interceptors_proto_rawDescGZIP() []byte { + file_goagen_interceptors_interceptors_proto_rawDescOnce.Do(func() { + file_goagen_interceptors_interceptors_proto_rawDescData = protoimpl.X.CompressGZIP(file_goagen_interceptors_interceptors_proto_rawDescData) + }) + return file_goagen_interceptors_interceptors_proto_rawDescData +} + +var file_goagen_interceptors_interceptors_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_goagen_interceptors_interceptors_proto_goTypes = []any{ + (*GetRequest)(nil), // 0: interceptors.GetRequest + (*GetResponse)(nil), // 1: interceptors.GetResponse +} +var file_goagen_interceptors_interceptors_proto_depIdxs = []int32{ + 0, // 0: interceptors.Interceptors.Get:input_type -> interceptors.GetRequest + 1, // 1: interceptors.Interceptors.Get:output_type -> interceptors.GetResponse + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_goagen_interceptors_interceptors_proto_init() } +func file_goagen_interceptors_interceptors_proto_init() { + if File_goagen_interceptors_interceptors_proto != nil { + return + } + file_goagen_interceptors_interceptors_proto_msgTypes[0].OneofWrappers = []any{} + file_goagen_interceptors_interceptors_proto_msgTypes[1].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_goagen_interceptors_interceptors_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_goagen_interceptors_interceptors_proto_goTypes, + DependencyIndexes: file_goagen_interceptors_interceptors_proto_depIdxs, + MessageInfos: file_goagen_interceptors_interceptors_proto_msgTypes, + }.Build() + File_goagen_interceptors_interceptors_proto = out.File + file_goagen_interceptors_interceptors_proto_rawDesc = nil + file_goagen_interceptors_interceptors_proto_goTypes = nil + file_goagen_interceptors_interceptors_proto_depIdxs = nil +} diff --git a/interceptors/gen/grpc/interceptors/pb/goagen_interceptors_interceptors.proto b/interceptors/gen/grpc/interceptors/pb/goagen_interceptors_interceptors.proto new file mode 100644 index 000000000..37d88a45c --- /dev/null +++ b/interceptors/gen/grpc/interceptors/pb/goagen_interceptors_interceptors.proto @@ -0,0 +1,57 @@ +// Code generated with goa v3.19.1, DO NOT EDIT. +// +// interceptors protocol buffer definition +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +syntax = "proto3"; + +package interceptors; + +option go_package = "/interceptorspb"; + +// The interceptors service demonstrates a comprehensive use of interceptors +// combining +// authentication, tenant validation, caching, audit logging, and retry +// mechanisms. It showcases +// both client-side and server-side interceptors working together to provide a +// robust service. +service Interceptors { + // Get retrieves a record by ID with all interceptors in action + rpc Get (GetRequest) returns (GetResponse); +} + +message GetRequest { + // Tenant ID for the request + string tenant_id = 1; + // ID of the record to retrieve + string record_id = 2; + // JWT auth token + string auth = 3; + // Unique trace ID for request, initialized by the TraceRequest interceptor + optional string trace_id = 4; + // Unique span ID for request, initialized by the TraceRequest interceptor + optional string span_id = 5; +} + +message GetResponse { + // ID of the record + string id = 1; + // Value of the record + string value = 2; + // Tenant the record belongs to + string tenant = 3; + // Response status code + sint32 status = 4; + // Timestamp when processed, written by the RequestAudit interceptor + string processed_at = 5; + // Processing duration in ms, written by the RequestAudit interceptor + sint32 duration = 6; + // Time at which the record was cached, written by the Cache interceptor + optional string cached_at = 7; + // Number of retry attempts made, written client-side by the Retry interceptor + optional sint32 retry_count = 8; + // Total time spent retrying, written client-side by the Retry interceptor + optional sint32 retry_duration = 9; +} diff --git a/interceptors/gen/grpc/interceptors/pb/goagen_interceptors_interceptors_grpc.pb.go b/interceptors/gen/grpc/interceptors/pb/goagen_interceptors_interceptors_grpc.pb.go new file mode 100644 index 000000000..074fdd787 --- /dev/null +++ b/interceptors/gen/grpc/interceptors/pb/goagen_interceptors_interceptors_grpc.pb.go @@ -0,0 +1,144 @@ +// Code generated with goa v3.19.1, DO NOT EDIT. +// +// interceptors protocol buffer definition +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v5.29.3 +// source: goagen_interceptors_interceptors.proto + +package interceptorspb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + Interceptors_Get_FullMethodName = "/interceptors.Interceptors/Get" +) + +// InterceptorsClient is the client API for Interceptors service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// The interceptors service demonstrates a comprehensive use of interceptors +// combining +// authentication, tenant validation, caching, audit logging, and retry +// mechanisms. It showcases +// both client-side and server-side interceptors working together to provide a +// robust service. +type InterceptorsClient interface { + // Get retrieves a record by ID with all interceptors in action + Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) +} + +type interceptorsClient struct { + cc grpc.ClientConnInterface +} + +func NewInterceptorsClient(cc grpc.ClientConnInterface) InterceptorsClient { + return &interceptorsClient{cc} +} + +func (c *interceptorsClient) Get(ctx context.Context, in *GetRequest, opts ...grpc.CallOption) (*GetResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetResponse) + err := c.cc.Invoke(ctx, Interceptors_Get_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// InterceptorsServer is the server API for Interceptors service. +// All implementations must embed UnimplementedInterceptorsServer +// for forward compatibility. +// +// The interceptors service demonstrates a comprehensive use of interceptors +// combining +// authentication, tenant validation, caching, audit logging, and retry +// mechanisms. It showcases +// both client-side and server-side interceptors working together to provide a +// robust service. +type InterceptorsServer interface { + // Get retrieves a record by ID with all interceptors in action + Get(context.Context, *GetRequest) (*GetResponse, error) + mustEmbedUnimplementedInterceptorsServer() +} + +// UnimplementedInterceptorsServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedInterceptorsServer struct{} + +func (UnimplementedInterceptorsServer) Get(context.Context, *GetRequest) (*GetResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Get not implemented") +} +func (UnimplementedInterceptorsServer) mustEmbedUnimplementedInterceptorsServer() {} +func (UnimplementedInterceptorsServer) testEmbeddedByValue() {} + +// UnsafeInterceptorsServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to InterceptorsServer will +// result in compilation errors. +type UnsafeInterceptorsServer interface { + mustEmbedUnimplementedInterceptorsServer() +} + +func RegisterInterceptorsServer(s grpc.ServiceRegistrar, srv InterceptorsServer) { + // If the following call pancis, it indicates UnimplementedInterceptorsServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&Interceptors_ServiceDesc, srv) +} + +func _Interceptors_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(InterceptorsServer).Get(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Interceptors_Get_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(InterceptorsServer).Get(ctx, req.(*GetRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Interceptors_ServiceDesc is the grpc.ServiceDesc for Interceptors service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Interceptors_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "interceptors.Interceptors", + HandlerType: (*InterceptorsServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Get", + Handler: _Interceptors_Get_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "goagen_interceptors_interceptors.proto", +} diff --git a/interceptors/gen/grpc/interceptors/server/encode_decode.go b/interceptors/gen/grpc/interceptors/server/encode_decode.go new file mode 100644 index 000000000..bc4c9a1d8 --- /dev/null +++ b/interceptors/gen/grpc/interceptors/server/encode_decode.go @@ -0,0 +1,50 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors gRPC server encoders and decoders +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package server + +import ( + "context" + + interceptorspb "goa.design/examples/interceptors/gen/grpc/interceptors/pb" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goagrpc "goa.design/goa/v3/grpc" + "google.golang.org/grpc/metadata" +) + +// EncodeGetResponse encodes responses from the "interceptors" service "get" +// endpoint. +func EncodeGetResponse(ctx context.Context, v any, hdr, trlr *metadata.MD) (any, error) { + result, ok := v.(*interceptors.GetResult) + if !ok { + return nil, goagrpc.ErrInvalidType("interceptors", "get", "*interceptors.GetResult", v) + } + resp := NewProtoGetResponse(result) + return resp, nil +} + +// DecodeGetRequest decodes requests sent to "interceptors" service "get" +// endpoint. +func DecodeGetRequest(ctx context.Context, v any, md metadata.MD) (any, error) { + var ( + message *interceptorspb.GetRequest + ok bool + ) + { + if message, ok = v.(*interceptorspb.GetRequest); !ok { + return nil, goagrpc.ErrInvalidType("interceptors", "get", "*interceptorspb.GetRequest", v) + } + if err := ValidateGetRequest(message); err != nil { + return nil, err + } + } + var payload *interceptors.GetPayload + { + payload = NewGetPayload(message) + } + return payload, nil +} diff --git a/interceptors/gen/grpc/interceptors/server/server.go b/interceptors/gen/grpc/interceptors/server/server.go new file mode 100644 index 000000000..024087c54 --- /dev/null +++ b/interceptors/gen/grpc/interceptors/server/server.go @@ -0,0 +1,62 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors gRPC server +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package server + +import ( + "context" + "errors" + + interceptorspb "goa.design/examples/interceptors/gen/grpc/interceptors/pb" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goagrpc "goa.design/goa/v3/grpc" + goa "goa.design/goa/v3/pkg" + "google.golang.org/grpc/codes" +) + +// Server implements the interceptorspb.InterceptorsServer interface. +type Server struct { + GetH goagrpc.UnaryHandler + interceptorspb.UnimplementedInterceptorsServer +} + +// New instantiates the server struct with the interceptors service endpoints. +func New(e *interceptors.Endpoints, uh goagrpc.UnaryHandler) *Server { + return &Server{ + GetH: NewGetHandler(e.Get, uh), + } +} + +// NewGetHandler creates a gRPC handler which serves the "interceptors" service +// "get" endpoint. +func NewGetHandler(endpoint goa.Endpoint, h goagrpc.UnaryHandler) goagrpc.UnaryHandler { + if h == nil { + h = goagrpc.NewUnaryHandler(endpoint, DecodeGetRequest, EncodeGetResponse) + } + return h +} + +// Get implements the "Get" method in interceptorspb.InterceptorsServer +// interface. +func (s *Server) Get(ctx context.Context, message *interceptorspb.GetRequest) (*interceptorspb.GetResponse, error) { + ctx = context.WithValue(ctx, goa.MethodKey, "get") + ctx = context.WithValue(ctx, goa.ServiceKey, "interceptors") + resp, err := s.GetH.Handle(ctx, message) + if err != nil { + var en goa.GoaErrorNamer + if errors.As(err, &en) { + switch en.GoaErrorName() { + case "NotFound": + return nil, goagrpc.NewStatusError(codes.NotFound, err, goagrpc.NewErrorResponse(err)) + case "Unavailable": + return nil, goagrpc.NewStatusError(codes.Unavailable, err, goagrpc.NewErrorResponse(err)) + } + } + return nil, goagrpc.EncodeError(err) + } + return resp.(*interceptorspb.GetResponse), nil +} diff --git a/interceptors/gen/grpc/interceptors/server/types.go b/interceptors/gen/grpc/interceptors/server/types.go new file mode 100644 index 000000000..ca081c16e --- /dev/null +++ b/interceptors/gen/grpc/interceptors/server/types.go @@ -0,0 +1,69 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors gRPC server types +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package server + +import ( + interceptorspb "goa.design/examples/interceptors/gen/grpc/interceptors/pb" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goa "goa.design/goa/v3/pkg" +) + +// NewGetPayload builds the payload of the "get" endpoint of the "interceptors" +// service from the gRPC request type. +func NewGetPayload(message *interceptorspb.GetRequest) *interceptors.GetPayload { + v := &interceptors.GetPayload{ + TenantID: interceptors.UUID(message.TenantId), + RecordID: interceptors.UUID(message.RecordId), + Auth: message.Auth, + } + if message.TraceId != nil { + traceID := interceptors.UUID(*message.TraceId) + v.TraceID = &traceID + } + if message.SpanId != nil { + spanID := interceptors.UUID(*message.SpanId) + v.SpanID = &spanID + } + return v +} + +// NewProtoGetResponse builds the gRPC response type from the result of the +// "get" endpoint of the "interceptors" service. +func NewProtoGetResponse(result *interceptors.GetResult) *interceptorspb.GetResponse { + message := &interceptorspb.GetResponse{ + Id: string(result.ID), + Value: result.Value, + Tenant: result.Tenant, + Status: int32(result.Status), + ProcessedAt: result.ProcessedAt, + Duration: int32(result.Duration), + CachedAt: result.CachedAt, + } + if result.RetryCount != nil { + retryCount := int32(*result.RetryCount) + message.RetryCount = &retryCount + } + if result.RetryDuration != nil { + retryDuration := int32(*result.RetryDuration) + message.RetryDuration = &retryDuration + } + return message +} + +// ValidateGetRequest runs the validations defined on GetRequest. +func ValidateGetRequest(message *interceptorspb.GetRequest) (err error) { + err = goa.MergeErrors(err, goa.ValidateFormat("message.tenantID", string(message.TenantId), goa.FormatUUID)) + err = goa.MergeErrors(err, goa.ValidateFormat("message.recordID", string(message.RecordId), goa.FormatUUID)) + if message.TraceId != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("message.traceID", string(*message.TraceId), goa.FormatUUID)) + } + if message.SpanId != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("message.spanID", string(*message.SpanId), goa.FormatUUID)) + } + return +} diff --git a/interceptors/gen/http/cli/interceptors/cli.go b/interceptors/gen/http/cli/interceptors/cli.go new file mode 100644 index 000000000..77cd21c4d --- /dev/null +++ b/interceptors/gen/http/cli/interceptors/cli.go @@ -0,0 +1,226 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors HTTP client CLI support package +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package cli + +import ( + "flag" + "fmt" + "net/http" + "os" + + interceptorsc "goa.design/examples/interceptors/gen/http/interceptors/client" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goahttp "goa.design/goa/v3/http" + goa "goa.design/goa/v3/pkg" +) + +// UsageCommands returns the set of commands and sub-commands using the format +// +// command (subcommand1|subcommand2|...) +func UsageCommands() string { + return `interceptors (get|create|stream) +` +} + +// UsageExamples produces an example of a valid invocation of the CLI tool. +func UsageExamples() string { + return os.Args[0] + ` interceptors get --body '{ + "spanID": "150d7874-6995-4405-9422-192a638fe1a3", + "traceID": "f03bb3ab-2f3b-4961-8396-30a04e467ad7" + }' --tenant-id "f2cd9ea9-8fd3-4b79-90a3-db4edb23981e" --record-id "7f502b4d-d893-45b1-a638-f84863ffa6eb" --auth "Mollitia harum eos consequatur aut qui."` + "\n" + + "" +} + +// ParseEndpoint returns the endpoint and payload as specified on the command +// line. +func ParseEndpoint( + scheme, host string, + doer goahttp.Doer, + enc func(*http.Request) goahttp.Encoder, + dec func(*http.Response) goahttp.Decoder, + restore bool, + dialer goahttp.Dialer, + interceptorsConfigurer *interceptorsc.ConnConfigurer, + inter interceptors.ClientInterceptors, +) (goa.Endpoint, any, error) { + var ( + interceptorsFlags = flag.NewFlagSet("interceptors", flag.ContinueOnError) + + interceptorsGetFlags = flag.NewFlagSet("get", flag.ExitOnError) + interceptorsGetBodyFlag = interceptorsGetFlags.String("body", "REQUIRED", "") + interceptorsGetTenantIDFlag = interceptorsGetFlags.String("tenant-id", "REQUIRED", "Tenant ID for the request") + interceptorsGetRecordIDFlag = interceptorsGetFlags.String("record-id", "REQUIRED", "ID of the record to retrieve") + interceptorsGetAuthFlag = interceptorsGetFlags.String("auth", "REQUIRED", "") + + interceptorsCreateFlags = flag.NewFlagSet("create", flag.ExitOnError) + interceptorsCreateBodyFlag = interceptorsCreateFlags.String("body", "REQUIRED", "") + interceptorsCreateTenantIDFlag = interceptorsCreateFlags.String("tenant-id", "REQUIRED", "Tenant ID for the request") + interceptorsCreateAuthFlag = interceptorsCreateFlags.String("auth", "REQUIRED", "") + + interceptorsStreamFlags = flag.NewFlagSet("stream", flag.ExitOnError) + interceptorsStreamTenantIDFlag = interceptorsStreamFlags.String("tenant-id", "REQUIRED", "Tenant ID for the request") + interceptorsStreamAuthFlag = interceptorsStreamFlags.String("auth", "REQUIRED", "") + ) + interceptorsFlags.Usage = interceptorsUsage + interceptorsGetFlags.Usage = interceptorsGetUsage + interceptorsCreateFlags.Usage = interceptorsCreateUsage + interceptorsStreamFlags.Usage = interceptorsStreamUsage + + if err := flag.CommandLine.Parse(os.Args[1:]); err != nil { + return nil, nil, err + } + + if flag.NArg() < 2 { // two non flag args are required: SERVICE and ENDPOINT (aka COMMAND) + return nil, nil, fmt.Errorf("not enough arguments") + } + + var ( + svcn string + svcf *flag.FlagSet + ) + { + svcn = flag.Arg(0) + switch svcn { + case "interceptors": + svcf = interceptorsFlags + default: + return nil, nil, fmt.Errorf("unknown service %q", svcn) + } + } + if err := svcf.Parse(flag.Args()[1:]); err != nil { + return nil, nil, err + } + + var ( + epn string + epf *flag.FlagSet + ) + { + epn = svcf.Arg(0) + switch svcn { + case "interceptors": + switch epn { + case "get": + epf = interceptorsGetFlags + + case "create": + epf = interceptorsCreateFlags + + case "stream": + epf = interceptorsStreamFlags + + } + + } + } + if epf == nil { + return nil, nil, fmt.Errorf("unknown %q endpoint %q", svcn, epn) + } + + // Parse endpoint flags if any + if svcf.NArg() > 1 { + if err := epf.Parse(svcf.Args()[1:]); err != nil { + return nil, nil, err + } + } + + var ( + data any + endpoint goa.Endpoint + err error + ) + { + switch svcn { + case "interceptors": + c := interceptorsc.NewClient(scheme, host, doer, enc, dec, restore, dialer, interceptorsConfigurer) + switch epn { + case "get": + endpoint = c.Get() + endpoint = interceptors.WrapGetClientEndpoint(endpoint, inter) + data, err = interceptorsc.BuildGetPayload(*interceptorsGetBodyFlag, *interceptorsGetTenantIDFlag, *interceptorsGetRecordIDFlag, *interceptorsGetAuthFlag) + case "create": + endpoint = c.Create() + endpoint = interceptors.WrapCreateClientEndpoint(endpoint, inter) + data, err = interceptorsc.BuildCreatePayload(*interceptorsCreateBodyFlag, *interceptorsCreateTenantIDFlag, *interceptorsCreateAuthFlag) + case "stream": + endpoint = c.Stream() + endpoint = interceptors.WrapStreamClientEndpoint(endpoint, inter) + data, err = interceptorsc.BuildStreamPayload(*interceptorsStreamTenantIDFlag, *interceptorsStreamAuthFlag) + } + } + } + if err != nil { + return nil, nil, err + } + + return endpoint, data, nil +} + +// interceptorsUsage displays the usage of the interceptors command and its +// subcommands. +func interceptorsUsage() { + fmt.Fprintf(os.Stderr, `The interceptors service demonstrates a comprehensive use of interceptors combining + authentication, tenant validation, caching, audit logging, and retry mechanisms. It showcases + both client-side and server-side interceptors working together to provide a robust service. +Usage: + %[1]s [globalflags] interceptors COMMAND [flags] + +COMMAND: + get: Get retrieves a record by ID with all interceptors in action + create: Create a new record with all interceptors in action + stream: Stream records + +Additional help: + %[1]s interceptors COMMAND --help +`, os.Args[0]) +} +func interceptorsGetUsage() { + fmt.Fprintf(os.Stderr, `%[1]s [flags] interceptors get -body JSON -tenant-id STRING -record-id STRING -auth STRING + +Get retrieves a record by ID with all interceptors in action + -body JSON: + -tenant-id STRING: Tenant ID for the request + -record-id STRING: ID of the record to retrieve + -auth STRING: + +Example: + %[1]s interceptors get --body '{ + "spanID": "150d7874-6995-4405-9422-192a638fe1a3", + "traceID": "f03bb3ab-2f3b-4961-8396-30a04e467ad7" + }' --tenant-id "f2cd9ea9-8fd3-4b79-90a3-db4edb23981e" --record-id "7f502b4d-d893-45b1-a638-f84863ffa6eb" --auth "Mollitia harum eos consequatur aut qui." +`, os.Args[0]) +} + +func interceptorsCreateUsage() { + fmt.Fprintf(os.Stderr, `%[1]s [flags] interceptors create -body JSON -tenant-id STRING -auth STRING + +Create a new record with all interceptors in action + -body JSON: + -tenant-id STRING: Tenant ID for the request + -auth STRING: + +Example: + %[1]s interceptors create --body '{ + "spanID": "60119d23-b695-492d-b0fb-4c5195591902", + "traceID": "d94bb031-1e29-4544-a640-ae17323e1a90", + "value": "Rerum nesciunt suscipit est quo." + }' --tenant-id "cb74657b-6207-403a-ac44-dcee07812d9c" --auth "Earum neque." +`, os.Args[0]) +} + +func interceptorsStreamUsage() { + fmt.Fprintf(os.Stderr, `%[1]s [flags] interceptors stream -tenant-id STRING -auth STRING + +Stream records + -tenant-id STRING: Tenant ID for the request + -auth STRING: + +Example: + %[1]s interceptors stream --tenant-id "32ced90b-a389-4014-96ee-998ad792affe" --auth "Provident illum voluptas repellat eum est omnis." +`, os.Args[0]) +} diff --git a/interceptors/gen/http/interceptors/client/cli.go b/interceptors/gen/http/interceptors/client/cli.go new file mode 100644 index 000000000..dec10f2ff --- /dev/null +++ b/interceptors/gen/http/interceptors/client/cli.go @@ -0,0 +1,144 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors HTTP client CLI support package +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package client + +import ( + "encoding/json" + "fmt" + + interceptors "goa.design/examples/interceptors/gen/interceptors" + goa "goa.design/goa/v3/pkg" +) + +// BuildGetPayload builds the payload for the interceptors get endpoint from +// CLI flags. +func BuildGetPayload(interceptorsGetBody string, interceptorsGetTenantID string, interceptorsGetRecordID string, interceptorsGetAuth string) (*interceptors.GetPayload, error) { + var err error + var body GetRequestBody + { + err = json.Unmarshal([]byte(interceptorsGetBody), &body) + if err != nil { + return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"spanID\": \"150d7874-6995-4405-9422-192a638fe1a3\",\n \"traceID\": \"f03bb3ab-2f3b-4961-8396-30a04e467ad7\"\n }'") + } + if body.TraceID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.traceID", *body.TraceID, goa.FormatUUID)) + } + if body.SpanID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.spanID", *body.SpanID, goa.FormatUUID)) + } + if err != nil { + return nil, err + } + } + var tenantID string + { + tenantID = interceptorsGetTenantID + err = goa.MergeErrors(err, goa.ValidateFormat("tenantID", tenantID, goa.FormatUUID)) + if err != nil { + return nil, err + } + } + var recordID string + { + recordID = interceptorsGetRecordID + err = goa.MergeErrors(err, goa.ValidateFormat("recordID", recordID, goa.FormatUUID)) + if err != nil { + return nil, err + } + } + var auth string + { + auth = interceptorsGetAuth + } + v := &interceptors.GetPayload{} + if body.TraceID != nil { + traceID := interceptors.UUID(*body.TraceID) + v.TraceID = &traceID + } + if body.SpanID != nil { + spanID := interceptors.UUID(*body.SpanID) + v.SpanID = &spanID + } + v.TenantID = interceptors.UUID(tenantID) + v.RecordID = interceptors.UUID(recordID) + v.Auth = auth + + return v, nil +} + +// BuildCreatePayload builds the payload for the interceptors create endpoint +// from CLI flags. +func BuildCreatePayload(interceptorsCreateBody string, interceptorsCreateTenantID string, interceptorsCreateAuth string) (*interceptors.CreatePayload, error) { + var err error + var body CreateRequestBody + { + err = json.Unmarshal([]byte(interceptorsCreateBody), &body) + if err != nil { + return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"spanID\": \"60119d23-b695-492d-b0fb-4c5195591902\",\n \"traceID\": \"d94bb031-1e29-4544-a640-ae17323e1a90\",\n \"value\": \"Rerum nesciunt suscipit est quo.\"\n }'") + } + if body.TraceID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.traceID", *body.TraceID, goa.FormatUUID)) + } + if body.SpanID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.spanID", *body.SpanID, goa.FormatUUID)) + } + if err != nil { + return nil, err + } + } + var tenantID string + { + tenantID = interceptorsCreateTenantID + err = goa.MergeErrors(err, goa.ValidateFormat("tenantID", tenantID, goa.FormatUUID)) + if err != nil { + return nil, err + } + } + var auth string + { + auth = interceptorsCreateAuth + } + v := &interceptors.CreatePayload{ + Value: body.Value, + } + if body.TraceID != nil { + traceID := interceptors.UUID(*body.TraceID) + v.TraceID = &traceID + } + if body.SpanID != nil { + spanID := interceptors.UUID(*body.SpanID) + v.SpanID = &spanID + } + v.TenantID = interceptors.UUID(tenantID) + v.Auth = auth + + return v, nil +} + +// BuildStreamPayload builds the payload for the interceptors stream endpoint +// from CLI flags. +func BuildStreamPayload(interceptorsStreamTenantID string, interceptorsStreamAuth string) (*interceptors.StreamPayload, error) { + var err error + var tenantID string + { + tenantID = interceptorsStreamTenantID + err = goa.MergeErrors(err, goa.ValidateFormat("tenantID", tenantID, goa.FormatUUID)) + if err != nil { + return nil, err + } + } + var auth string + { + auth = interceptorsStreamAuth + } + v := &interceptors.StreamPayload{} + v.TenantID = interceptors.UUID(tenantID) + v.Auth = auth + + return v, nil +} diff --git a/interceptors/gen/http/interceptors/client/client.go b/interceptors/gen/http/interceptors/client/client.go new file mode 100644 index 000000000..99197ffe3 --- /dev/null +++ b/interceptors/gen/http/interceptors/client/client.go @@ -0,0 +1,146 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors client HTTP transport +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package client + +import ( + "context" + "net/http" + + goahttp "goa.design/goa/v3/http" + goa "goa.design/goa/v3/pkg" +) + +// Client lists the interceptors service endpoint HTTP clients. +type Client struct { + // Get Doer is the HTTP client used to make requests to the get endpoint. + GetDoer goahttp.Doer + + // Create Doer is the HTTP client used to make requests to the create endpoint. + CreateDoer goahttp.Doer + + // Stream Doer is the HTTP client used to make requests to the stream endpoint. + StreamDoer goahttp.Doer + + // RestoreResponseBody controls whether the response bodies are reset after + // decoding so they can be read again. + RestoreResponseBody bool + + scheme string + host string + encoder func(*http.Request) goahttp.Encoder + decoder func(*http.Response) goahttp.Decoder + dialer goahttp.Dialer + configurer *ConnConfigurer +} + +// NewClient instantiates HTTP clients for all the interceptors service servers. +func NewClient( + scheme string, + host string, + doer goahttp.Doer, + enc func(*http.Request) goahttp.Encoder, + dec func(*http.Response) goahttp.Decoder, + restoreBody bool, + dialer goahttp.Dialer, + cfn *ConnConfigurer, +) *Client { + if cfn == nil { + cfn = &ConnConfigurer{} + } + return &Client{ + GetDoer: doer, + CreateDoer: doer, + StreamDoer: doer, + RestoreResponseBody: restoreBody, + scheme: scheme, + host: host, + decoder: dec, + encoder: enc, + dialer: dialer, + configurer: cfn, + } +} + +// Get returns an endpoint that makes HTTP requests to the interceptors service +// get server. +func (c *Client) Get() goa.Endpoint { + var ( + encodeRequest = EncodeGetRequest(c.encoder) + decodeResponse = DecodeGetResponse(c.decoder, c.RestoreResponseBody) + ) + return func(ctx context.Context, v any) (any, error) { + req, err := c.BuildGetRequest(ctx, v) + if err != nil { + return nil, err + } + err = encodeRequest(req, v) + if err != nil { + return nil, err + } + resp, err := c.GetDoer.Do(req) + if err != nil { + return nil, goahttp.ErrRequestError("interceptors", "get", err) + } + return decodeResponse(resp) + } +} + +// Create returns an endpoint that makes HTTP requests to the interceptors +// service create server. +func (c *Client) Create() goa.Endpoint { + var ( + encodeRequest = EncodeCreateRequest(c.encoder) + decodeResponse = DecodeCreateResponse(c.decoder, c.RestoreResponseBody) + ) + return func(ctx context.Context, v any) (any, error) { + req, err := c.BuildCreateRequest(ctx, v) + if err != nil { + return nil, err + } + err = encodeRequest(req, v) + if err != nil { + return nil, err + } + resp, err := c.CreateDoer.Do(req) + if err != nil { + return nil, goahttp.ErrRequestError("interceptors", "create", err) + } + return decodeResponse(resp) + } +} + +// Stream returns an endpoint that makes HTTP requests to the interceptors +// service stream server. +func (c *Client) Stream() goa.Endpoint { + var ( + encodeRequest = EncodeStreamRequest(c.encoder) + decodeResponse = DecodeStreamResponse(c.decoder, c.RestoreResponseBody) + ) + return func(ctx context.Context, v any) (any, error) { + req, err := c.BuildStreamRequest(ctx, v) + if err != nil { + return nil, err + } + err = encodeRequest(req, v) + if err != nil { + return nil, err + } + conn, resp, err := c.dialer.DialContext(ctx, req.URL.String(), req.Header) + if err != nil { + if resp != nil { + return decodeResponse(resp) + } + return nil, goahttp.ErrRequestError("interceptors", "stream", err) + } + if c.configurer.StreamFn != nil { + conn = c.configurer.StreamFn(conn, nil) + } + stream := &StreamClientStream{conn: conn} + return stream, nil + } +} diff --git a/interceptors/gen/http/interceptors/client/encode_decode.go b/interceptors/gen/http/interceptors/client/encode_decode.go new file mode 100644 index 000000000..78267058c --- /dev/null +++ b/interceptors/gen/http/interceptors/client/encode_decode.go @@ -0,0 +1,311 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors HTTP client encoders and decoders +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package client + +import ( + "bytes" + "context" + "io" + "net/http" + "net/url" + + interceptors "goa.design/examples/interceptors/gen/interceptors" + goahttp "goa.design/goa/v3/http" +) + +// BuildGetRequest instantiates a HTTP request object with method and path set +// to call the "interceptors" service "get" endpoint +func (c *Client) BuildGetRequest(ctx context.Context, v any) (*http.Request, error) { + var ( + tenantID string + recordID string + ) + { + p, ok := v.(*interceptors.GetPayload) + if !ok { + return nil, goahttp.ErrInvalidType("interceptors", "get", "*interceptors.GetPayload", v) + } + tenantID = string(p.TenantID) + recordID = string(p.RecordID) + } + u := &url.URL{Scheme: c.scheme, Host: c.host, Path: GetInterceptorsPath(tenantID, recordID)} + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return nil, goahttp.ErrInvalidURL("interceptors", "get", u.String(), err) + } + if ctx != nil { + req = req.WithContext(ctx) + } + + return req, nil +} + +// EncodeGetRequest returns an encoder for requests sent to the interceptors +// get server. +func EncodeGetRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, any) error { + return func(req *http.Request, v any) error { + p, ok := v.(*interceptors.GetPayload) + if !ok { + return goahttp.ErrInvalidType("interceptors", "get", "*interceptors.GetPayload", v) + } + { + head := p.Auth + req.Header.Set("Authorization", head) + } + body := NewGetRequestBody(p) + if err := encoder(req).Encode(&body); err != nil { + return goahttp.ErrEncodingError("interceptors", "get", err) + } + return nil + } +} + +// DecodeGetResponse returns a decoder for responses returned by the +// interceptors get endpoint. restoreBody controls whether the response body +// should be restored after having been read. +// DecodeGetResponse may return the following errors: +// - "NotFound" (type *goa.ServiceError): http.StatusNotFound +// - "Unavailable" (type *goa.ServiceError): http.StatusServiceUnavailable +// - error: internal error +func DecodeGetResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { + return func(resp *http.Response) (any, error) { + if restoreBody { + b, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + defer func() { + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + }() + } else { + defer resp.Body.Close() + } + switch resp.StatusCode { + case http.StatusOK: + var ( + body GetResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("interceptors", "get", err) + } + err = ValidateGetResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("interceptors", "get", err) + } + res := NewGetResultOK(&body) + return res, nil + case http.StatusNotFound: + var ( + body GetNotFoundResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("interceptors", "get", err) + } + err = ValidateGetNotFoundResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("interceptors", "get", err) + } + return nil, NewGetNotFound(&body) + case http.StatusServiceUnavailable: + var ( + body GetUnavailableResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("interceptors", "get", err) + } + err = ValidateGetUnavailableResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("interceptors", "get", err) + } + return nil, NewGetUnavailable(&body) + default: + body, _ := io.ReadAll(resp.Body) + return nil, goahttp.ErrInvalidResponse("interceptors", "get", resp.StatusCode, string(body)) + } + } +} + +// BuildCreateRequest instantiates a HTTP request object with method and path +// set to call the "interceptors" service "create" endpoint +func (c *Client) BuildCreateRequest(ctx context.Context, v any) (*http.Request, error) { + var ( + tenantID string + ) + { + p, ok := v.(*interceptors.CreatePayload) + if !ok { + return nil, goahttp.ErrInvalidType("interceptors", "create", "*interceptors.CreatePayload", v) + } + tenantID = string(p.TenantID) + } + u := &url.URL{Scheme: c.scheme, Host: c.host, Path: CreateInterceptorsPath(tenantID)} + req, err := http.NewRequest("POST", u.String(), nil) + if err != nil { + return nil, goahttp.ErrInvalidURL("interceptors", "create", u.String(), err) + } + if ctx != nil { + req = req.WithContext(ctx) + } + + return req, nil +} + +// EncodeCreateRequest returns an encoder for requests sent to the interceptors +// create server. +func EncodeCreateRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, any) error { + return func(req *http.Request, v any) error { + p, ok := v.(*interceptors.CreatePayload) + if !ok { + return goahttp.ErrInvalidType("interceptors", "create", "*interceptors.CreatePayload", v) + } + { + head := p.Auth + req.Header.Set("Authorization", head) + } + body := NewCreateRequestBody(p) + if err := encoder(req).Encode(&body); err != nil { + return goahttp.ErrEncodingError("interceptors", "create", err) + } + return nil + } +} + +// DecodeCreateResponse returns a decoder for responses returned by the +// interceptors create endpoint. restoreBody controls whether the response body +// should be restored after having been read. +func DecodeCreateResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { + return func(resp *http.Response) (any, error) { + if restoreBody { + b, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + defer func() { + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + }() + } else { + defer resp.Body.Close() + } + switch resp.StatusCode { + case http.StatusCreated: + var ( + body CreateResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("interceptors", "create", err) + } + err = ValidateCreateResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("interceptors", "create", err) + } + res := NewCreateResultCreated(&body) + return res, nil + default: + body, _ := io.ReadAll(resp.Body) + return nil, goahttp.ErrInvalidResponse("interceptors", "create", resp.StatusCode, string(body)) + } + } +} + +// BuildStreamRequest instantiates a HTTP request object with method and path +// set to call the "interceptors" service "stream" endpoint +func (c *Client) BuildStreamRequest(ctx context.Context, v any) (*http.Request, error) { + var ( + tenantID string + ) + { + p, ok := v.(*interceptors.StreamPayload) + if !ok { + return nil, goahttp.ErrInvalidType("interceptors", "stream", "*interceptors.StreamPayload", v) + } + tenantID = string(p.TenantID) + } + scheme := c.scheme + switch c.scheme { + case "http": + scheme = "ws" + case "https": + scheme = "wss" + } + u := &url.URL{Scheme: scheme, Host: c.host, Path: StreamInterceptorsPath(tenantID)} + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return nil, goahttp.ErrInvalidURL("interceptors", "stream", u.String(), err) + } + if ctx != nil { + req = req.WithContext(ctx) + } + + return req, nil +} + +// EncodeStreamRequest returns an encoder for requests sent to the interceptors +// stream server. +func EncodeStreamRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, any) error { + return func(req *http.Request, v any) error { + p, ok := v.(*interceptors.StreamPayload) + if !ok { + return goahttp.ErrInvalidType("interceptors", "stream", "*interceptors.StreamPayload", v) + } + { + head := p.Auth + req.Header.Set("Authorization", head) + } + return nil + } +} + +// DecodeStreamResponse returns a decoder for responses returned by the +// interceptors stream endpoint. restoreBody controls whether the response body +// should be restored after having been read. +func DecodeStreamResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { + return func(resp *http.Response) (any, error) { + if restoreBody { + b, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + defer func() { + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + }() + } else { + defer resp.Body.Close() + } + switch resp.StatusCode { + case http.StatusOK: + var ( + body StreamResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("interceptors", "stream", err) + } + err = ValidateStreamResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("interceptors", "stream", err) + } + res := NewStreamResultOK(&body) + return res, nil + default: + body, _ := io.ReadAll(resp.Body) + return nil, goahttp.ErrInvalidResponse("interceptors", "stream", resp.StatusCode, string(body)) + } + } +} diff --git a/interceptors/gen/http/interceptors/client/paths.go b/interceptors/gen/http/interceptors/client/paths.go new file mode 100644 index 000000000..83fe87420 --- /dev/null +++ b/interceptors/gen/http/interceptors/client/paths.go @@ -0,0 +1,27 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// HTTP request path constructors for the interceptors service. +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package client + +import ( + "fmt" +) + +// GetInterceptorsPath returns the URL path to the interceptors service get HTTP endpoint. +func GetInterceptorsPath(tenantID string, recordID string) string { + return fmt.Sprintf("/records/%v/%v", tenantID, recordID) +} + +// CreateInterceptorsPath returns the URL path to the interceptors service create HTTP endpoint. +func CreateInterceptorsPath(tenantID string) string { + return fmt.Sprintf("/records/%v", tenantID) +} + +// StreamInterceptorsPath returns the URL path to the interceptors service stream HTTP endpoint. +func StreamInterceptorsPath(tenantID string) string { + return fmt.Sprintf("/records/%v/stream", tenantID) +} diff --git a/interceptors/gen/http/interceptors/client/types.go b/interceptors/gen/http/interceptors/client/types.go new file mode 100644 index 000000000..7e70094b9 --- /dev/null +++ b/interceptors/gen/http/interceptors/client/types.go @@ -0,0 +1,407 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors HTTP client types +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package client + +import ( + interceptors "goa.design/examples/interceptors/gen/interceptors" + goa "goa.design/goa/v3/pkg" +) + +// GetRequestBody is the type of the "interceptors" service "get" endpoint HTTP +// request body. +type GetRequestBody struct { + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *string `form:"traceID,omitempty" json:"traceID,omitempty" xml:"traceID,omitempty"` + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *string `form:"spanID,omitempty" json:"spanID,omitempty" xml:"spanID,omitempty"` +} + +// CreateRequestBody is the type of the "interceptors" service "create" +// endpoint HTTP request body. +type CreateRequestBody struct { + // Value to store in record + Value string `form:"value" json:"value" xml:"value"` + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *string `form:"traceID,omitempty" json:"traceID,omitempty" xml:"traceID,omitempty"` + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *string `form:"spanID,omitempty" json:"spanID,omitempty" xml:"spanID,omitempty"` +} + +// StreamStreamingBody is the type of the "interceptors" service "stream" +// endpoint HTTP request body. +type StreamStreamingBody struct { + // ID of the created record + ID UUIDStreamingBody `form:"id" json:"id" xml:"id"` + // Value of the record + Value string `form:"value" json:"value" xml:"value"` + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *UUIDStreamingBody `form:"traceID,omitempty" json:"traceID,omitempty" xml:"traceID,omitempty"` + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *UUIDStreamingBody `form:"spanID,omitempty" json:"spanID,omitempty" xml:"spanID,omitempty"` +} + +// GetResponseBody is the type of the "interceptors" service "get" endpoint +// HTTP response body. +type GetResponseBody struct { + // ID of the record + ID *string `form:"id,omitempty" json:"id,omitempty" xml:"id,omitempty"` + // Value of the record + Value *string `form:"value,omitempty" json:"value,omitempty" xml:"value,omitempty"` + // Tenant the record belongs to + Tenant *string `form:"tenant,omitempty" json:"tenant,omitempty" xml:"tenant,omitempty"` + // Response status code + Status *int `form:"status,omitempty" json:"status,omitempty" xml:"status,omitempty"` + // Timestamp when processed, written by the RequestAudit interceptor + ProcessedAt *string `form:"processedAt,omitempty" json:"processedAt,omitempty" xml:"processedAt,omitempty"` + // Processing duration in ms, written by the RequestAudit interceptor + Duration *int `form:"duration,omitempty" json:"duration,omitempty" xml:"duration,omitempty"` + // Time at which the record was cached, written by the Cache interceptor + CachedAt *string `form:"cachedAt,omitempty" json:"cachedAt,omitempty" xml:"cachedAt,omitempty"` + // Number of retry attempts made, written client-side by the Retry interceptor + RetryCount *int `form:"retryCount,omitempty" json:"retryCount,omitempty" xml:"retryCount,omitempty"` + // Total time spent retrying, written client-side by the Retry interceptor + RetryDuration *int `form:"retryDuration,omitempty" json:"retryDuration,omitempty" xml:"retryDuration,omitempty"` +} + +// CreateResponseBody is the type of the "interceptors" service "create" +// endpoint HTTP response body. +type CreateResponseBody struct { + // ID of the created record + ID *string `form:"id,omitempty" json:"id,omitempty" xml:"id,omitempty"` + // Value of the record + Value *string `form:"value,omitempty" json:"value,omitempty" xml:"value,omitempty"` + // Tenant the record belongs to + Tenant *string `form:"tenant,omitempty" json:"tenant,omitempty" xml:"tenant,omitempty"` + // Response status code + Status *int `form:"status,omitempty" json:"status,omitempty" xml:"status,omitempty"` + // Timestamp when processed + ProcessedAt *string `form:"processedAt,omitempty" json:"processedAt,omitempty" xml:"processedAt,omitempty"` + // Processing duration in ms + Duration *int `form:"duration,omitempty" json:"duration,omitempty" xml:"duration,omitempty"` + // Number of retry attempts made + RetryCount *int `form:"retryCount,omitempty" json:"retryCount,omitempty" xml:"retryCount,omitempty"` + // Total time spent retrying + RetryDuration *int `form:"retryDuration,omitempty" json:"retryDuration,omitempty" xml:"retryDuration,omitempty"` +} + +// StreamResponseBody is the type of the "interceptors" service "stream" +// endpoint HTTP response body. +type StreamResponseBody struct { + // ID of the created record + ID *string `form:"id,omitempty" json:"id,omitempty" xml:"id,omitempty"` + // Value of the record + Value *string `form:"value,omitempty" json:"value,omitempty" xml:"value,omitempty"` + // Tenant the record belongs to + Tenant *string `form:"tenant,omitempty" json:"tenant,omitempty" xml:"tenant,omitempty"` + // Response status code + Status *int `form:"status,omitempty" json:"status,omitempty" xml:"status,omitempty"` + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *string `form:"traceID,omitempty" json:"traceID,omitempty" xml:"traceID,omitempty"` + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *string `form:"spanID,omitempty" json:"spanID,omitempty" xml:"spanID,omitempty"` +} + +// GetNotFoundResponseBody is the type of the "interceptors" service "get" +// endpoint HTTP response body for the "NotFound" error. +type GetNotFoundResponseBody struct { + // Name is the name of this class of errors. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // ID is a unique identifier for this particular occurrence of the problem. + ID *string `form:"id,omitempty" json:"id,omitempty" xml:"id,omitempty"` + // Message is a human-readable explanation specific to this occurrence of the + // problem. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` + // Is the error temporary? + Temporary *bool `form:"temporary,omitempty" json:"temporary,omitempty" xml:"temporary,omitempty"` + // Is the error a timeout? + Timeout *bool `form:"timeout,omitempty" json:"timeout,omitempty" xml:"timeout,omitempty"` + // Is the error a server-side fault? + Fault *bool `form:"fault,omitempty" json:"fault,omitempty" xml:"fault,omitempty"` +} + +// GetUnavailableResponseBody is the type of the "interceptors" service "get" +// endpoint HTTP response body for the "Unavailable" error. +type GetUnavailableResponseBody struct { + // Name is the name of this class of errors. + Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + // ID is a unique identifier for this particular occurrence of the problem. + ID *string `form:"id,omitempty" json:"id,omitempty" xml:"id,omitempty"` + // Message is a human-readable explanation specific to this occurrence of the + // problem. + Message *string `form:"message,omitempty" json:"message,omitempty" xml:"message,omitempty"` + // Is the error temporary? + Temporary *bool `form:"temporary,omitempty" json:"temporary,omitempty" xml:"temporary,omitempty"` + // Is the error a timeout? + Timeout *bool `form:"timeout,omitempty" json:"timeout,omitempty" xml:"timeout,omitempty"` + // Is the error a server-side fault? + Fault *bool `form:"fault,omitempty" json:"fault,omitempty" xml:"fault,omitempty"` +} + +// UUIDStreamingBody is used to define fields on request body types. +type UUIDStreamingBody string + +// NewGetRequestBody builds the HTTP request body from the payload of the "get" +// endpoint of the "interceptors" service. +func NewGetRequestBody(p *interceptors.GetPayload) *GetRequestBody { + body := &GetRequestBody{} + if p.TraceID != nil { + traceID := string(*p.TraceID) + body.TraceID = &traceID + } + if p.SpanID != nil { + spanID := string(*p.SpanID) + body.SpanID = &spanID + } + return body +} + +// NewCreateRequestBody builds the HTTP request body from the payload of the +// "create" endpoint of the "interceptors" service. +func NewCreateRequestBody(p *interceptors.CreatePayload) *CreateRequestBody { + body := &CreateRequestBody{ + Value: p.Value, + } + if p.TraceID != nil { + traceID := string(*p.TraceID) + body.TraceID = &traceID + } + if p.SpanID != nil { + spanID := string(*p.SpanID) + body.SpanID = &spanID + } + return body +} + +// NewStreamStreamingBody builds the HTTP request body from the payload of the +// "stream" endpoint of the "interceptors" service. +func NewStreamStreamingBody(p *interceptors.StreamStreamingPayload) *StreamStreamingBody { + body := &StreamStreamingBody{ + ID: UUIDStreamingBody(p.ID), + Value: p.Value, + } + if p.TraceID != nil { + traceID := UUIDStreamingBody(*p.TraceID) + body.TraceID = &traceID + } + if p.SpanID != nil { + spanID := UUIDStreamingBody(*p.SpanID) + body.SpanID = &spanID + } + return body +} + +// NewGetResultOK builds a "interceptors" service "get" endpoint result from a +// HTTP "OK" response. +func NewGetResultOK(body *GetResponseBody) *interceptors.GetResult { + v := &interceptors.GetResult{ + ID: interceptors.UUID(*body.ID), + Value: *body.Value, + Tenant: *body.Tenant, + Status: *body.Status, + ProcessedAt: *body.ProcessedAt, + Duration: *body.Duration, + CachedAt: body.CachedAt, + RetryCount: body.RetryCount, + RetryDuration: body.RetryDuration, + } + + return v +} + +// NewGetNotFound builds a interceptors service get endpoint NotFound error. +func NewGetNotFound(body *GetNotFoundResponseBody) *goa.ServiceError { + v := &goa.ServiceError{ + Name: *body.Name, + ID: *body.ID, + Message: *body.Message, + Temporary: *body.Temporary, + Timeout: *body.Timeout, + Fault: *body.Fault, + } + + return v +} + +// NewGetUnavailable builds a interceptors service get endpoint Unavailable +// error. +func NewGetUnavailable(body *GetUnavailableResponseBody) *goa.ServiceError { + v := &goa.ServiceError{ + Name: *body.Name, + ID: *body.ID, + Message: *body.Message, + Temporary: *body.Temporary, + Timeout: *body.Timeout, + Fault: *body.Fault, + } + + return v +} + +// NewCreateResultCreated builds a "interceptors" service "create" endpoint +// result from a HTTP "Created" response. +func NewCreateResultCreated(body *CreateResponseBody) *interceptors.CreateResult { + v := &interceptors.CreateResult{ + ID: interceptors.UUID(*body.ID), + Value: *body.Value, + Tenant: *body.Tenant, + Status: *body.Status, + ProcessedAt: *body.ProcessedAt, + Duration: *body.Duration, + RetryCount: body.RetryCount, + RetryDuration: body.RetryDuration, + } + + return v +} + +// NewStreamResultOK builds a "interceptors" service "stream" endpoint result +// from a HTTP "OK" response. +func NewStreamResultOK(body *StreamResponseBody) *interceptors.StreamResult { + v := &interceptors.StreamResult{ + ID: interceptors.UUID(*body.ID), + Value: *body.Value, + Tenant: *body.Tenant, + Status: *body.Status, + } + if body.TraceID != nil { + traceID := interceptors.UUID(*body.TraceID) + v.TraceID = &traceID + } + if body.SpanID != nil { + spanID := interceptors.UUID(*body.SpanID) + v.SpanID = &spanID + } + + return v +} + +// ValidateGetResponseBody runs the validations defined on GetResponseBody +func ValidateGetResponseBody(body *GetResponseBody) (err error) { + if body.ID == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("id", "body")) + } + if body.Value == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("value", "body")) + } + if body.Tenant == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("tenant", "body")) + } + if body.Status == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("status", "body")) + } + if body.ProcessedAt == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("processedAt", "body")) + } + if body.Duration == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("duration", "body")) + } + if body.ID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.id", *body.ID, goa.FormatUUID)) + } + return +} + +// ValidateCreateResponseBody runs the validations defined on CreateResponseBody +func ValidateCreateResponseBody(body *CreateResponseBody) (err error) { + if body.ID == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("id", "body")) + } + if body.Value == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("value", "body")) + } + if body.Tenant == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("tenant", "body")) + } + if body.Status == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("status", "body")) + } + if body.ProcessedAt == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("processedAt", "body")) + } + if body.Duration == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("duration", "body")) + } + if body.ID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.id", *body.ID, goa.FormatUUID)) + } + return +} + +// ValidateStreamResponseBody runs the validations defined on StreamResponseBody +func ValidateStreamResponseBody(body *StreamResponseBody) (err error) { + if body.ID == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("id", "body")) + } + if body.Value == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("value", "body")) + } + if body.Tenant == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("tenant", "body")) + } + if body.Status == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("status", "body")) + } + if body.ID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.id", *body.ID, goa.FormatUUID)) + } + if body.TraceID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.traceID", *body.TraceID, goa.FormatUUID)) + } + if body.SpanID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.spanID", *body.SpanID, goa.FormatUUID)) + } + return +} + +// ValidateGetNotFoundResponseBody runs the validations defined on +// get_NotFound_response_body +func ValidateGetNotFoundResponseBody(body *GetNotFoundResponseBody) (err error) { + if body.Name == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("name", "body")) + } + if body.ID == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("id", "body")) + } + if body.Message == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("message", "body")) + } + if body.Temporary == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("temporary", "body")) + } + if body.Timeout == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("timeout", "body")) + } + if body.Fault == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("fault", "body")) + } + return +} + +// ValidateGetUnavailableResponseBody runs the validations defined on +// get_Unavailable_response_body +func ValidateGetUnavailableResponseBody(body *GetUnavailableResponseBody) (err error) { + if body.Name == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("name", "body")) + } + if body.ID == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("id", "body")) + } + if body.Message == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("message", "body")) + } + if body.Temporary == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("temporary", "body")) + } + if body.Timeout == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("timeout", "body")) + } + if body.Fault == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("fault", "body")) + } + return +} diff --git a/interceptors/gen/http/interceptors/client/websocket.go b/interceptors/gen/http/interceptors/client/websocket.go new file mode 100644 index 000000000..fb401a6b2 --- /dev/null +++ b/interceptors/gen/http/interceptors/client/websocket.go @@ -0,0 +1,89 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors WebSocket client streaming +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package client + +import ( + "context" + "io" + + "github.com/gorilla/websocket" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goahttp "goa.design/goa/v3/http" +) + +// ConnConfigurer holds the websocket connection configurer functions for the +// streaming endpoints in "interceptors" service. +type ConnConfigurer struct { + StreamFn goahttp.ConnConfigureFunc +} + +// StreamClientStream implements the interceptors.StreamClientStream interface. +type StreamClientStream struct { + // conn is the underlying websocket connection. + conn *websocket.Conn +} + +// NewConnConfigurer initializes the websocket connection configurer function +// with fn for all the streaming endpoints in "interceptors" service. +func NewConnConfigurer(fn goahttp.ConnConfigureFunc) *ConnConfigurer { + return &ConnConfigurer{ + StreamFn: fn, + } +} + +// Recv reads instances of "interceptors.StreamResult" from the "stream" +// endpoint websocket connection. +func (s *StreamClientStream) Recv() (*interceptors.StreamResult, error) { + var ( + rv *interceptors.StreamResult + body StreamResponseBody + err error + ) + err = s.conn.ReadJSON(&body) + if websocket.IsCloseError(err, websocket.CloseNormalClosure) { + return rv, io.EOF + } + if err != nil { + return rv, err + } + err = ValidateStreamResponseBody(&body) + if err != nil { + return rv, err + } + res := NewStreamResultOK(&body) + return res, nil +} + +// RecvWithContext reads instances of "interceptors.StreamResult" from the +// "stream" endpoint websocket connection with context. +func (s *StreamClientStream) RecvWithContext(ctx context.Context) (*interceptors.StreamResult, error) { + return s.Recv() +} + +// Send streams instances of "interceptors.StreamStreamingPayload" to the +// "stream" endpoint websocket connection. +func (s *StreamClientStream) Send(v *interceptors.StreamStreamingPayload) error { + body := NewStreamStreamingBody(v) + return s.conn.WriteJSON(body) +} + +// SendWithContext streams instances of "interceptors.StreamStreamingPayload" +// to the "stream" endpoint websocket connection with context. +func (s *StreamClientStream) SendWithContext(ctx context.Context, v *interceptors.StreamStreamingPayload) error { + return s.Send(v) +} + +// Close closes the "stream" endpoint websocket connection. +func (s *StreamClientStream) Close() error { + var err error + // Send a nil payload to the server implying client closing connection. + if err = s.conn.WriteJSON(nil); err != nil { + return err + } + return s.conn.Close() +} diff --git a/interceptors/gen/http/interceptors/server/encode_decode.go b/interceptors/gen/http/interceptors/server/encode_decode.go new file mode 100644 index 000000000..3bb9edb72 --- /dev/null +++ b/interceptors/gen/http/interceptors/server/encode_decode.go @@ -0,0 +1,204 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors HTTP server encoders and decoders +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package server + +import ( + "context" + "errors" + "io" + "net/http" + + interceptors "goa.design/examples/interceptors/gen/interceptors" + goahttp "goa.design/goa/v3/http" + goa "goa.design/goa/v3/pkg" +) + +// EncodeGetResponse returns an encoder for responses returned by the +// interceptors get endpoint. +func EncodeGetResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { + return func(ctx context.Context, w http.ResponseWriter, v any) error { + res, _ := v.(*interceptors.GetResult) + enc := encoder(ctx, w) + body := NewGetResponseBody(res) + w.WriteHeader(http.StatusOK) + return enc.Encode(body) + } +} + +// DecodeGetRequest returns a decoder for requests sent to the interceptors get +// endpoint. +func DecodeGetRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) { + return func(r *http.Request) (any, error) { + var ( + body GetRequestBody + err error + ) + err = decoder(r).Decode(&body) + if err != nil { + if err == io.EOF { + return nil, goa.MissingPayloadError() + } + var gerr *goa.ServiceError + if errors.As(err, &gerr) { + return nil, gerr + } + return nil, goa.DecodePayloadError(err.Error()) + } + err = ValidateGetRequestBody(&body) + if err != nil { + return nil, err + } + + var ( + tenantID string + recordID string + auth string + + params = mux.Vars(r) + ) + tenantID = params["tenantID"] + err = goa.MergeErrors(err, goa.ValidateFormat("tenantID", tenantID, goa.FormatUUID)) + recordID = params["recordID"] + err = goa.MergeErrors(err, goa.ValidateFormat("recordID", recordID, goa.FormatUUID)) + auth = r.Header.Get("Authorization") + if auth == "" { + err = goa.MergeErrors(err, goa.MissingFieldError("auth", "header")) + } + if err != nil { + return nil, err + } + payload := NewGetPayload(&body, tenantID, recordID, auth) + + return payload, nil + } +} + +// EncodeGetError returns an encoder for errors returned by the get +// interceptors endpoint. +func EncodeGetError(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, formatter func(ctx context.Context, err error) goahttp.Statuser) func(context.Context, http.ResponseWriter, error) error { + encodeError := goahttp.ErrorEncoder(encoder, formatter) + return func(ctx context.Context, w http.ResponseWriter, v error) error { + var en goa.GoaErrorNamer + if !errors.As(v, &en) { + return encodeError(ctx, w, v) + } + switch en.GoaErrorName() { + case "NotFound": + var res *goa.ServiceError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewGetNotFoundResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusNotFound) + return enc.Encode(body) + case "Unavailable": + var res *goa.ServiceError + errors.As(v, &res) + enc := encoder(ctx, w) + var body any + if formatter != nil { + body = formatter(ctx, res) + } else { + body = NewGetUnavailableResponseBody(res) + } + w.Header().Set("goa-error", res.GoaErrorName()) + w.WriteHeader(http.StatusServiceUnavailable) + return enc.Encode(body) + default: + return encodeError(ctx, w, v) + } + } +} + +// EncodeCreateResponse returns an encoder for responses returned by the +// interceptors create endpoint. +func EncodeCreateResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { + return func(ctx context.Context, w http.ResponseWriter, v any) error { + res, _ := v.(*interceptors.CreateResult) + enc := encoder(ctx, w) + body := NewCreateResponseBody(res) + w.WriteHeader(http.StatusCreated) + return enc.Encode(body) + } +} + +// DecodeCreateRequest returns a decoder for requests sent to the interceptors +// create endpoint. +func DecodeCreateRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) { + return func(r *http.Request) (any, error) { + var ( + body CreateRequestBody + err error + ) + err = decoder(r).Decode(&body) + if err != nil { + if err == io.EOF { + return nil, goa.MissingPayloadError() + } + var gerr *goa.ServiceError + if errors.As(err, &gerr) { + return nil, gerr + } + return nil, goa.DecodePayloadError(err.Error()) + } + err = ValidateCreateRequestBody(&body) + if err != nil { + return nil, err + } + + var ( + tenantID string + auth string + + params = mux.Vars(r) + ) + tenantID = params["tenantID"] + err = goa.MergeErrors(err, goa.ValidateFormat("tenantID", tenantID, goa.FormatUUID)) + auth = r.Header.Get("Authorization") + if auth == "" { + err = goa.MergeErrors(err, goa.MissingFieldError("auth", "header")) + } + if err != nil { + return nil, err + } + payload := NewCreatePayload(&body, tenantID, auth) + + return payload, nil + } +} + +// DecodeStreamRequest returns a decoder for requests sent to the interceptors +// stream endpoint. +func DecodeStreamRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) { + return func(r *http.Request) (any, error) { + var ( + tenantID string + auth string + err error + + params = mux.Vars(r) + ) + tenantID = params["tenantID"] + err = goa.MergeErrors(err, goa.ValidateFormat("tenantID", tenantID, goa.FormatUUID)) + auth = r.Header.Get("Authorization") + if auth == "" { + err = goa.MergeErrors(err, goa.MissingFieldError("auth", "header")) + } + if err != nil { + return nil, err + } + payload := NewStreamPayload(tenantID, auth) + + return payload, nil + } +} diff --git a/interceptors/gen/http/interceptors/server/paths.go b/interceptors/gen/http/interceptors/server/paths.go new file mode 100644 index 000000000..eb3081143 --- /dev/null +++ b/interceptors/gen/http/interceptors/server/paths.go @@ -0,0 +1,27 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// HTTP request path constructors for the interceptors service. +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package server + +import ( + "fmt" +) + +// GetInterceptorsPath returns the URL path to the interceptors service get HTTP endpoint. +func GetInterceptorsPath(tenantID string, recordID string) string { + return fmt.Sprintf("/records/%v/%v", tenantID, recordID) +} + +// CreateInterceptorsPath returns the URL path to the interceptors service create HTTP endpoint. +func CreateInterceptorsPath(tenantID string) string { + return fmt.Sprintf("/records/%v", tenantID) +} + +// StreamInterceptorsPath returns the URL path to the interceptors service stream HTTP endpoint. +func StreamInterceptorsPath(tenantID string) string { + return fmt.Sprintf("/records/%v/stream", tenantID) +} diff --git a/interceptors/gen/http/interceptors/server/server.go b/interceptors/gen/http/interceptors/server/server.go new file mode 100644 index 000000000..16004b9f7 --- /dev/null +++ b/interceptors/gen/http/interceptors/server/server.go @@ -0,0 +1,260 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors HTTP server +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package server + +import ( + "context" + "net/http" + + interceptors "goa.design/examples/interceptors/gen/interceptors" + goahttp "goa.design/goa/v3/http" + goa "goa.design/goa/v3/pkg" +) + +// Server lists the interceptors service endpoint HTTP handlers. +type Server struct { + Mounts []*MountPoint + Get http.Handler + Create http.Handler + Stream http.Handler +} + +// MountPoint holds information about the mounted endpoints. +type MountPoint struct { + // Method is the name of the service method served by the mounted HTTP handler. + Method string + // Verb is the HTTP method used to match requests to the mounted handler. + Verb string + // Pattern is the HTTP request path pattern used to match requests to the + // mounted handler. + Pattern string +} + +// New instantiates HTTP handlers for all the interceptors service endpoints +// using the provided encoder and decoder. The handlers are mounted on the +// given mux using the HTTP verb and path defined in the design. errhandler is +// called whenever a response fails to be encoded. formatter is used to format +// errors returned by the service methods prior to encoding. Both errhandler +// and formatter are optional and can be nil. +func New( + e *interceptors.Endpoints, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(ctx context.Context, err error) goahttp.Statuser, + upgrader goahttp.Upgrader, + configurer *ConnConfigurer, +) *Server { + if configurer == nil { + configurer = &ConnConfigurer{} + } + return &Server{ + Mounts: []*MountPoint{ + {"Get", "GET", "/records/{tenantID}/{recordID}"}, + {"Create", "POST", "/records/{tenantID}"}, + {"Stream", "GET", "/records/{tenantID}/stream"}, + }, + Get: NewGetHandler(e.Get, mux, decoder, encoder, errhandler, formatter), + Create: NewCreateHandler(e.Create, mux, decoder, encoder, errhandler, formatter), + Stream: NewStreamHandler(e.Stream, mux, decoder, encoder, errhandler, formatter, upgrader, configurer.StreamFn), + } +} + +// Service returns the name of the service served. +func (s *Server) Service() string { return "interceptors" } + +// Use wraps the server handlers with the given middleware. +func (s *Server) Use(m func(http.Handler) http.Handler) { + s.Get = m(s.Get) + s.Create = m(s.Create) + s.Stream = m(s.Stream) +} + +// MethodNames returns the methods served. +func (s *Server) MethodNames() []string { return interceptors.MethodNames[:] } + +// Mount configures the mux to serve the interceptors endpoints. +func Mount(mux goahttp.Muxer, h *Server) { + MountGetHandler(mux, h.Get) + MountCreateHandler(mux, h.Create) + MountStreamHandler(mux, h.Stream) +} + +// Mount configures the mux to serve the interceptors endpoints. +func (s *Server) Mount(mux goahttp.Muxer) { + Mount(mux, s) +} + +// MountGetHandler configures the mux to serve the "interceptors" service "get" +// endpoint. +func MountGetHandler(mux goahttp.Muxer, h http.Handler) { + f, ok := h.(http.HandlerFunc) + if !ok { + f = func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + } + } + mux.Handle("GET", "/records/{tenantID}/{recordID}", f) +} + +// NewGetHandler creates a HTTP handler which loads the HTTP request and calls +// the "interceptors" service "get" endpoint. +func NewGetHandler( + endpoint goa.Endpoint, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(ctx context.Context, err error) goahttp.Statuser, +) http.Handler { + var ( + decodeRequest = DecodeGetRequest(mux, decoder) + encodeResponse = EncodeGetResponse(encoder) + encodeError = EncodeGetError(encoder, formatter) + ) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) + ctx = context.WithValue(ctx, goa.MethodKey, "get") + ctx = context.WithValue(ctx, goa.ServiceKey, "interceptors") + payload, err := decodeRequest(r) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + res, err := endpoint(ctx, payload) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + if err := encodeResponse(ctx, w, res); err != nil { + errhandler(ctx, w, err) + } + }) +} + +// MountCreateHandler configures the mux to serve the "interceptors" service +// "create" endpoint. +func MountCreateHandler(mux goahttp.Muxer, h http.Handler) { + f, ok := h.(http.HandlerFunc) + if !ok { + f = func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + } + } + mux.Handle("POST", "/records/{tenantID}", f) +} + +// NewCreateHandler creates a HTTP handler which loads the HTTP request and +// calls the "interceptors" service "create" endpoint. +func NewCreateHandler( + endpoint goa.Endpoint, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(ctx context.Context, err error) goahttp.Statuser, +) http.Handler { + var ( + decodeRequest = DecodeCreateRequest(mux, decoder) + encodeResponse = EncodeCreateResponse(encoder) + encodeError = goahttp.ErrorEncoder(encoder, formatter) + ) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) + ctx = context.WithValue(ctx, goa.MethodKey, "create") + ctx = context.WithValue(ctx, goa.ServiceKey, "interceptors") + payload, err := decodeRequest(r) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + res, err := endpoint(ctx, payload) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + if err := encodeResponse(ctx, w, res); err != nil { + errhandler(ctx, w, err) + } + }) +} + +// MountStreamHandler configures the mux to serve the "interceptors" service +// "stream" endpoint. +func MountStreamHandler(mux goahttp.Muxer, h http.Handler) { + f, ok := h.(http.HandlerFunc) + if !ok { + f = func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + } + } + mux.Handle("GET", "/records/{tenantID}/stream", f) +} + +// NewStreamHandler creates a HTTP handler which loads the HTTP request and +// calls the "interceptors" service "stream" endpoint. +func NewStreamHandler( + endpoint goa.Endpoint, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(ctx context.Context, err error) goahttp.Statuser, + upgrader goahttp.Upgrader, + configurer goahttp.ConnConfigureFunc, +) http.Handler { + var ( + decodeRequest = DecodeStreamRequest(mux, decoder) + encodeError = goahttp.ErrorEncoder(encoder, formatter) + ) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) + ctx = context.WithValue(ctx, goa.MethodKey, "stream") + ctx = context.WithValue(ctx, goa.ServiceKey, "interceptors") + payload, err := decodeRequest(r) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + var cancel context.CancelFunc + ctx, cancel = context.WithCancel(ctx) + v := &interceptors.StreamEndpointInput{ + Stream: &StreamServerStream{ + upgrader: upgrader, + configurer: configurer, + cancel: cancel, + w: w, + r: r, + }, + Payload: payload.(*interceptors.StreamPayload), + } + _, err = endpoint(ctx, v) + if err != nil { + if v.Stream.(*StreamServerStream).conn != nil { + // Response writer has been hijacked, do not encode the error + errhandler(ctx, w, err) + return + } + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + }) +} diff --git a/interceptors/gen/http/interceptors/server/types.go b/interceptors/gen/http/interceptors/server/types.go new file mode 100644 index 000000000..19db98000 --- /dev/null +++ b/interceptors/gen/http/interceptors/server/types.go @@ -0,0 +1,337 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors HTTP server types +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package server + +import ( + interceptors "goa.design/examples/interceptors/gen/interceptors" + goa "goa.design/goa/v3/pkg" +) + +// GetRequestBody is the type of the "interceptors" service "get" endpoint HTTP +// request body. +type GetRequestBody struct { + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *string `form:"traceID,omitempty" json:"traceID,omitempty" xml:"traceID,omitempty"` + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *string `form:"spanID,omitempty" json:"spanID,omitempty" xml:"spanID,omitempty"` +} + +// CreateRequestBody is the type of the "interceptors" service "create" +// endpoint HTTP request body. +type CreateRequestBody struct { + // Value to store in record + Value *string `form:"value,omitempty" json:"value,omitempty" xml:"value,omitempty"` + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *string `form:"traceID,omitempty" json:"traceID,omitempty" xml:"traceID,omitempty"` + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *string `form:"spanID,omitempty" json:"spanID,omitempty" xml:"spanID,omitempty"` +} + +// StreamStreamingBody is the type of the "interceptors" service "stream" +// endpoint HTTP request body. +type StreamStreamingBody struct { + // ID of the created record + ID *UUIDStreamingBody `form:"id,omitempty" json:"id,omitempty" xml:"id,omitempty"` + // Value of the record + Value *string `form:"value,omitempty" json:"value,omitempty" xml:"value,omitempty"` + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *UUIDStreamingBody `form:"traceID,omitempty" json:"traceID,omitempty" xml:"traceID,omitempty"` + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *UUIDStreamingBody `form:"spanID,omitempty" json:"spanID,omitempty" xml:"spanID,omitempty"` +} + +// GetResponseBody is the type of the "interceptors" service "get" endpoint +// HTTP response body. +type GetResponseBody struct { + // ID of the record + ID string `form:"id" json:"id" xml:"id"` + // Value of the record + Value string `form:"value" json:"value" xml:"value"` + // Tenant the record belongs to + Tenant string `form:"tenant" json:"tenant" xml:"tenant"` + // Response status code + Status int `form:"status" json:"status" xml:"status"` + // Timestamp when processed, written by the RequestAudit interceptor + ProcessedAt string `form:"processedAt" json:"processedAt" xml:"processedAt"` + // Processing duration in ms, written by the RequestAudit interceptor + Duration int `form:"duration" json:"duration" xml:"duration"` + // Time at which the record was cached, written by the Cache interceptor + CachedAt *string `form:"cachedAt,omitempty" json:"cachedAt,omitempty" xml:"cachedAt,omitempty"` + // Number of retry attempts made, written client-side by the Retry interceptor + RetryCount *int `form:"retryCount,omitempty" json:"retryCount,omitempty" xml:"retryCount,omitempty"` + // Total time spent retrying, written client-side by the Retry interceptor + RetryDuration *int `form:"retryDuration,omitempty" json:"retryDuration,omitempty" xml:"retryDuration,omitempty"` +} + +// CreateResponseBody is the type of the "interceptors" service "create" +// endpoint HTTP response body. +type CreateResponseBody struct { + // ID of the created record + ID string `form:"id" json:"id" xml:"id"` + // Value of the record + Value string `form:"value" json:"value" xml:"value"` + // Tenant the record belongs to + Tenant string `form:"tenant" json:"tenant" xml:"tenant"` + // Response status code + Status int `form:"status" json:"status" xml:"status"` + // Timestamp when processed + ProcessedAt string `form:"processedAt" json:"processedAt" xml:"processedAt"` + // Processing duration in ms + Duration int `form:"duration" json:"duration" xml:"duration"` + // Number of retry attempts made + RetryCount *int `form:"retryCount,omitempty" json:"retryCount,omitempty" xml:"retryCount,omitempty"` + // Total time spent retrying + RetryDuration *int `form:"retryDuration,omitempty" json:"retryDuration,omitempty" xml:"retryDuration,omitempty"` +} + +// StreamResponseBody is the type of the "interceptors" service "stream" +// endpoint HTTP response body. +type StreamResponseBody struct { + // ID of the created record + ID string `form:"id" json:"id" xml:"id"` + // Value of the record + Value string `form:"value" json:"value" xml:"value"` + // Tenant the record belongs to + Tenant string `form:"tenant" json:"tenant" xml:"tenant"` + // Response status code + Status int `form:"status" json:"status" xml:"status"` + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *string `form:"traceID,omitempty" json:"traceID,omitempty" xml:"traceID,omitempty"` + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *string `form:"spanID,omitempty" json:"spanID,omitempty" xml:"spanID,omitempty"` +} + +// GetNotFoundResponseBody is the type of the "interceptors" service "get" +// endpoint HTTP response body for the "NotFound" error. +type GetNotFoundResponseBody struct { + // Name is the name of this class of errors. + Name string `form:"name" json:"name" xml:"name"` + // ID is a unique identifier for this particular occurrence of the problem. + ID string `form:"id" json:"id" xml:"id"` + // Message is a human-readable explanation specific to this occurrence of the + // problem. + Message string `form:"message" json:"message" xml:"message"` + // Is the error temporary? + Temporary bool `form:"temporary" json:"temporary" xml:"temporary"` + // Is the error a timeout? + Timeout bool `form:"timeout" json:"timeout" xml:"timeout"` + // Is the error a server-side fault? + Fault bool `form:"fault" json:"fault" xml:"fault"` +} + +// GetUnavailableResponseBody is the type of the "interceptors" service "get" +// endpoint HTTP response body for the "Unavailable" error. +type GetUnavailableResponseBody struct { + // Name is the name of this class of errors. + Name string `form:"name" json:"name" xml:"name"` + // ID is a unique identifier for this particular occurrence of the problem. + ID string `form:"id" json:"id" xml:"id"` + // Message is a human-readable explanation specific to this occurrence of the + // problem. + Message string `form:"message" json:"message" xml:"message"` + // Is the error temporary? + Temporary bool `form:"temporary" json:"temporary" xml:"temporary"` + // Is the error a timeout? + Timeout bool `form:"timeout" json:"timeout" xml:"timeout"` + // Is the error a server-side fault? + Fault bool `form:"fault" json:"fault" xml:"fault"` +} + +// UUIDStreamingBody is used to define fields on request body types. +type UUIDStreamingBody string + +// NewGetResponseBody builds the HTTP response body from the result of the +// "get" endpoint of the "interceptors" service. +func NewGetResponseBody(res *interceptors.GetResult) *GetResponseBody { + body := &GetResponseBody{ + ID: string(res.ID), + Value: res.Value, + Tenant: res.Tenant, + Status: res.Status, + ProcessedAt: res.ProcessedAt, + Duration: res.Duration, + CachedAt: res.CachedAt, + RetryCount: res.RetryCount, + RetryDuration: res.RetryDuration, + } + return body +} + +// NewCreateResponseBody builds the HTTP response body from the result of the +// "create" endpoint of the "interceptors" service. +func NewCreateResponseBody(res *interceptors.CreateResult) *CreateResponseBody { + body := &CreateResponseBody{ + ID: string(res.ID), + Value: res.Value, + Tenant: res.Tenant, + Status: res.Status, + ProcessedAt: res.ProcessedAt, + Duration: res.Duration, + RetryCount: res.RetryCount, + RetryDuration: res.RetryDuration, + } + return body +} + +// NewStreamResponseBody builds the HTTP response body from the result of the +// "stream" endpoint of the "interceptors" service. +func NewStreamResponseBody(res *interceptors.StreamResult) *StreamResponseBody { + body := &StreamResponseBody{ + ID: string(res.ID), + Value: res.Value, + Tenant: res.Tenant, + Status: res.Status, + } + if res.TraceID != nil { + traceID := string(*res.TraceID) + body.TraceID = &traceID + } + if res.SpanID != nil { + spanID := string(*res.SpanID) + body.SpanID = &spanID + } + return body +} + +// NewGetNotFoundResponseBody builds the HTTP response body from the result of +// the "get" endpoint of the "interceptors" service. +func NewGetNotFoundResponseBody(res *goa.ServiceError) *GetNotFoundResponseBody { + body := &GetNotFoundResponseBody{ + Name: res.Name, + ID: res.ID, + Message: res.Message, + Temporary: res.Temporary, + Timeout: res.Timeout, + Fault: res.Fault, + } + return body +} + +// NewGetUnavailableResponseBody builds the HTTP response body from the result +// of the "get" endpoint of the "interceptors" service. +func NewGetUnavailableResponseBody(res *goa.ServiceError) *GetUnavailableResponseBody { + body := &GetUnavailableResponseBody{ + Name: res.Name, + ID: res.ID, + Message: res.Message, + Temporary: res.Temporary, + Timeout: res.Timeout, + Fault: res.Fault, + } + return body +} + +// NewGetPayload builds a interceptors service get endpoint payload. +func NewGetPayload(body *GetRequestBody, tenantID string, recordID string, auth string) *interceptors.GetPayload { + v := &interceptors.GetPayload{} + if body.TraceID != nil { + traceID := interceptors.UUID(*body.TraceID) + v.TraceID = &traceID + } + if body.SpanID != nil { + spanID := interceptors.UUID(*body.SpanID) + v.SpanID = &spanID + } + v.TenantID = interceptors.UUID(tenantID) + v.RecordID = interceptors.UUID(recordID) + v.Auth = auth + + return v +} + +// NewCreatePayload builds a interceptors service create endpoint payload. +func NewCreatePayload(body *CreateRequestBody, tenantID string, auth string) *interceptors.CreatePayload { + v := &interceptors.CreatePayload{ + Value: *body.Value, + } + if body.TraceID != nil { + traceID := interceptors.UUID(*body.TraceID) + v.TraceID = &traceID + } + if body.SpanID != nil { + spanID := interceptors.UUID(*body.SpanID) + v.SpanID = &spanID + } + v.TenantID = interceptors.UUID(tenantID) + v.Auth = auth + + return v +} + +// NewStreamPayload builds a interceptors service stream endpoint payload. +func NewStreamPayload(tenantID string, auth string) *interceptors.StreamPayload { + v := &interceptors.StreamPayload{} + v.TenantID = interceptors.UUID(tenantID) + v.Auth = auth + + return v +} + +// NewStreamStreamingBody builds a interceptors service stream endpoint payload. +func NewStreamStreamingBody(body *StreamStreamingBody) *interceptors.StreamStreamingPayload { + v := &interceptors.StreamStreamingPayload{ + ID: interceptors.UUID(*body.ID), + Value: *body.Value, + } + if body.TraceID != nil { + traceID := interceptors.UUID(*body.TraceID) + v.TraceID = &traceID + } + if body.SpanID != nil { + spanID := interceptors.UUID(*body.SpanID) + v.SpanID = &spanID + } + + return v +} + +// ValidateGetRequestBody runs the validations defined on GetRequestBody +func ValidateGetRequestBody(body *GetRequestBody) (err error) { + if body.TraceID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.traceID", *body.TraceID, goa.FormatUUID)) + } + if body.SpanID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.spanID", *body.SpanID, goa.FormatUUID)) + } + return +} + +// ValidateCreateRequestBody runs the validations defined on CreateRequestBody +func ValidateCreateRequestBody(body *CreateRequestBody) (err error) { + if body.Value == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("value", "body")) + } + if body.TraceID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.traceID", *body.TraceID, goa.FormatUUID)) + } + if body.SpanID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.spanID", *body.SpanID, goa.FormatUUID)) + } + return +} + +// ValidateStreamStreamingBody runs the validations defined on +// StreamStreamingBody +func ValidateStreamStreamingBody(body *StreamStreamingBody) (err error) { + if body.ID == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("id", "body")) + } + if body.Value == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("value", "body")) + } + if body.ID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.id", string(*body.ID), goa.FormatUUID)) + } + if body.TraceID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.traceID", string(*body.TraceID), goa.FormatUUID)) + } + if body.SpanID != nil { + err = goa.MergeErrors(err, goa.ValidateFormat("body.spanID", string(*body.SpanID), goa.FormatUUID)) + } + return +} diff --git a/interceptors/gen/http/interceptors/server/websocket.go b/interceptors/gen/http/interceptors/server/websocket.go new file mode 100644 index 000000000..643a09f56 --- /dev/null +++ b/interceptors/gen/http/interceptors/server/websocket.go @@ -0,0 +1,145 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors WebSocket server streaming +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package server + +import ( + "context" + "io" + "net/http" + "sync" + "time" + + "github.com/gorilla/websocket" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goahttp "goa.design/goa/v3/http" +) + +// ConnConfigurer holds the websocket connection configurer functions for the +// streaming endpoints in "interceptors" service. +type ConnConfigurer struct { + StreamFn goahttp.ConnConfigureFunc +} + +// StreamServerStream implements the interceptors.StreamServerStream interface. +type StreamServerStream struct { + once sync.Once + // upgrader is the websocket connection upgrader. + upgrader goahttp.Upgrader + // configurer is the websocket connection configurer. + configurer goahttp.ConnConfigureFunc + // cancel is the context cancellation function which cancels the request + // context when invoked. + cancel context.CancelFunc + // w is the HTTP response writer used in upgrading the connection. + w http.ResponseWriter + // r is the HTTP request. + r *http.Request + // conn is the underlying websocket connection. + conn *websocket.Conn +} + +// NewConnConfigurer initializes the websocket connection configurer function +// with fn for all the streaming endpoints in "interceptors" service. +func NewConnConfigurer(fn goahttp.ConnConfigureFunc) *ConnConfigurer { + return &ConnConfigurer{ + StreamFn: fn, + } +} + +// Send streams instances of "interceptors.StreamResult" to the "stream" +// endpoint websocket connection. +func (s *StreamServerStream) Send(v *interceptors.StreamResult) error { + var err error + // Upgrade the HTTP connection to a websocket connection only once. Connection + // upgrade is done here so that authorization logic in the endpoint is executed + // before calling the actual service method which may call Send(). + s.once.Do(func() { + var conn *websocket.Conn + conn, err = s.upgrader.Upgrade(s.w, s.r, nil) + if err != nil { + return + } + if s.configurer != nil { + conn = s.configurer(conn, s.cancel) + } + s.conn = conn + }) + if err != nil { + return err + } + res := v + body := NewStreamResponseBody(res) + return s.conn.WriteJSON(body) +} + +// SendWithContext streams instances of "interceptors.StreamResult" to the +// "stream" endpoint websocket connection with context. +func (s *StreamServerStream) SendWithContext(ctx context.Context, v *interceptors.StreamResult) error { + return s.Send(v) +} + +// Recv reads instances of "interceptors.StreamStreamingPayload" from the +// "stream" endpoint websocket connection. +func (s *StreamServerStream) Recv() (*interceptors.StreamStreamingPayload, error) { + var ( + rv *interceptors.StreamStreamingPayload + msg *StreamStreamingBody + err error + ) + // Upgrade the HTTP connection to a websocket connection only once. Connection + // upgrade is done here so that authorization logic in the endpoint is executed + // before calling the actual service method which may call Recv(). + s.once.Do(func() { + var conn *websocket.Conn + conn, err = s.upgrader.Upgrade(s.w, s.r, nil) + if err != nil { + return + } + if s.configurer != nil { + conn = s.configurer(conn, s.cancel) + } + s.conn = conn + }) + if err != nil { + return rv, err + } + if err = s.conn.ReadJSON(&msg); err != nil { + return rv, err + } + if msg == nil { + return rv, io.EOF + } + body := *msg + err = ValidateStreamStreamingBody(&body) + if err != nil { + return rv, err + } + return NewStreamStreamingBody(msg), nil +} + +// RecvWithContext reads instances of "interceptors.StreamStreamingPayload" +// from the "stream" endpoint websocket connection with context. +func (s *StreamServerStream) RecvWithContext(ctx context.Context) (*interceptors.StreamStreamingPayload, error) { + return s.Recv() +} + +// Close closes the "stream" endpoint websocket connection. +func (s *StreamServerStream) Close() error { + var err error + if s.conn == nil { + return nil + } + if err = s.conn.WriteControl( + websocket.CloseMessage, + websocket.FormatCloseMessage(websocket.CloseNormalClosure, "server closing connection"), + time.Now().Add(time.Second), + ); err != nil { + return err + } + return s.conn.Close() +} diff --git a/interceptors/gen/http/openapi.json b/interceptors/gen/http/openapi.json new file mode 100644 index 000000000..074f09f5a --- /dev/null +++ b/interceptors/gen/http/openapi.json @@ -0,0 +1 @@ +{"swagger":"2.0","info":{"title":"","version":"0.0.1"},"host":"localhost:80","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/records/{tenantID}":{"post":{"tags":["interceptors"],"summary":"create interceptors","description":"Create a new record with all interceptors in action","operationId":"interceptors#create","parameters":[{"name":"tenantID","in":"path","description":"Valid UUID representation as per RFC 4122","required":true,"type":"string"},{"name":"Authorization","in":"header","description":"JWT auth token","required":true,"type":"string"},{"name":"CreateRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/InterceptorsCreateRequestBody","required":["value"]}}],"responses":{"201":{"description":"Created response.","schema":{"$ref":"#/definitions/InterceptorsCreateResponseBody","required":["id","value","tenant","status","processedAt","duration"]}}},"schemes":["http"]}},"/records/{tenantID}/stream":{"get":{"tags":["interceptors"],"summary":"stream interceptors","description":"Stream records","operationId":"interceptors#stream","parameters":[{"name":"tenantID","in":"path","description":"Valid UUID representation as per RFC 4122","required":true,"type":"string"},{"name":"Authorization","in":"header","description":"JWT auth token","required":true,"type":"string"}],"responses":{"101":{"description":"Switching Protocols response.","schema":{"$ref":"#/definitions/InterceptorsStreamResponseBody","required":["id","value","tenant","status"]}}},"schemes":["ws"]}},"/records/{tenantID}/{recordID}":{"get":{"tags":["interceptors"],"summary":"get interceptors","description":"Get retrieves a record by ID with all interceptors in action","operationId":"interceptors#get","parameters":[{"name":"tenantID","in":"path","description":"Valid UUID representation as per RFC 4122","required":true,"type":"string"},{"name":"recordID","in":"path","description":"Valid UUID representation as per RFC 4122","required":true,"type":"string"},{"name":"Authorization","in":"header","description":"JWT auth token","required":true,"type":"string"},{"name":"GetRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/InterceptorsGetRequestBody"}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/InterceptorsGetResponseBody","required":["id","value","tenant","status","processedAt","duration"]}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/InterceptorsGetNotFoundResponseBody"}},"503":{"description":"Service Unavailable response.","schema":{"$ref":"#/definitions/InterceptorsGetUnavailableResponseBody"}}},"schemes":["http"]}}},"definitions":{"InterceptorsCreateRequestBody":{"title":"InterceptorsCreateRequestBody","type":"object","properties":{"spanID":{"type":"string","description":"Unique span ID for request, initialized by the TraceRequest interceptor","example":"29e580bf-8ed1-4f19-b60c-352214b806df","format":"uuid"},"traceID":{"type":"string","description":"Unique trace ID for request, initialized by the TraceRequest interceptor","example":"0c85e724-f296-4161-92e9-c90de96436d0","format":"uuid"},"value":{"type":"string","description":"Value to store in record","example":"Ut quia reiciendis voluptatum quia."}},"example":{"spanID":"9b6b1c4b-3b86-41e0-b2d3-467713766ff4","traceID":"f842a33c-5087-4249-869b-41f44e253343","value":"Placeat nesciunt voluptas rerum consequatur ut at."},"required":["value"]},"InterceptorsCreateResponseBody":{"title":"InterceptorsCreateResponseBody","type":"object","properties":{"duration":{"type":"integer","description":"Processing duration in ms","example":6712797237524310620,"format":"int64"},"id":{"type":"string","description":"ID of the created record","example":"1505eca3-abf9-47be-a051-3cc1ac869d6e","format":"uuid"},"processedAt":{"type":"string","description":"Timestamp when processed","example":"Ducimus doloribus sit porro."},"retryCount":{"type":"integer","description":"Number of retry attempts made","example":1282775257137073598,"format":"int64"},"retryDuration":{"type":"integer","description":"Total time spent retrying","example":1655803061842165866,"format":"int64"},"status":{"type":"integer","description":"Response status code","example":271401219907671088,"format":"int64"},"tenant":{"type":"string","description":"Tenant the record belongs to","example":"Molestiae praesentium corporis."},"value":{"type":"string","description":"Value of the record","example":"Vero voluptas consectetur odio praesentium nisi dignissimos."}},"example":{"duration":8335746665792469984,"id":"bc56c1bb-6f8d-4c3e-a153-8475b20e1d69","processedAt":"Quia voluptate quam ut quo.","retryCount":8188308883955071545,"retryDuration":341724810159970805,"status":1640505517961949417,"tenant":"Qui quia voluptatem necessitatibus doloribus et.","value":"Minima et debitis similique."},"required":["id","value","tenant","status","processedAt","duration"]},"InterceptorsGetNotFoundResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"Record not found (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":false,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"InterceptorsGetRequestBody":{"title":"InterceptorsGetRequestBody","type":"object","properties":{"spanID":{"type":"string","description":"Unique span ID for request, initialized by the TraceRequest interceptor","example":"1959bb59-5ab1-4415-8885-728ac60cc1f3","format":"uuid"},"traceID":{"type":"string","description":"Unique trace ID for request, initialized by the TraceRequest interceptor","example":"57a37f50-ed5d-4319-b8ed-162e5bd3e1ef","format":"uuid"}},"example":{"spanID":"5b2f4108-5922-4bd5-9a48-3d82e22ecb02","traceID":"d81b1710-f6f4-43de-889b-4c31639c6015"}},"InterceptorsGetResponseBody":{"title":"InterceptorsGetResponseBody","type":"object","properties":{"cachedAt":{"type":"string","description":"Time at which the record was cached, written by the Cache interceptor","example":"Molestiae ipsam."},"duration":{"type":"integer","description":"Processing duration in ms, written by the RequestAudit interceptor","example":4041388843296110658,"format":"int64"},"id":{"type":"string","description":"ID of the record","example":"cb87528f-0478-46e3-adff-bab6a8d3760a","format":"uuid"},"processedAt":{"type":"string","description":"Timestamp when processed, written by the RequestAudit interceptor","example":"Sed perspiciatis corporis."},"retryCount":{"type":"integer","description":"Number of retry attempts made, written client-side by the Retry interceptor","example":6608198285387567718,"format":"int64"},"retryDuration":{"type":"integer","description":"Total time spent retrying, written client-side by the Retry interceptor","example":4348821142730194322,"format":"int64"},"status":{"type":"integer","description":"Response status code","example":7548420244555805334,"format":"int64"},"tenant":{"type":"string","description":"Tenant the record belongs to","example":"Repellat aut."},"value":{"type":"string","description":"Value of the record","example":"Non doloribus modi autem sed sequi."}},"example":{"cachedAt":"Repellendus sit corporis unde consectetur.","duration":5892548184232957614,"id":"86e2de32-5a58-47de-bdbd-1b4255a58bba","processedAt":"Doloremque qui.","retryCount":6513275449747503812,"retryDuration":4533506119215742706,"status":7862620419154776647,"tenant":"Eum qui vitae omnis.","value":"Rerum dicta."},"required":["id","value","tenant","status","processedAt","duration"]},"InterceptorsGetUnavailableResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"Temporary error (default view)","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":false,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"InterceptorsStreamResponseBody":{"title":"InterceptorsStreamResponseBody","type":"object","properties":{"id":{"type":"string","description":"ID of the created record","example":"f9ed7d90-c040-4a21-9571-c469a1f89fbd","format":"uuid"},"spanID":{"type":"string","description":"Unique span ID for request, initialized by the TraceRequest interceptor","example":"03c7a5df-7be0-42b6-ac11-2c142758dfa4","format":"uuid"},"status":{"type":"integer","description":"Response status code","example":8504919717171234071,"format":"int64"},"tenant":{"type":"string","description":"Tenant the record belongs to","example":"Eaque a a."},"traceID":{"type":"string","description":"Unique trace ID for request, initialized by the TraceRequest interceptor","example":"af654500-9597-40a5-8ddb-9786bfe49a5e","format":"uuid"},"value":{"type":"string","description":"Value of the record","example":"Pariatur sunt aut est dolor recusandae voluptatibus."}},"example":{"id":"e5f5bccf-86d5-4888-a697-55f09213a85e","spanID":"00a30ea4-7d32-4464-b1cd-8b6127ad20a5","status":2203681731170129552,"tenant":"Aliquam quo et aperiam ut voluptatum.","traceID":"d61c9300-89d0-4ba0-bb1a-040200e68d85","value":"In at magnam."},"required":["id","value","tenant","status"]}}} \ No newline at end of file diff --git a/interceptors/gen/http/openapi.yaml b/interceptors/gen/http/openapi.yaml new file mode 100644 index 000000000..d3c4234d7 --- /dev/null +++ b/interceptors/gen/http/openapi.yaml @@ -0,0 +1,424 @@ +swagger: "2.0" +info: + title: "" + version: 0.0.1 +host: localhost:80 +consumes: + - application/json + - application/xml + - application/gob +produces: + - application/json + - application/xml + - application/gob +paths: + /records/{tenantID}: + post: + tags: + - interceptors + summary: create interceptors + description: Create a new record with all interceptors in action + operationId: interceptors#create + parameters: + - name: tenantID + in: path + description: Valid UUID representation as per RFC 4122 + required: true + type: string + - name: Authorization + in: header + description: JWT auth token + required: true + type: string + - name: CreateRequestBody + in: body + required: true + schema: + $ref: '#/definitions/InterceptorsCreateRequestBody' + required: + - value + responses: + "201": + description: Created response. + schema: + $ref: '#/definitions/InterceptorsCreateResponseBody' + required: + - id + - value + - tenant + - status + - processedAt + - duration + schemes: + - http + /records/{tenantID}/{recordID}: + get: + tags: + - interceptors + summary: get interceptors + description: Get retrieves a record by ID with all interceptors in action + operationId: interceptors#get + parameters: + - name: tenantID + in: path + description: Valid UUID representation as per RFC 4122 + required: true + type: string + - name: recordID + in: path + description: Valid UUID representation as per RFC 4122 + required: true + type: string + - name: Authorization + in: header + description: JWT auth token + required: true + type: string + - name: GetRequestBody + in: body + required: true + schema: + $ref: '#/definitions/InterceptorsGetRequestBody' + responses: + "200": + description: OK response. + schema: + $ref: '#/definitions/InterceptorsGetResponseBody' + required: + - id + - value + - tenant + - status + - processedAt + - duration + "404": + description: Not Found response. + schema: + $ref: '#/definitions/InterceptorsGetNotFoundResponseBody' + "503": + description: Service Unavailable response. + schema: + $ref: '#/definitions/InterceptorsGetUnavailableResponseBody' + schemes: + - http + /records/{tenantID}/stream: + get: + tags: + - interceptors + summary: stream interceptors + description: Stream records + operationId: interceptors#stream + parameters: + - name: tenantID + in: path + description: Valid UUID representation as per RFC 4122 + required: true + type: string + - name: Authorization + in: header + description: JWT auth token + required: true + type: string + responses: + "101": + description: Switching Protocols response. + schema: + $ref: '#/definitions/InterceptorsStreamResponseBody' + required: + - id + - value + - tenant + - status + schemes: + - ws +definitions: + InterceptorsCreateRequestBody: + title: InterceptorsCreateRequestBody + type: object + properties: + spanID: + type: string + description: Unique span ID for request, initialized by the TraceRequest interceptor + example: 29e580bf-8ed1-4f19-b60c-352214b806df + format: uuid + traceID: + type: string + description: Unique trace ID for request, initialized by the TraceRequest interceptor + example: 0c85e724-f296-4161-92e9-c90de96436d0 + format: uuid + value: + type: string + description: Value to store in record + example: Ut quia reiciendis voluptatum quia. + example: + spanID: 9b6b1c4b-3b86-41e0-b2d3-467713766ff4 + traceID: f842a33c-5087-4249-869b-41f44e253343 + value: Placeat nesciunt voluptas rerum consequatur ut at. + required: + - value + InterceptorsCreateResponseBody: + title: InterceptorsCreateResponseBody + type: object + properties: + duration: + type: integer + description: Processing duration in ms + example: 6712797237524310620 + format: int64 + id: + type: string + description: ID of the created record + example: 1505eca3-abf9-47be-a051-3cc1ac869d6e + format: uuid + processedAt: + type: string + description: Timestamp when processed + example: Ducimus doloribus sit porro. + retryCount: + type: integer + description: Number of retry attempts made + example: 1282775257137073598 + format: int64 + retryDuration: + type: integer + description: Total time spent retrying + example: 1655803061842165866 + format: int64 + status: + type: integer + description: Response status code + example: 271401219907671088 + format: int64 + tenant: + type: string + description: Tenant the record belongs to + example: Molestiae praesentium corporis. + value: + type: string + description: Value of the record + example: Vero voluptas consectetur odio praesentium nisi dignissimos. + example: + duration: 8335746665792469984 + id: bc56c1bb-6f8d-4c3e-a153-8475b20e1d69 + processedAt: Quia voluptate quam ut quo. + retryCount: 8188308883955071545 + retryDuration: 341724810159970805 + status: 1640505517961949417 + tenant: Qui quia voluptatem necessitatibus doloribus et. + value: Minima et debitis similique. + required: + - id + - value + - tenant + - status + - processedAt + - duration + InterceptorsGetNotFoundResponseBody: + title: 'Mediatype identifier: application/vnd.goa.error; view=default' + type: object + properties: + fault: + type: boolean + description: Is the error a server-side fault? + example: true + id: + type: string + description: ID is a unique identifier for this particular occurrence of the problem. + example: 123abc + message: + type: string + description: Message is a human-readable explanation specific to this occurrence of the problem. + example: parameter 'p' must be an integer + name: + type: string + description: Name is the name of this class of errors. + example: bad_request + temporary: + type: boolean + description: Is the error temporary? + example: true + timeout: + type: boolean + description: Is the error a timeout? + example: true + description: Record not found (default view) + example: + fault: false + id: 123abc + message: parameter 'p' must be an integer + name: bad_request + temporary: false + timeout: false + required: + - name + - id + - message + - temporary + - timeout + - fault + InterceptorsGetRequestBody: + title: InterceptorsGetRequestBody + type: object + properties: + spanID: + type: string + description: Unique span ID for request, initialized by the TraceRequest interceptor + example: 1959bb59-5ab1-4415-8885-728ac60cc1f3 + format: uuid + traceID: + type: string + description: Unique trace ID for request, initialized by the TraceRequest interceptor + example: 57a37f50-ed5d-4319-b8ed-162e5bd3e1ef + format: uuid + example: + spanID: 5b2f4108-5922-4bd5-9a48-3d82e22ecb02 + traceID: d81b1710-f6f4-43de-889b-4c31639c6015 + InterceptorsGetResponseBody: + title: InterceptorsGetResponseBody + type: object + properties: + cachedAt: + type: string + description: Time at which the record was cached, written by the Cache interceptor + example: Molestiae ipsam. + duration: + type: integer + description: Processing duration in ms, written by the RequestAudit interceptor + example: 4041388843296110658 + format: int64 + id: + type: string + description: ID of the record + example: cb87528f-0478-46e3-adff-bab6a8d3760a + format: uuid + processedAt: + type: string + description: Timestamp when processed, written by the RequestAudit interceptor + example: Sed perspiciatis corporis. + retryCount: + type: integer + description: Number of retry attempts made, written client-side by the Retry interceptor + example: 6608198285387567718 + format: int64 + retryDuration: + type: integer + description: Total time spent retrying, written client-side by the Retry interceptor + example: 4348821142730194322 + format: int64 + status: + type: integer + description: Response status code + example: 7548420244555805334 + format: int64 + tenant: + type: string + description: Tenant the record belongs to + example: Repellat aut. + value: + type: string + description: Value of the record + example: Non doloribus modi autem sed sequi. + example: + cachedAt: Repellendus sit corporis unde consectetur. + duration: 5892548184232957614 + id: 86e2de32-5a58-47de-bdbd-1b4255a58bba + processedAt: Doloremque qui. + retryCount: 6513275449747503812 + retryDuration: 4533506119215742706 + status: 7862620419154776647 + tenant: Eum qui vitae omnis. + value: Rerum dicta. + required: + - id + - value + - tenant + - status + - processedAt + - duration + InterceptorsGetUnavailableResponseBody: + title: 'Mediatype identifier: application/vnd.goa.error; view=default' + type: object + properties: + fault: + type: boolean + description: Is the error a server-side fault? + example: false + id: + type: string + description: ID is a unique identifier for this particular occurrence of the problem. + example: 123abc + message: + type: string + description: Message is a human-readable explanation specific to this occurrence of the problem. + example: parameter 'p' must be an integer + name: + type: string + description: Name is the name of this class of errors. + example: bad_request + temporary: + type: boolean + description: Is the error temporary? + example: false + timeout: + type: boolean + description: Is the error a timeout? + example: false + description: Temporary error (default view) + example: + fault: true + id: 123abc + message: parameter 'p' must be an integer + name: bad_request + temporary: false + timeout: false + required: + - name + - id + - message + - temporary + - timeout + - fault + InterceptorsStreamResponseBody: + title: InterceptorsStreamResponseBody + type: object + properties: + id: + type: string + description: ID of the created record + example: f9ed7d90-c040-4a21-9571-c469a1f89fbd + format: uuid + spanID: + type: string + description: Unique span ID for request, initialized by the TraceRequest interceptor + example: 03c7a5df-7be0-42b6-ac11-2c142758dfa4 + format: uuid + status: + type: integer + description: Response status code + example: 8504919717171234071 + format: int64 + tenant: + type: string + description: Tenant the record belongs to + example: Eaque a a. + traceID: + type: string + description: Unique trace ID for request, initialized by the TraceRequest interceptor + example: af654500-9597-40a5-8ddb-9786bfe49a5e + format: uuid + value: + type: string + description: Value of the record + example: Pariatur sunt aut est dolor recusandae voluptatibus. + example: + id: e5f5bccf-86d5-4888-a697-55f09213a85e + spanID: 00a30ea4-7d32-4464-b1cd-8b6127ad20a5 + status: 2203681731170129552 + tenant: Aliquam quo et aperiam ut voluptatum. + traceID: d61c9300-89d0-4ba0-bb1a-040200e68d85 + value: In at magnam. + required: + - id + - value + - tenant + - status diff --git a/interceptors/gen/http/openapi3.json b/interceptors/gen/http/openapi3.json new file mode 100644 index 000000000..9c3f21122 --- /dev/null +++ b/interceptors/gen/http/openapi3.json @@ -0,0 +1 @@ +{"openapi":"3.0.3","info":{"title":"Goa API","version":"0.0.1"},"servers":[{"url":"http://localhost:80","description":"Default server for interceptors"}],"paths":{"/records/{tenantID}":{"post":{"tags":["interceptors"],"summary":"create interceptors","description":"Create a new record with all interceptors in action","operationId":"interceptors#create","parameters":[{"name":"tenantID","in":"path","description":"Tenant ID for the request","required":true,"schema":{"type":"string","description":"Valid UUID representation as per RFC 4122","example":"d0f3a1f4-6b11-4294-b59d-f9e34b9b6e93","format":"uuid"},"example":"Aliquid necessitatibus asperiores iure."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRequestBody"},"example":{"spanID":"60119d23-b695-492d-b0fb-4c5195591902","traceID":"d94bb031-1e29-4544-a640-ae17323e1a90","value":"Rerum nesciunt suscipit est quo."}}}},"responses":{"201":{"description":"Created response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateResponseBody"},"example":{"duration":3684023309181312870,"id":"512fafca-7f09-4b06-863a-cecc41a8f6a8","processedAt":"Ea non vitae sit iure.","retryCount":7486950083313293759,"retryDuration":3930787756291036119,"status":5202814868737196904,"tenant":"Rerum sed ad vel esse.","value":"Repudiandae quia."}}}}}}},"/records/{tenantID}/stream":{"get":{"tags":["interceptors"],"summary":"stream interceptors","description":"Stream records","operationId":"interceptors#stream","parameters":[{"name":"tenantID","in":"path","description":"Tenant ID for the request","required":true,"schema":{"type":"string","description":"Valid UUID representation as per RFC 4122","example":"eddf9d7c-5830-4633-91cd-c102156bbdb2","format":"uuid"},"example":"Aliquid necessitatibus asperiores iure."}],"responses":{"101":{"description":"Switching Protocols response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreamResponseBody"},"example":{"id":"a726b78a-0abe-43b3-879c-eaf39b95345a","spanID":"ed81916d-f3bd-44c6-b138-a855bf2c7f12","status":4913202279654507592,"tenant":"Sunt aut qui voluptatem modi eveniet sit.","traceID":"9bd267da-8bf9-4e43-88e9-2d035c6b0951","value":"Optio consequatur ipsam."}}}}}}},"/records/{tenantID}/{recordID}":{"get":{"tags":["interceptors"],"summary":"get interceptors","description":"Get retrieves a record by ID with all interceptors in action","operationId":"interceptors#get","parameters":[{"name":"tenantID","in":"path","description":"Tenant ID for the request","required":true,"schema":{"type":"string","description":"Valid UUID representation as per RFC 4122","example":"897674da-3904-428f-b934-c43798999d7b","format":"uuid"},"example":"Aliquid necessitatibus asperiores iure."},{"name":"recordID","in":"path","description":"ID of the record to retrieve","required":true,"schema":{"type":"string","description":"Valid UUID representation as per RFC 4122","example":"d31df5e3-01de-43b4-acbe-bfc980f9345e","format":"uuid"},"example":"Aliquid necessitatibus asperiores iure."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetRequestBody"},"example":{"spanID":"150d7874-6995-4405-9422-192a638fe1a3","traceID":"f03bb3ab-2f3b-4961-8396-30a04e467ad7"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetResponseBody"},"example":{"cachedAt":"Enim architecto vel.","duration":2688045444648128819,"id":"3189318c-89b1-4a0f-8768-a13a5369660e","processedAt":"Pariatur nobis architecto sint consequatur et unde.","retryCount":949445419645481428,"retryDuration":4472582507154208325,"status":54933130937179257,"tenant":"Quos numquam aut minima.","value":"Sint necessitatibus id ut minus quia quia."}}}},"404":{"description":"NotFound: Record not found","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Unavailable: Temporary error","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"CreateRequestBody":{"type":"object","properties":{"spanID":{"type":"string","description":"Unique span ID for request, initialized by the TraceRequest interceptor","example":"dde4c149-b4bd-4097-8621-30006c86e8e0","format":"uuid"},"traceID":{"type":"string","description":"Unique trace ID for request, initialized by the TraceRequest interceptor","example":"bf7bbcc5-1e3a-4f80-b27c-f20dc46dd59d","format":"uuid"},"value":{"type":"string","description":"Value to store in record","example":"Iure velit rerum natus."}},"example":{"spanID":"001ef099-6900-4b03-82c4-30247338a067","traceID":"b0c40fb5-b995-4019-b8b8-9653de84b789","value":"Eos non aut omnis et."},"required":["value"]},"CreateResponseBody":{"type":"object","properties":{"duration":{"type":"integer","description":"Processing duration in ms","example":2422317059159953466,"format":"int64"},"id":{"type":"string","description":"ID of the created record","example":"6348968a-0415-4470-8805-796539fcae73","format":"uuid"},"processedAt":{"type":"string","description":"Timestamp when processed","example":"Velit reprehenderit."},"retryCount":{"type":"integer","description":"Number of retry attempts made","example":9195687640623575973,"format":"int64"},"retryDuration":{"type":"integer","description":"Total time spent retrying","example":8864959330259880556,"format":"int64"},"status":{"type":"integer","description":"Response status code","example":380020668886814383,"format":"int64"},"tenant":{"type":"string","description":"Tenant the record belongs to","example":"Ea pariatur molestias nemo deserunt sit."},"value":{"type":"string","description":"Value of the record","example":"Facere est suscipit quo."}},"example":{"duration":1790111840231600946,"id":"c93b19d4-11ac-4651-a327-5a2f00464fb0","processedAt":"Quis dicta.","retryCount":7805510653290713336,"retryDuration":8684061465502470561,"status":8372104706994352588,"tenant":"Neque vel.","value":"Nemo incidunt."},"required":["id","value","tenant","status","processedAt","duration"]},"Error":{"type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"Record not found","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":false,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"GetRequestBody":{"type":"object","properties":{"spanID":{"type":"string","description":"Unique span ID for request, initialized by the TraceRequest interceptor","example":"c17986d0-69c6-458b-aaca-41fb6a9e2aaf","format":"uuid"},"traceID":{"type":"string","description":"Unique trace ID for request, initialized by the TraceRequest interceptor","example":"6cc200ba-005e-4e4e-90cf-edab8d0cd369","format":"uuid"}},"example":{"spanID":"3774ed03-eceb-4016-ab1e-afaca435e4fa","traceID":"9a0d22da-e117-41a2-bfb4-515c613f2ae7"}},"GetResponseBody":{"type":"object","properties":{"cachedAt":{"type":"string","description":"Time at which the record was cached, written by the Cache interceptor","example":"Et quas iste quas explicabo."},"duration":{"type":"integer","description":"Processing duration in ms, written by the RequestAudit interceptor","example":4234899879073199693,"format":"int64"},"id":{"type":"string","description":"ID of the record","example":"feb30c06-2b2b-463f-9785-3a10018763c7","format":"uuid"},"processedAt":{"type":"string","description":"Timestamp when processed, written by the RequestAudit interceptor","example":"Et quidem eos laboriosam velit provident."},"retryCount":{"type":"integer","description":"Number of retry attempts made, written client-side by the Retry interceptor","example":8984616366653758809,"format":"int64"},"retryDuration":{"type":"integer","description":"Total time spent retrying, written client-side by the Retry interceptor","example":783576862198586200,"format":"int64"},"status":{"type":"integer","description":"Response status code","example":943917848840806908,"format":"int64"},"tenant":{"type":"string","description":"Tenant the record belongs to","example":"Corporis dolorem sit."},"value":{"type":"string","description":"Value of the record","example":"Vitae molestiae vitae."}},"example":{"cachedAt":"Occaecati aut asperiores.","duration":8398049820790322035,"id":"57063575-9e52-4a61-93ad-3bbd7d73728d","processedAt":"Quo voluptatem.","retryCount":727626558249177223,"retryDuration":1482120365798449866,"status":805191965083195454,"tenant":"Voluptas et quisquam enim.","value":"Quas nihil numquam ut."},"required":["id","value","tenant","status","processedAt","duration"]},"StreamResponseBody":{"type":"object","properties":{"id":{"type":"string","description":"ID of the created record","example":"4dfe326d-ad2e-4131-a841-07ed3b67159c","format":"uuid"},"spanID":{"type":"string","description":"Unique span ID for request, initialized by the TraceRequest interceptor","example":"6666e8e6-81b7-4ee1-be48-b7cc0f843b81","format":"uuid"},"status":{"type":"integer","description":"Response status code","example":7575731313406397237,"format":"int64"},"tenant":{"type":"string","description":"Tenant the record belongs to","example":"Aut velit laborum ut."},"traceID":{"type":"string","description":"Unique trace ID for request, initialized by the TraceRequest interceptor","example":"52c42b5c-63c5-458d-8853-aeb0591b61df","format":"uuid"},"value":{"type":"string","description":"Value of the record","example":"Accusantium eos non maiores et quia."}},"example":{"id":"c3e5c8b1-b344-4640-879e-ddb0b4092c21","spanID":"4b6461cd-5a28-438b-9b46-9305009847e6","status":4070852458818509986,"tenant":"Nobis et animi facere.","traceID":"a4c3c8d3-598b-461e-ae0d-78511bc13c20","value":"Quos maiores minus iusto."},"required":["id","value","tenant","status"]},"StreamStreamingBody":{"type":"object","properties":{"id":{"type":"string","description":"Valid UUID representation as per RFC 4122","example":"5bb2f445-a761-4846-8e02-531493eed8b7","format":"uuid"},"spanID":{"type":"string","description":"Valid UUID representation as per RFC 4122","example":"4d18dbc6-c7b9-4593-b845-e7dddb190381","format":"uuid"},"traceID":{"type":"string","description":"Valid UUID representation as per RFC 4122","example":"d1b8e80f-caae-4312-af70-cf0fb1b043b7","format":"uuid"},"value":{"type":"string","description":"Value of the record","example":"Adipisci sit aut."}},"example":{"id":"Nesciunt quia ullam.","spanID":"Nesciunt quia ullam.","traceID":"Nesciunt quia ullam.","value":"Et fugiat ipsam porro non sequi."},"required":["id","value"]}}},"tags":[{"name":"interceptors","description":"The interceptors service demonstrates a comprehensive use of interceptors combining\nauthentication, tenant validation, caching, audit logging, and retry mechanisms. It showcases\nboth client-side and server-side interceptors working together to provide a robust service."}]} \ No newline at end of file diff --git a/interceptors/gen/http/openapi3.yaml b/interceptors/gen/http/openapi3.yaml new file mode 100644 index 000000000..919f77aba --- /dev/null +++ b/interceptors/gen/http/openapi3.yaml @@ -0,0 +1,429 @@ +openapi: 3.0.3 +info: + title: Goa API + version: 0.0.1 +servers: + - url: http://localhost:80 + description: Default server for interceptors +paths: + /records/{tenantID}: + post: + tags: + - interceptors + summary: create interceptors + description: Create a new record with all interceptors in action + operationId: interceptors#create + parameters: + - name: tenantID + in: path + description: Tenant ID for the request + required: true + schema: + type: string + description: Valid UUID representation as per RFC 4122 + example: d0f3a1f4-6b11-4294-b59d-f9e34b9b6e93 + format: uuid + example: Aliquid necessitatibus asperiores iure. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateRequestBody' + example: + spanID: 60119d23-b695-492d-b0fb-4c5195591902 + traceID: d94bb031-1e29-4544-a640-ae17323e1a90 + value: Rerum nesciunt suscipit est quo. + responses: + "201": + description: Created response. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateResponseBody' + example: + duration: 3684023309181312870 + id: 512fafca-7f09-4b06-863a-cecc41a8f6a8 + processedAt: Ea non vitae sit iure. + retryCount: 7486950083313293759 + retryDuration: 3930787756291036119 + status: 5202814868737196904 + tenant: Rerum sed ad vel esse. + value: Repudiandae quia. + /records/{tenantID}/{recordID}: + get: + tags: + - interceptors + summary: get interceptors + description: Get retrieves a record by ID with all interceptors in action + operationId: interceptors#get + parameters: + - name: tenantID + in: path + description: Tenant ID for the request + required: true + schema: + type: string + description: Valid UUID representation as per RFC 4122 + example: 897674da-3904-428f-b934-c43798999d7b + format: uuid + example: Aliquid necessitatibus asperiores iure. + - name: recordID + in: path + description: ID of the record to retrieve + required: true + schema: + type: string + description: Valid UUID representation as per RFC 4122 + example: d31df5e3-01de-43b4-acbe-bfc980f9345e + format: uuid + example: Aliquid necessitatibus asperiores iure. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/GetRequestBody' + example: + spanID: 150d7874-6995-4405-9422-192a638fe1a3 + traceID: f03bb3ab-2f3b-4961-8396-30a04e467ad7 + responses: + "200": + description: OK response. + content: + application/json: + schema: + $ref: '#/components/schemas/GetResponseBody' + example: + cachedAt: Enim architecto vel. + duration: 2688045444648128819 + id: 3189318c-89b1-4a0f-8768-a13a5369660e + processedAt: Pariatur nobis architecto sint consequatur et unde. + retryCount: 949445419645481428 + retryDuration: 4472582507154208325 + status: 54933130937179257 + tenant: Quos numquam aut minima. + value: Sint necessitatibus id ut minus quia quia. + "404": + description: 'NotFound: Record not found' + content: + application/vnd.goa.error: + schema: + $ref: '#/components/schemas/Error' + "503": + description: 'Unavailable: Temporary error' + content: + application/vnd.goa.error: + schema: + $ref: '#/components/schemas/Error' + /records/{tenantID}/stream: + get: + tags: + - interceptors + summary: stream interceptors + description: Stream records + operationId: interceptors#stream + parameters: + - name: tenantID + in: path + description: Tenant ID for the request + required: true + schema: + type: string + description: Valid UUID representation as per RFC 4122 + example: eddf9d7c-5830-4633-91cd-c102156bbdb2 + format: uuid + example: Aliquid necessitatibus asperiores iure. + responses: + "101": + description: Switching Protocols response. + content: + application/json: + schema: + $ref: '#/components/schemas/StreamResponseBody' + example: + id: a726b78a-0abe-43b3-879c-eaf39b95345a + spanID: ed81916d-f3bd-44c6-b138-a855bf2c7f12 + status: 4913202279654507592 + tenant: Sunt aut qui voluptatem modi eveniet sit. + traceID: 9bd267da-8bf9-4e43-88e9-2d035c6b0951 + value: Optio consequatur ipsam. +components: + schemas: + CreateRequestBody: + type: object + properties: + spanID: + type: string + description: Unique span ID for request, initialized by the TraceRequest interceptor + example: dde4c149-b4bd-4097-8621-30006c86e8e0 + format: uuid + traceID: + type: string + description: Unique trace ID for request, initialized by the TraceRequest interceptor + example: bf7bbcc5-1e3a-4f80-b27c-f20dc46dd59d + format: uuid + value: + type: string + description: Value to store in record + example: Iure velit rerum natus. + example: + spanID: 001ef099-6900-4b03-82c4-30247338a067 + traceID: b0c40fb5-b995-4019-b8b8-9653de84b789 + value: Eos non aut omnis et. + required: + - value + CreateResponseBody: + type: object + properties: + duration: + type: integer + description: Processing duration in ms + example: 2422317059159953466 + format: int64 + id: + type: string + description: ID of the created record + example: 6348968a-0415-4470-8805-796539fcae73 + format: uuid + processedAt: + type: string + description: Timestamp when processed + example: Velit reprehenderit. + retryCount: + type: integer + description: Number of retry attempts made + example: 9195687640623575973 + format: int64 + retryDuration: + type: integer + description: Total time spent retrying + example: 8864959330259880556 + format: int64 + status: + type: integer + description: Response status code + example: 380020668886814383 + format: int64 + tenant: + type: string + description: Tenant the record belongs to + example: Ea pariatur molestias nemo deserunt sit. + value: + type: string + description: Value of the record + example: Facere est suscipit quo. + example: + duration: 1790111840231600946 + id: c93b19d4-11ac-4651-a327-5a2f00464fb0 + processedAt: Quis dicta. + retryCount: 7805510653290713336 + retryDuration: 8684061465502470561 + status: 8372104706994352588 + tenant: Neque vel. + value: Nemo incidunt. + required: + - id + - value + - tenant + - status + - processedAt + - duration + Error: + type: object + properties: + fault: + type: boolean + description: Is the error a server-side fault? + example: true + id: + type: string + description: ID is a unique identifier for this particular occurrence of the problem. + example: 123abc + message: + type: string + description: Message is a human-readable explanation specific to this occurrence of the problem. + example: parameter 'p' must be an integer + name: + type: string + description: Name is the name of this class of errors. + example: bad_request + temporary: + type: boolean + description: Is the error temporary? + example: true + timeout: + type: boolean + description: Is the error a timeout? + example: true + description: Record not found + example: + fault: false + id: 123abc + message: parameter 'p' must be an integer + name: bad_request + temporary: false + timeout: true + required: + - name + - id + - message + - temporary + - timeout + - fault + GetRequestBody: + type: object + properties: + spanID: + type: string + description: Unique span ID for request, initialized by the TraceRequest interceptor + example: c17986d0-69c6-458b-aaca-41fb6a9e2aaf + format: uuid + traceID: + type: string + description: Unique trace ID for request, initialized by the TraceRequest interceptor + example: 6cc200ba-005e-4e4e-90cf-edab8d0cd369 + format: uuid + example: + spanID: 3774ed03-eceb-4016-ab1e-afaca435e4fa + traceID: 9a0d22da-e117-41a2-bfb4-515c613f2ae7 + GetResponseBody: + type: object + properties: + cachedAt: + type: string + description: Time at which the record was cached, written by the Cache interceptor + example: Et quas iste quas explicabo. + duration: + type: integer + description: Processing duration in ms, written by the RequestAudit interceptor + example: 4234899879073199693 + format: int64 + id: + type: string + description: ID of the record + example: feb30c06-2b2b-463f-9785-3a10018763c7 + format: uuid + processedAt: + type: string + description: Timestamp when processed, written by the RequestAudit interceptor + example: Et quidem eos laboriosam velit provident. + retryCount: + type: integer + description: Number of retry attempts made, written client-side by the Retry interceptor + example: 8984616366653758809 + format: int64 + retryDuration: + type: integer + description: Total time spent retrying, written client-side by the Retry interceptor + example: 783576862198586200 + format: int64 + status: + type: integer + description: Response status code + example: 943917848840806908 + format: int64 + tenant: + type: string + description: Tenant the record belongs to + example: Corporis dolorem sit. + value: + type: string + description: Value of the record + example: Vitae molestiae vitae. + example: + cachedAt: Occaecati aut asperiores. + duration: 8398049820790322035 + id: 57063575-9e52-4a61-93ad-3bbd7d73728d + processedAt: Quo voluptatem. + retryCount: 727626558249177223 + retryDuration: 1482120365798449866 + status: 805191965083195454 + tenant: Voluptas et quisquam enim. + value: Quas nihil numquam ut. + required: + - id + - value + - tenant + - status + - processedAt + - duration + StreamResponseBody: + type: object + properties: + id: + type: string + description: ID of the created record + example: 4dfe326d-ad2e-4131-a841-07ed3b67159c + format: uuid + spanID: + type: string + description: Unique span ID for request, initialized by the TraceRequest interceptor + example: 6666e8e6-81b7-4ee1-be48-b7cc0f843b81 + format: uuid + status: + type: integer + description: Response status code + example: 7575731313406397237 + format: int64 + tenant: + type: string + description: Tenant the record belongs to + example: Aut velit laborum ut. + traceID: + type: string + description: Unique trace ID for request, initialized by the TraceRequest interceptor + example: 52c42b5c-63c5-458d-8853-aeb0591b61df + format: uuid + value: + type: string + description: Value of the record + example: Accusantium eos non maiores et quia. + example: + id: c3e5c8b1-b344-4640-879e-ddb0b4092c21 + spanID: 4b6461cd-5a28-438b-9b46-9305009847e6 + status: 4070852458818509986 + tenant: Nobis et animi facere. + traceID: a4c3c8d3-598b-461e-ae0d-78511bc13c20 + value: Quos maiores minus iusto. + required: + - id + - value + - tenant + - status + StreamStreamingBody: + type: object + properties: + id: + type: string + description: Valid UUID representation as per RFC 4122 + example: 5bb2f445-a761-4846-8e02-531493eed8b7 + format: uuid + spanID: + type: string + description: Valid UUID representation as per RFC 4122 + example: 4d18dbc6-c7b9-4593-b845-e7dddb190381 + format: uuid + traceID: + type: string + description: Valid UUID representation as per RFC 4122 + example: d1b8e80f-caae-4312-af70-cf0fb1b043b7 + format: uuid + value: + type: string + description: Value of the record + example: Adipisci sit aut. + example: + id: Nesciunt quia ullam. + spanID: Nesciunt quia ullam. + traceID: Nesciunt quia ullam. + value: Et fugiat ipsam porro non sequi. + required: + - id + - value +tags: + - name: interceptors + description: |- + The interceptors service demonstrates a comprehensive use of interceptors combining + authentication, tenant validation, caching, audit logging, and retry mechanisms. It showcases + both client-side and server-side interceptors working together to provide a robust service. diff --git a/interceptors/gen/interceptors/client.go b/interceptors/gen/interceptors/client.go new file mode 100644 index 000000000..f119bae66 --- /dev/null +++ b/interceptors/gen/interceptors/client.go @@ -0,0 +1,64 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors client +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package interceptors + +import ( + "context" + + goa "goa.design/goa/v3/pkg" +) + +// Client is the "interceptors" service client. +type Client struct { + GetEndpoint goa.Endpoint + CreateEndpoint goa.Endpoint + StreamEndpoint goa.Endpoint +} + +// NewClient initializes a "interceptors" service client given the endpoints. +func NewClient(get, create, stream goa.Endpoint, ci ClientInterceptors) *Client { + return &Client{ + GetEndpoint: WrapGetClientEndpoint(get, ci), + CreateEndpoint: WrapCreateClientEndpoint(create, ci), + StreamEndpoint: WrapStreamClientEndpoint(stream, ci), + } +} + +// Get calls the "get" endpoint of the "interceptors" service. +// Get may return the following errors: +// - "NotFound" (type *goa.ServiceError): Record not found +// - "Unavailable" (type *goa.ServiceError): Temporary error +// - error: internal error +func (c *Client) Get(ctx context.Context, p *GetPayload) (res *GetResult, err error) { + var ires any + ires, err = c.GetEndpoint(ctx, p) + if err != nil { + return + } + return ires.(*GetResult), nil +} + +// Create calls the "create" endpoint of the "interceptors" service. +func (c *Client) Create(ctx context.Context, p *CreatePayload) (res *CreateResult, err error) { + var ires any + ires, err = c.CreateEndpoint(ctx, p) + if err != nil { + return + } + return ires.(*CreateResult), nil +} + +// Stream calls the "stream" endpoint of the "interceptors" service. +func (c *Client) Stream(ctx context.Context, p *StreamPayload) (res StreamClientStream, err error) { + var ires any + ires, err = c.StreamEndpoint(ctx, p) + if err != nil { + return + } + return ires.(StreamClientStream), nil +} diff --git a/interceptors/gen/interceptors/client_interceptors.go b/interceptors/gen/interceptors/client_interceptors.go new file mode 100644 index 000000000..bd8cd44ee --- /dev/null +++ b/interceptors/gen/interceptors/client_interceptors.go @@ -0,0 +1,218 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptorsClient Interceptors +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package interceptors + +import ( + "context" + + goa "goa.design/goa/v3/pkg" +) + +// ClientInterceptors defines the interface for all client-side interceptors. +// Client interceptors execute after the payload is encoded and before the request +// is sent to the server. The implementation is responsible for calling next to +// complete the request. +type ClientInterceptors interface { + // Client-side interceptor which writes the tenant ID to the signed JWT + // contained in the Authorization header + EncodeTenant(ctx context.Context, info *EncodeTenantInfo, next goa.Endpoint) (any, error) + // Client-side interceptor which implements smart retry logic with exponential + // backoff + Retry(ctx context.Context, info *RetryInfo, next goa.Endpoint) (any, error) + // Server-side and client-side interceptor that adds trace context to the + // bidirectional stream payload + TraceBidirectionalStream(ctx context.Context, info *TraceBidirectionalStreamInfo, next goa.Endpoint) (any, error) +} + +// Access interfaces for interceptor payloads and results +type ( + // EncodeTenantInfo provides metadata about the current interception. + // It includes service name, method name, and access to the endpoint. + EncodeTenantInfo struct { + service string + method string + callType goa.InterceptorCallType + rawPayload any + } + + // EncodeTenantPayload provides type-safe access to the method payload. + // It allows reading and writing specific fields of the payload as defined + // in the design. + EncodeTenantPayload interface { + TenantID() UUID + SetAuth(string) + } + // RetryInfo provides metadata about the current interception. + // It includes service name, method name, and access to the endpoint. + RetryInfo struct { + service string + method string + callType goa.InterceptorCallType + rawPayload any + } + + // RetryResult provides type-safe access to the method result. + // It allows reading and writing specific fields of the result as defined + // in the design. + RetryResult interface { + Status() int + SetRetryCount(int) + SetRetryDuration(int) + } +) + +// Private implementation types +type ( + encodeTenantGetPayload struct { + payload *GetPayload + } + encodeTenantCreatePayload struct { + payload *CreatePayload + } + encodeTenantStreamPayload struct { + payload *StreamPayload + } + retryGetResult struct { + result *GetResult + } + retryCreateResult struct { + result *CreateResult + } +) + +// WrapGetClientEndpoint wraps the get endpoint with the client interceptors +// defined in the design. +func WrapGetClientEndpoint(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + endpoint = wrapClientGetEncodeTenant(endpoint, i) + endpoint = wrapClientGetRetry(endpoint, i) + return endpoint +} + +// WrapCreateClientEndpoint wraps the create endpoint with the client +// interceptors defined in the design. +func WrapCreateClientEndpoint(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + endpoint = wrapClientCreateEncodeTenant(endpoint, i) + endpoint = wrapClientCreateRetry(endpoint, i) + return endpoint +} + +// WrapStreamClientEndpoint wraps the stream endpoint with the client +// interceptors defined in the design. +func WrapStreamClientEndpoint(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + endpoint = wrapClientStreamEncodeTenant(endpoint, i) + endpoint = wrapClientStreamTraceBidirectionalStream(endpoint, i) + return endpoint +} + +// Public accessor methods for Info types + +// Service returns the name of the service handling the request. +func (info *EncodeTenantInfo) Service() string { + return info.service +} + +// Method returns the name of the method handling the request. +func (info *EncodeTenantInfo) Method() string { + return info.method +} + +// CallType returns the type of call the interceptor is handling. +func (info *EncodeTenantInfo) CallType() goa.InterceptorCallType { + return info.callType +} + +// RawPayload returns the raw payload of the request. +func (info *EncodeTenantInfo) RawPayload() any { + return info.rawPayload +} + +// Payload returns a type-safe accessor for the method payload. +func (info *EncodeTenantInfo) Payload() EncodeTenantPayload { + switch info.Method() { + case "Get": + return &encodeTenantGetPayload{payload: info.RawPayload().(*GetPayload)} + case "Create": + return &encodeTenantCreatePayload{payload: info.RawPayload().(*CreatePayload)} + case "Stream": + return &encodeTenantStreamPayload{payload: info.RawPayload().(*StreamPayload)} + default: + return nil + } +} + +// Service returns the name of the service handling the request. +func (info *RetryInfo) Service() string { + return info.service +} + +// Method returns the name of the method handling the request. +func (info *RetryInfo) Method() string { + return info.method +} + +// CallType returns the type of call the interceptor is handling. +func (info *RetryInfo) CallType() goa.InterceptorCallType { + return info.callType +} + +// RawPayload returns the raw payload of the request. +func (info *RetryInfo) RawPayload() any { + return info.rawPayload +} + +// Result returns a type-safe accessor for the method result. +func (info *RetryInfo) Result(res any) RetryResult { + switch info.Method() { + case "Get": + return &retryGetResult{result: res.(*GetResult)} + case "Create": + return &retryCreateResult{result: res.(*CreateResult)} + default: + return nil + } +} + +// Private implementation methods + +func (p *encodeTenantGetPayload) TenantID() UUID { + return p.payload.TenantID +} +func (p *encodeTenantGetPayload) SetAuth(v string) { + p.payload.Auth = v +} +func (p *encodeTenantCreatePayload) TenantID() UUID { + return p.payload.TenantID +} +func (p *encodeTenantCreatePayload) SetAuth(v string) { + p.payload.Auth = v +} +func (p *encodeTenantStreamPayload) TenantID() UUID { + return p.payload.TenantID +} +func (p *encodeTenantStreamPayload) SetAuth(v string) { + p.payload.Auth = v +} + +func (r *retryGetResult) Status() int { + return r.result.Status +} +func (r *retryGetResult) SetRetryCount(v int) { + r.result.RetryCount = &v +} +func (r *retryGetResult) SetRetryDuration(v int) { + r.result.RetryDuration = &v +} +func (r *retryCreateResult) Status() int { + return r.result.Status +} +func (r *retryCreateResult) SetRetryCount(v int) { + r.result.RetryCount = &v +} +func (r *retryCreateResult) SetRetryDuration(v int) { + r.result.RetryDuration = &v +} diff --git a/interceptors/gen/interceptors/endpoints.go b/interceptors/gen/interceptors/endpoints.go new file mode 100644 index 000000000..6400737f9 --- /dev/null +++ b/interceptors/gen/interceptors/endpoints.go @@ -0,0 +1,77 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors endpoints +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package interceptors + +import ( + "context" + + goa "goa.design/goa/v3/pkg" +) + +// Endpoints wraps the "interceptors" service endpoints. +type Endpoints struct { + Get goa.Endpoint + Create goa.Endpoint + Stream goa.Endpoint +} + +// StreamEndpointInput holds both the payload and the server stream of the +// "stream" method. +type StreamEndpointInput struct { + // Payload is the method payload. + Payload *StreamPayload + // Stream is the server stream used by the "stream" method to send data. + Stream StreamServerStream +} + +// NewEndpoints wraps the methods of the "interceptors" service with endpoints. +func NewEndpoints(s Service, si ServerInterceptors) *Endpoints { + endpoints := &Endpoints{ + Get: NewGetEndpoint(s), + Create: NewCreateEndpoint(s), + Stream: NewStreamEndpoint(s), + } + endpoints.Get = WrapGetEndpoint(endpoints.Get, si) + endpoints.Create = WrapCreateEndpoint(endpoints.Create, si) + endpoints.Stream = WrapStreamEndpoint(endpoints.Stream, si) + return endpoints +} + +// Use applies the given middleware to all the "interceptors" service endpoints. +func (e *Endpoints) Use(m func(goa.Endpoint) goa.Endpoint) { + e.Get = m(e.Get) + e.Create = m(e.Create) + e.Stream = m(e.Stream) +} + +// NewGetEndpoint returns an endpoint function that calls the method "get" of +// service "interceptors". +func NewGetEndpoint(s Service) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + p := req.(*GetPayload) + return s.Get(ctx, p) + } +} + +// NewCreateEndpoint returns an endpoint function that calls the method +// "create" of service "interceptors". +func NewCreateEndpoint(s Service) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + p := req.(*CreatePayload) + return s.Create(ctx, p) + } +} + +// NewStreamEndpoint returns an endpoint function that calls the method +// "stream" of service "interceptors". +func NewStreamEndpoint(s Service) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + ep := req.(*StreamEndpointInput) + return nil, s.Stream(ctx, ep.Payload, ep.Stream) + } +} diff --git a/interceptors/gen/interceptors/interceptor_wrappers.go b/interceptors/gen/interceptors/interceptor_wrappers.go new file mode 100644 index 000000000..88d5316cf --- /dev/null +++ b/interceptors/gen/interceptors/interceptor_wrappers.go @@ -0,0 +1,396 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// Interceptor wrappers +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package interceptors + +import ( + "context" + + goa "goa.design/goa/v3/pkg" +) + +// wrappedStreamServerStream is a server interceptor wrapper for the +// StreamServerStream stream. +type wrappedStreamServerStream struct { + ctx context.Context + sendWithContext func(context.Context, *StreamResult) error + recvWithContext func(context.Context) (*StreamStreamingPayload, error) + stream StreamServerStream +} + +// wrappedStreamClientStream is a client interceptor wrapper for the +// StreamClientStream stream. +type wrappedStreamClientStream struct { + ctx context.Context + sendWithContext func(context.Context, *StreamStreamingPayload) error + recvWithContext func(context.Context) (*StreamResult, error) + stream StreamClientStream +} + +// wrapCacheGet applies the Cache server interceptor to endpoints. +func wrapGetCache(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &CacheInfo{ + service: "interceptors", + method: "Get", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.Cache(ctx, info, endpoint) + } +} + +// wrapJWTAuthGet applies the JWTAuth server interceptor to endpoints. +func wrapGetJWTAuth(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &JWTAuthInfo{ + service: "interceptors", + method: "Get", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.JWTAuth(ctx, info, endpoint) + } +} + +// wrapJWTAuthCreate applies the JWTAuth server interceptor to endpoints. +func wrapCreateJWTAuth(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &JWTAuthInfo{ + service: "interceptors", + method: "Create", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.JWTAuth(ctx, info, endpoint) + } +} + +// wrapJWTAuthStream applies the JWTAuth server interceptor to endpoints. +func wrapStreamJWTAuth(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &JWTAuthInfo{ + service: "interceptors", + method: "Stream", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.JWTAuth(ctx, info, endpoint) + } +} + +// wrapRequestAuditGet applies the RequestAudit server interceptor to endpoints. +func wrapGetRequestAudit(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &RequestAuditInfo{ + service: "interceptors", + method: "Get", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.RequestAudit(ctx, info, endpoint) + } +} + +// wrapRequestAuditCreate applies the RequestAudit server interceptor to +// endpoints. +func wrapCreateRequestAudit(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &RequestAuditInfo{ + service: "interceptors", + method: "Create", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.RequestAudit(ctx, info, endpoint) + } +} + +// wrapSetDeadlineGet applies the SetDeadline server interceptor to endpoints. +func wrapGetSetDeadline(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &SetDeadlineInfo{ + service: "interceptors", + method: "Get", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.SetDeadline(ctx, info, endpoint) + } +} + +// wrapSetDeadlineCreate applies the SetDeadline server interceptor to +// endpoints. +func wrapCreateSetDeadline(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &SetDeadlineInfo{ + service: "interceptors", + method: "Create", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.SetDeadline(ctx, info, endpoint) + } +} + +// wrapSetDeadlineStream applies the SetDeadline server interceptor to +// endpoints. +func wrapStreamSetDeadline(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &SetDeadlineInfo{ + service: "interceptors", + method: "Stream", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.SetDeadline(ctx, info, endpoint) + } +} + +// wrapTraceBidirectionalStreamStream applies the TraceBidirectionalStream +// server interceptor to endpoints. +func wrapStreamTraceBidirectionalStream(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + stream := req.(*StreamEndpointInput).Stream + req.(*StreamEndpointInput).Stream = &wrappedStreamServerStream{ + ctx: ctx, + sendWithContext: func(ctx context.Context, req *StreamResult) error { + info := &TraceBidirectionalStreamInfo{ + service: "interceptors", + method: "Stream", + callType: goa.InterceptorStreamingSend, + rawPayload: req, + } + _, err := i.TraceBidirectionalStream(ctx, info, func(ctx context.Context, req any) (any, error) { + castReq, _ := req.(*StreamResult) + return nil, stream.SendWithContext(ctx, castReq) + }) + return err + }, + recvWithContext: func(ctx context.Context) (*StreamStreamingPayload, error) { + info := &TraceBidirectionalStreamInfo{ + service: "interceptors", + method: "Stream", + callType: goa.InterceptorStreamingRecv, + } + res, err := i.TraceBidirectionalStream(ctx, info, func(ctx context.Context, _ any) (any, error) { + return stream.RecvWithContext(ctx) + }) + castRes, _ := res.(*StreamStreamingPayload) + return castRes, err + }, + stream: stream, + } + return endpoint(ctx, req) + } +} + +// wrapTraceRequestGet applies the TraceRequest server interceptor to endpoints. +func wrapGetTraceRequest(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &TraceRequestInfo{ + service: "interceptors", + method: "Get", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.TraceRequest(ctx, info, endpoint) + } +} + +// wrapTraceRequestCreate applies the TraceRequest server interceptor to +// endpoints. +func wrapCreateTraceRequest(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &TraceRequestInfo{ + service: "interceptors", + method: "Create", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.TraceRequest(ctx, info, endpoint) + } +} + +// wrapClientEncodeTenantGet applies the EncodeTenant client interceptor to +// endpoints. +func wrapClientGetEncodeTenant(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &EncodeTenantInfo{ + service: "interceptors", + method: "Get", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.EncodeTenant(ctx, info, endpoint) + } +} + +// wrapClientEncodeTenantCreate applies the EncodeTenant client interceptor to +// endpoints. +func wrapClientCreateEncodeTenant(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &EncodeTenantInfo{ + service: "interceptors", + method: "Create", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.EncodeTenant(ctx, info, endpoint) + } +} + +// wrapClientEncodeTenantStream applies the EncodeTenant client interceptor to +// endpoints. +func wrapClientStreamEncodeTenant(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &EncodeTenantInfo{ + service: "interceptors", + method: "Stream", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.EncodeTenant(ctx, info, endpoint) + } +} + +// wrapClientRetryGet applies the Retry client interceptor to endpoints. +func wrapClientGetRetry(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &RetryInfo{ + service: "interceptors", + method: "Get", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.Retry(ctx, info, endpoint) + } +} + +// wrapClientRetryCreate applies the Retry client interceptor to endpoints. +func wrapClientCreateRetry(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + info := &RetryInfo{ + service: "interceptors", + method: "Create", + callType: goa.InterceptorUnary, + rawPayload: req, + } + return i.Retry(ctx, info, endpoint) + } +} + +// wrapClientTraceBidirectionalStreamStream applies the +// TraceBidirectionalStream client interceptor to endpoints. +func wrapClientStreamTraceBidirectionalStream(endpoint goa.Endpoint, i ClientInterceptors) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + res, err := endpoint(ctx, req) + if err != nil { + return res, err + } + stream := res.(StreamClientStream) + return &wrappedStreamClientStream{ + ctx: ctx, + sendWithContext: func(ctx context.Context, req *StreamStreamingPayload) error { + info := &TraceBidirectionalStreamInfo{ + service: "interceptors", + method: "Stream", + callType: goa.InterceptorStreamingSend, + rawPayload: req, + } + _, err := i.TraceBidirectionalStream(ctx, info, func(ctx context.Context, req any) (any, error) { + castReq, _ := req.(*StreamStreamingPayload) + return nil, stream.SendWithContext(ctx, castReq) + }) + return err + }, + recvWithContext: func(ctx context.Context) (*StreamResult, error) { + info := &TraceBidirectionalStreamInfo{ + service: "interceptors", + method: "Stream", + callType: goa.InterceptorStreamingRecv, + } + res, err := i.TraceBidirectionalStream(ctx, info, func(ctx context.Context, _ any) (any, error) { + return stream.RecvWithContext(ctx) + }) + castRes, _ := res.(*StreamResult) + return castRes, err + }, + stream: stream, + }, nil + } +} + +// Send streams instances of "StreamServerStream" after executing the applied +// interceptor. +func (w *wrappedStreamServerStream) Send(v *StreamResult) error { + return w.SendWithContext(w.ctx, v) +} + +// SendWithContext streams instances of "StreamServerStream" after executing +// the applied interceptor with context. +func (w *wrappedStreamServerStream) SendWithContext(ctx context.Context, v *StreamResult) error { + if w.sendWithContext == nil { + return w.stream.SendWithContext(ctx, v) + } + return w.sendWithContext(ctx, v) +} + +// Recv reads instances of "StreamServerStream" from the stream after executing +// the applied interceptor. +func (w *wrappedStreamServerStream) Recv() (*StreamStreamingPayload, error) { + return w.RecvWithContext(w.ctx) +} + +// RecvWithContext reads instances of "StreamServerStream" from the stream +// after executing the applied interceptor with context. +func (w *wrappedStreamServerStream) RecvWithContext(ctx context.Context) (*StreamStreamingPayload, error) { + if w.recvWithContext == nil { + return w.stream.RecvWithContext(ctx) + } + return w.recvWithContext(ctx) +} + +// Close closes the stream. +func (w *wrappedStreamServerStream) Close() error { + return w.stream.Close() +} + +// Send streams instances of "StreamClientStream" after executing the applied +// interceptor. +func (w *wrappedStreamClientStream) Send(v *StreamStreamingPayload) error { + return w.SendWithContext(w.ctx, v) +} + +// SendWithContext streams instances of "StreamClientStream" after executing +// the applied interceptor with context. +func (w *wrappedStreamClientStream) SendWithContext(ctx context.Context, v *StreamStreamingPayload) error { + if w.sendWithContext == nil { + return w.stream.SendWithContext(ctx, v) + } + return w.sendWithContext(ctx, v) +} + +// Recv reads instances of "StreamClientStream" from the stream after executing +// the applied interceptor. +func (w *wrappedStreamClientStream) Recv() (*StreamResult, error) { + return w.RecvWithContext(w.ctx) +} + +// RecvWithContext reads instances of "StreamClientStream" from the stream +// after executing the applied interceptor with context. +func (w *wrappedStreamClientStream) RecvWithContext(ctx context.Context) (*StreamResult, error) { + if w.recvWithContext == nil { + return w.stream.RecvWithContext(ctx) + } + return w.recvWithContext(ctx) +} + +// Close closes the stream. +func (w *wrappedStreamClientStream) Close() error { + return w.stream.Close() +} diff --git a/interceptors/gen/interceptors/service.go b/interceptors/gen/interceptors/service.go new file mode 100644 index 000000000..fbf61a5d7 --- /dev/null +++ b/interceptors/gen/interceptors/service.go @@ -0,0 +1,197 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors service +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package interceptors + +import ( + "context" + + goa "goa.design/goa/v3/pkg" +) + +// The interceptors service demonstrates a comprehensive use of interceptors +// combining +// authentication, tenant validation, caching, audit logging, and retry +// mechanisms. It showcases +// both client-side and server-side interceptors working together to provide a +// robust service. +type Service interface { + // Get retrieves a record by ID with all interceptors in action + Get(context.Context, *GetPayload) (res *GetResult, err error) + // Create a new record with all interceptors in action + Create(context.Context, *CreatePayload) (res *CreateResult, err error) + // Stream records + Stream(context.Context, *StreamPayload, StreamServerStream) (err error) +} + +// APIName is the name of the API as defined in the design. +const APIName = "interceptors" + +// APIVersion is the version of the API as defined in the design. +const APIVersion = "0.0.1" + +// ServiceName is the name of the service as defined in the design. This is the +// same value that is set in the endpoint request contexts under the ServiceKey +// key. +const ServiceName = "interceptors" + +// MethodNames lists the service method names as defined in the design. These +// are the same values that are set in the endpoint request contexts under the +// MethodKey key. +var MethodNames = [3]string{"get", "create", "stream"} + +// StreamServerStream is the interface a "stream" endpoint server stream must +// satisfy. +type StreamServerStream interface { + // Send streams instances of "StreamResult". + Send(*StreamResult) error + // SendWithContext streams instances of "StreamResult" with context. + SendWithContext(context.Context, *StreamResult) error + // Recv reads instances of "StreamStreamingPayload" from the stream. + Recv() (*StreamStreamingPayload, error) + // RecvWithContext reads instances of "StreamStreamingPayload" from the stream + // with context. + RecvWithContext(context.Context) (*StreamStreamingPayload, error) + // Close closes the stream. + Close() error +} + +// StreamClientStream is the interface a "stream" endpoint client stream must +// satisfy. +type StreamClientStream interface { + // Send streams instances of "StreamStreamingPayload". + Send(*StreamStreamingPayload) error + // SendWithContext streams instances of "StreamStreamingPayload" with context. + SendWithContext(context.Context, *StreamStreamingPayload) error + // Recv reads instances of "StreamResult" from the stream. + Recv() (*StreamResult, error) + // RecvWithContext reads instances of "StreamResult" from the stream with + // context. + RecvWithContext(context.Context) (*StreamResult, error) + // Close closes the stream. + Close() error +} + +// CreatePayload is the payload type of the interceptors service create method. +type CreatePayload struct { + // Tenant ID for the request + TenantID UUID + // Value to store in record + Value string + // JWT auth token + Auth string + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *UUID + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *UUID +} + +// CreateResult is the result type of the interceptors service create method. +type CreateResult struct { + // ID of the created record + ID UUID + // Value of the record + Value string + // Tenant the record belongs to + Tenant string + // Response status code + Status int + // Timestamp when processed + ProcessedAt string + // Processing duration in ms + Duration int + // Number of retry attempts made + RetryCount *int + // Total time spent retrying + RetryDuration *int +} + +// GetPayload is the payload type of the interceptors service get method. +type GetPayload struct { + // Tenant ID for the request + TenantID UUID + // ID of the record to retrieve + RecordID UUID + // JWT auth token + Auth string + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *UUID + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *UUID +} + +// GetResult is the result type of the interceptors service get method. +type GetResult struct { + // ID of the record + ID UUID + // Value of the record + Value string + // Tenant the record belongs to + Tenant string + // Response status code + Status int + // Timestamp when processed, written by the RequestAudit interceptor + ProcessedAt string + // Processing duration in ms, written by the RequestAudit interceptor + Duration int + // Time at which the record was cached, written by the Cache interceptor + CachedAt *string + // Number of retry attempts made, written client-side by the Retry interceptor + RetryCount *int + // Total time spent retrying, written client-side by the Retry interceptor + RetryDuration *int +} + +// StreamPayload is the payload type of the interceptors service stream method. +type StreamPayload struct { + // Tenant ID for the request + TenantID UUID + // JWT auth token + Auth string +} + +// StreamResult is the result type of the interceptors service stream method. +type StreamResult struct { + // ID of the created record + ID UUID + // Value of the record + Value string + // Tenant the record belongs to + Tenant string + // Response status code + Status int + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *UUID + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *UUID +} + +// StreamStreamingPayload is the streaming payload type of the interceptors +// service stream method. +type StreamStreamingPayload struct { + // ID of the created record + ID UUID + // Value of the record + Value string + // Unique trace ID for request, initialized by the TraceRequest interceptor + TraceID *UUID + // Unique span ID for request, initialized by the TraceRequest interceptor + SpanID *UUID +} + +// Valid UUID representation as per RFC 4122 +type UUID string + +// MakeNotFound builds a goa.ServiceError from an error. +func MakeNotFound(err error) *goa.ServiceError { + return goa.NewServiceError(err, "NotFound", false, false, false) +} + +// MakeUnavailable builds a goa.ServiceError from an error. +func MakeUnavailable(err error) *goa.ServiceError { + return goa.NewServiceError(err, "Unavailable", false, true, false) +} diff --git a/interceptors/gen/interceptors/service_interceptors.go b/interceptors/gen/interceptors/service_interceptors.go new file mode 100644 index 000000000..7c9e457d0 --- /dev/null +++ b/interceptors/gen/interceptors/service_interceptors.go @@ -0,0 +1,510 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptorsServer Interceptors +// +// Command: +// $ goa gen goa.design/examples/interceptors/design + +package interceptors + +import ( + "context" + + goa "goa.design/goa/v3/pkg" +) + +// ServerInterceptors defines the interface for all server-side interceptors. +// Server interceptors execute after the request is decoded and before the +// payload is sent to the service. The implementation is responsible for calling +// next to complete the request. +type ServerInterceptors interface { + // Server-side interceptor which implements a transparent cache for loaded + // records + Cache(ctx context.Context, info *CacheInfo, next goa.Endpoint) (any, error) + // Server-side interceptor that validates JWT token and tenant ID + JWTAuth(ctx context.Context, info *JWTAuthInfo, next goa.Endpoint) (any, error) + // Server-side interceptor that provides comprehensive request/response audit + // logging + RequestAudit(ctx context.Context, info *RequestAuditInfo, next goa.Endpoint) (any, error) + // Server-side interceptor which sets the context deadline for the request + SetDeadline(ctx context.Context, info *SetDeadlineInfo, next goa.Endpoint) (any, error) + // Server-side and client-side interceptor that adds trace context to the + // bidirectional stream payload + TraceBidirectionalStream(ctx context.Context, info *TraceBidirectionalStreamInfo, next goa.Endpoint) (any, error) + // Server-side interceptor that adds trace context to the request payload + TraceRequest(ctx context.Context, info *TraceRequestInfo, next goa.Endpoint) (any, error) +} + +// Access interfaces for interceptor payloads and results +type ( + // CacheInfo provides metadata about the current interception. + // It includes service name, method name, and access to the endpoint. + CacheInfo struct { + service string + method string + callType goa.InterceptorCallType + rawPayload any + } + + // CachePayload provides type-safe access to the method payload. + // It allows reading and writing specific fields of the payload as defined + // in the design. + CachePayload interface { + RecordID() UUID + } + + // CacheResult provides type-safe access to the method result. + // It allows reading and writing specific fields of the result as defined + // in the design. + CacheResult interface { + SetCachedAt(string) + } + // JWTAuthInfo provides metadata about the current interception. + // It includes service name, method name, and access to the endpoint. + JWTAuthInfo struct { + service string + method string + callType goa.InterceptorCallType + rawPayload any + } + + // JWTAuthPayload provides type-safe access to the method payload. + // It allows reading and writing specific fields of the payload as defined + // in the design. + JWTAuthPayload interface { + Auth() string + TenantID() UUID + } + // RequestAuditInfo provides metadata about the current interception. + // It includes service name, method name, and access to the endpoint. + RequestAuditInfo struct { + service string + method string + callType goa.InterceptorCallType + rawPayload any + } + + // RequestAuditResult provides type-safe access to the method result. + // It allows reading and writing specific fields of the result as defined + // in the design. + RequestAuditResult interface { + Status() int + SetProcessedAt(string) + SetDuration(int) + } + // SetDeadlineInfo provides metadata about the current interception. + // It includes service name, method name, and access to the endpoint. + SetDeadlineInfo struct { + service string + method string + callType goa.InterceptorCallType + rawPayload any + } + // TraceBidirectionalStreamInfo provides metadata about the current interception. + // It includes service name, method name, and access to the endpoint. + TraceBidirectionalStreamInfo struct { + service string + method string + callType goa.InterceptorCallType + rawPayload any + } + + // TraceBidirectionalStreamStreamingPayload provides type-safe access to the method streaming payload. + // It allows reading and writing specific fields of the streaming payload as defined + // in the design. + TraceBidirectionalStreamStreamingPayload interface { + TraceID() UUID + SpanID() UUID + SetTraceID(UUID) + SetSpanID(UUID) + } + + // TraceBidirectionalStreamStreamingResult provides type-safe access to the method streaming result. + // It allows reading and writing specific fields of the streaming result as defined + // in the design. + TraceBidirectionalStreamStreamingResult interface { + TraceID() UUID + SpanID() UUID + SetTraceID(UUID) + SetSpanID(UUID) + } + // TraceRequestInfo provides metadata about the current interception. + // It includes service name, method name, and access to the endpoint. + TraceRequestInfo struct { + service string + method string + callType goa.InterceptorCallType + rawPayload any + } + + // TraceRequestPayload provides type-safe access to the method payload. + // It allows reading and writing specific fields of the payload as defined + // in the design. + TraceRequestPayload interface { + SetTraceID(UUID) + SetSpanID(UUID) + } +) + +// Private implementation types +type ( + cacheGetPayload struct { + payload *GetPayload + } + jWTAuthGetPayload struct { + payload *GetPayload + } + jWTAuthCreatePayload struct { + payload *CreatePayload + } + jWTAuthStreamPayload struct { + payload *StreamPayload + } + traceRequestGetPayload struct { + payload *GetPayload + } + traceRequestCreatePayload struct { + payload *CreatePayload + } + cacheGetResult struct { + result *GetResult + } + requestAuditGetResult struct { + result *GetResult + } + requestAuditCreateResult struct { + result *CreateResult + } + traceBidirectionalStreamStreamStreamingPayload struct { + payload *StreamStreamingPayload + } + traceBidirectionalStreamStreamStreamingResult struct { + result *StreamResult + } +) + +// WrapGetEndpoint wraps the get endpoint with the server-side interceptors +// defined in the design. +func WrapGetEndpoint(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + endpoint = wrapGetCache(endpoint, i) + endpoint = wrapGetJWTAuth(endpoint, i) + endpoint = wrapGetRequestAudit(endpoint, i) + endpoint = wrapGetSetDeadline(endpoint, i) + endpoint = wrapGetTraceRequest(endpoint, i) + return endpoint +} + +// WrapCreateEndpoint wraps the create endpoint with the server-side +// interceptors defined in the design. +func WrapCreateEndpoint(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + endpoint = wrapCreateJWTAuth(endpoint, i) + endpoint = wrapCreateRequestAudit(endpoint, i) + endpoint = wrapCreateSetDeadline(endpoint, i) + endpoint = wrapCreateTraceRequest(endpoint, i) + return endpoint +} + +// WrapStreamEndpoint wraps the stream endpoint with the server-side +// interceptors defined in the design. +func WrapStreamEndpoint(endpoint goa.Endpoint, i ServerInterceptors) goa.Endpoint { + endpoint = wrapStreamJWTAuth(endpoint, i) + endpoint = wrapStreamSetDeadline(endpoint, i) + endpoint = wrapStreamTraceBidirectionalStream(endpoint, i) + return endpoint +} + +// Public accessor methods for Info types + +// Service returns the name of the service handling the request. +func (info *CacheInfo) Service() string { + return info.service +} + +// Method returns the name of the method handling the request. +func (info *CacheInfo) Method() string { + return info.method +} + +// CallType returns the type of call the interceptor is handling. +func (info *CacheInfo) CallType() goa.InterceptorCallType { + return info.callType +} + +// RawPayload returns the raw payload of the request. +func (info *CacheInfo) RawPayload() any { + return info.rawPayload +} + +// Payload returns a type-safe accessor for the method payload. +func (info *CacheInfo) Payload() CachePayload { + return &cacheGetPayload{payload: info.RawPayload().(*GetPayload)} +} + +// Result returns a type-safe accessor for the method result. +func (info *CacheInfo) Result(res any) CacheResult { + return &cacheGetResult{result: res.(*GetResult)} +} + +// Service returns the name of the service handling the request. +func (info *JWTAuthInfo) Service() string { + return info.service +} + +// Method returns the name of the method handling the request. +func (info *JWTAuthInfo) Method() string { + return info.method +} + +// CallType returns the type of call the interceptor is handling. +func (info *JWTAuthInfo) CallType() goa.InterceptorCallType { + return info.callType +} + +// RawPayload returns the raw payload of the request. +func (info *JWTAuthInfo) RawPayload() any { + return info.rawPayload +} + +// Payload returns a type-safe accessor for the method payload. +func (info *JWTAuthInfo) Payload() JWTAuthPayload { + switch info.Method() { + case "Get": + return &jWTAuthGetPayload{payload: info.RawPayload().(*GetPayload)} + case "Create": + return &jWTAuthCreatePayload{payload: info.RawPayload().(*CreatePayload)} + case "Stream": + switch pay := info.RawPayload().(type) { + case *StreamEndpointInput: + return &jWTAuthStreamPayload{payload: pay.Payload} + default: + return &jWTAuthStreamPayload{payload: pay.(*StreamPayload)} + } + default: + return nil + } +} + +// Service returns the name of the service handling the request. +func (info *RequestAuditInfo) Service() string { + return info.service +} + +// Method returns the name of the method handling the request. +func (info *RequestAuditInfo) Method() string { + return info.method +} + +// CallType returns the type of call the interceptor is handling. +func (info *RequestAuditInfo) CallType() goa.InterceptorCallType { + return info.callType +} + +// RawPayload returns the raw payload of the request. +func (info *RequestAuditInfo) RawPayload() any { + return info.rawPayload +} + +// Result returns a type-safe accessor for the method result. +func (info *RequestAuditInfo) Result(res any) RequestAuditResult { + switch info.Method() { + case "Get": + return &requestAuditGetResult{result: res.(*GetResult)} + case "Create": + return &requestAuditCreateResult{result: res.(*CreateResult)} + default: + return nil + } +} + +// Service returns the name of the service handling the request. +func (info *SetDeadlineInfo) Service() string { + return info.service +} + +// Method returns the name of the method handling the request. +func (info *SetDeadlineInfo) Method() string { + return info.method +} + +// CallType returns the type of call the interceptor is handling. +func (info *SetDeadlineInfo) CallType() goa.InterceptorCallType { + return info.callType +} + +// RawPayload returns the raw payload of the request. +func (info *SetDeadlineInfo) RawPayload() any { + return info.rawPayload +} + +// Service returns the name of the service handling the request. +func (info *TraceBidirectionalStreamInfo) Service() string { + return info.service +} + +// Method returns the name of the method handling the request. +func (info *TraceBidirectionalStreamInfo) Method() string { + return info.method +} + +// CallType returns the type of call the interceptor is handling. +func (info *TraceBidirectionalStreamInfo) CallType() goa.InterceptorCallType { + return info.callType +} + +// RawPayload returns the raw payload of the request. +func (info *TraceBidirectionalStreamInfo) RawPayload() any { + return info.rawPayload +} + +// ClientStreamingPayload returns a type-safe accessor for the method streaming payload for a client-side interceptor. +func (info *TraceBidirectionalStreamInfo) ClientStreamingPayload() TraceBidirectionalStreamStreamingPayload { + return &traceBidirectionalStreamStreamStreamingPayload{payload: info.RawPayload().(*StreamStreamingPayload)} +} + +// ClientStreamingResult returns a type-safe accessor for the method streaming result for a client-side interceptor. +func (info *TraceBidirectionalStreamInfo) ClientStreamingResult(res any) TraceBidirectionalStreamStreamingResult { + return &traceBidirectionalStreamStreamStreamingResult{result: res.(*StreamResult)} +} + +// ServerStreamingPayload returns a type-safe accessor for the method streaming payload for a server-side interceptor. +func (info *TraceBidirectionalStreamInfo) ServerStreamingPayload(pay any) TraceBidirectionalStreamStreamingPayload { + return &traceBidirectionalStreamStreamStreamingPayload{payload: pay.(*StreamStreamingPayload)} +} + +// ServerStreamingResult returns a type-safe accessor for the method streaming result for a server-side interceptor. +func (info *TraceBidirectionalStreamInfo) ServerStreamingResult() TraceBidirectionalStreamStreamingResult { + return &traceBidirectionalStreamStreamStreamingResult{result: info.RawPayload().(*StreamResult)} +} + +// Service returns the name of the service handling the request. +func (info *TraceRequestInfo) Service() string { + return info.service +} + +// Method returns the name of the method handling the request. +func (info *TraceRequestInfo) Method() string { + return info.method +} + +// CallType returns the type of call the interceptor is handling. +func (info *TraceRequestInfo) CallType() goa.InterceptorCallType { + return info.callType +} + +// RawPayload returns the raw payload of the request. +func (info *TraceRequestInfo) RawPayload() any { + return info.rawPayload +} + +// Payload returns a type-safe accessor for the method payload. +func (info *TraceRequestInfo) Payload() TraceRequestPayload { + switch info.Method() { + case "Get": + return &traceRequestGetPayload{payload: info.RawPayload().(*GetPayload)} + case "Create": + return &traceRequestCreatePayload{payload: info.RawPayload().(*CreatePayload)} + default: + return nil + } +} + +// Private implementation methods + +func (p *cacheGetPayload) RecordID() UUID { + return p.payload.RecordID +} +func (r *cacheGetResult) SetCachedAt(v string) { + r.result.CachedAt = &v +} + +func (p *jWTAuthGetPayload) Auth() string { + return p.payload.Auth +} +func (p *jWTAuthGetPayload) TenantID() UUID { + return p.payload.TenantID +} +func (p *jWTAuthCreatePayload) Auth() string { + return p.payload.Auth +} +func (p *jWTAuthCreatePayload) TenantID() UUID { + return p.payload.TenantID +} +func (p *jWTAuthStreamPayload) Auth() string { + return p.payload.Auth +} +func (p *jWTAuthStreamPayload) TenantID() UUID { + return p.payload.TenantID +} + +func (r *requestAuditGetResult) Status() int { + return r.result.Status +} +func (r *requestAuditGetResult) SetProcessedAt(v string) { + r.result.ProcessedAt = v +} +func (r *requestAuditGetResult) SetDuration(v int) { + r.result.Duration = v +} +func (r *requestAuditCreateResult) Status() int { + return r.result.Status +} +func (r *requestAuditCreateResult) SetProcessedAt(v string) { + r.result.ProcessedAt = v +} +func (r *requestAuditCreateResult) SetDuration(v int) { + r.result.Duration = v +} + +func (p *traceBidirectionalStreamStreamStreamingPayload) TraceID() UUID { + if p.payload.TraceID == nil { + var zero UUID + return zero + } + return *p.payload.TraceID +} +func (p *traceBidirectionalStreamStreamStreamingPayload) SpanID() UUID { + if p.payload.SpanID == nil { + var zero UUID + return zero + } + return *p.payload.SpanID +} +func (p *traceBidirectionalStreamStreamStreamingPayload) SetTraceID(v UUID) { + p.payload.TraceID = &v +} +func (p *traceBidirectionalStreamStreamStreamingPayload) SetSpanID(v UUID) { + p.payload.SpanID = &v +} +func (r *traceBidirectionalStreamStreamStreamingResult) TraceID() UUID { + if r.result.TraceID == nil { + var zero UUID + return zero + } + return *r.result.TraceID +} +func (r *traceBidirectionalStreamStreamStreamingResult) SpanID() UUID { + if r.result.SpanID == nil { + var zero UUID + return zero + } + return *r.result.SpanID +} +func (r *traceBidirectionalStreamStreamStreamingResult) SetTraceID(v UUID) { + r.result.TraceID = &v +} +func (r *traceBidirectionalStreamStreamStreamingResult) SetSpanID(v UUID) { + r.result.SpanID = &v +} + +func (p *traceRequestGetPayload) SetTraceID(v UUID) { + p.payload.TraceID = &v +} +func (p *traceRequestGetPayload) SetSpanID(v UUID) { + p.payload.SpanID = &v +} +func (p *traceRequestCreatePayload) SetTraceID(v UUID) { + p.payload.TraceID = &v +} +func (p *traceRequestCreatePayload) SetSpanID(v UUID) { + p.payload.SpanID = &v +} diff --git a/interceptors/go.mod b/interceptors/go.mod new file mode 100644 index 000000000..86fa3d5cf --- /dev/null +++ b/interceptors/go.mod @@ -0,0 +1,36 @@ +module goa.design/examples/interceptors + +go 1.23 + +require ( + github.com/google/uuid v1.6.0 + github.com/gorilla/websocket v1.5.3 + goa.design/clue v1.0.7 + goa.design/goa/v3 v3.20.0-rc1.0.20250218194113-0094132f1d01 + google.golang.org/grpc v1.70.0 + google.golang.org/protobuf v1.36.4 +) + +require ( + github.com/aws/smithy-go v1.22.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 // indirect + github.com/go-chi/chi/v5 v5.2.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/kr/pretty v0.1.0 // indirect + github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.10.0 // indirect + go.opentelemetry.io/otel v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/term v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/tools v0.29.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/interceptors/go.sum b/interceptors/go.sum new file mode 100644 index 000000000..ca109fee0 --- /dev/null +++ b/interceptors/go.sum @@ -0,0 +1,77 @@ +github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= +github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +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= +github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= +github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598/go.mod h1:0FpDmbrt36utu8jEmeU05dPC9AB5tsLYVVi+ZHfyuwI= +github.com/go-chi/chi/v5 v5.2.0 h1:Aj1EtB0qR2Rdo2dG4O94RIU35w2lvQSj6BRA4+qwFL0= +github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= +github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= +github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= +github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0 h1:UGZ1QwZWY67Z6BmckTU+9Rxn04m2bD3gD6Mk0OIOCPk= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0/go.mod h1:fcwWuDuaObkkChiDlhEpSq9+X1C0omv+s5mBtToAQ64= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= +go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +goa.design/clue v1.0.7 h1:Z0qhUTvMMo2C7bxn9X7Wt4DXahGMdYuIg7pr3F+iLOs= +goa.design/clue v1.0.7/go.mod h1:z9vhVyNCV02Aggr20KilzR/QQigD/wuz+0uGvWr4MYk= +goa.design/goa/v3 v3.20.0-rc1.0.20250218194113-0094132f1d01 h1:UzfxlJabMk5IdC37hM+0WErBuCok/8egu1gncoLL0Bs= +goa.design/goa/v3 v3.20.0-rc1.0.20250218194113-0094132f1d01/go.mod h1:YFTHST5DUS9dPdL42h3o/Wtdb9VU6tKbytBxc5hOeLU= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= +golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= +google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/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-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/interceptors/interceptors.go b/interceptors/interceptors.go new file mode 100644 index 000000000..9ba420ea2 --- /dev/null +++ b/interceptors/interceptors.go @@ -0,0 +1,152 @@ +package interceptorsapi + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/google/uuid" + "goa.design/clue/log" + + interceptors "goa.design/examples/interceptors/gen/interceptors" +) + +// interceptors service example implementation. +// The example methods log the requests and return zero values. +type interceptorssrvc struct { + records sync.Map +} + +// ReturnUnavailable is a hard-coded UUID used to demonstrate the client-side Retry +// interceptor by simulating a temporary service unavailability +const ReturnUnavailable interceptors.UUID = "00000000-0000-0000-0000-000000000000" + +// Hang is a hard-coded UUID used to demonstrate the Deadline interceptor +// by simulating a slow response that should trigger timeouts +const Hang interceptors.UUID = "00000000-0000-0000-0000-000000000001" + +// NewInterceptors returns the interceptors service implementation. +func NewInterceptors() interceptors.Service { + return &interceptorssrvc{} +} + +// Get retrieves a record by ID demonstrating various interceptor scenarios: +// - ReturnUnavailable: Triggers the retry interceptor with a 503 response +// - Hang: Triggers the deadline interceptor by delaying the response +// - Other IDs: Normal flow demonstrating tenant and logging interceptors +func (s *interceptorssrvc) Get(ctx context.Context, p *interceptors.GetPayload) (*interceptors.GetResult, error) { + log.Printf(ctx, "[Get] ID: %s", p.RecordID) + + switch p.RecordID { + case ReturnUnavailable: + return nil, interceptors.MakeUnavailable(fmt.Errorf("service temporarily unavailable - retry should handle this")) + case Hang: + log.Printf(ctx, "[Get] Simulating slow response for deadline demonstration") + time.Sleep(10 * time.Second) + } + + record, ok := s.records.Load(p.RecordID) + if !ok { + return nil, interceptors.MakeNotFound(fmt.Errorf("record with ID %s not found", p.RecordID)) + } + result := record.(*interceptors.CreateResult) + return &interceptors.GetResult{ + ID: result.ID, + Value: result.Value, + Tenant: result.Tenant, + Status: 200, + }, nil +} + +// Create generates a new record demonstrating the logging and tenant interceptors. +// It shows how interceptors can access and utilize context values (like tenant ID) +// throughout the request lifecycle. +func (s *interceptorssrvc) Create(ctx context.Context, p *interceptors.CreatePayload) (*interceptors.CreateResult, error) { + log.Printf(ctx, "[Create] Creating record for tenant: %s with value: %s", p.TenantID, p.Value) + id := interceptors.UUID(uuid.New().String()) + result := &interceptors.CreateResult{ + ID: id, + Value: fmt.Sprintf("Created record with value: %s", p.Value), + Tenant: string(p.TenantID), + Status: 201, + } + + s.records.Store(id, result) + log.Printf(ctx, "[Create] Successfully created record with ID: %s", id) + + return result, nil +} + +// Stream demonstrates the streaming interceptor by sending a stream of records and accepting new records to +// be created. It shows how interceptors can access and utilize context values (like trace ID and span ID) +// throughout the request lifecycle. +func (s *interceptorssrvc) Stream(ctx context.Context, p *interceptors.StreamPayload, stream interceptors.StreamServerStream) error { + log.Printf(ctx, "[Stream] Streaming records for tenant: %s", p.TenantID) + defer stream.Close() + + var err error + s.records.Range(func(key, value any) bool { + result := value.(*interceptors.CreateResult) + log.Printf(ctx, "[Stream] Sending stream result: %s", result.ID) + err = stream.SendWithContext(ctx, &interceptors.StreamResult{ + ID: result.ID, + Value: result.Value, + Tenant: result.Tenant, + Status: 200, + }) + return err == nil + }) + if err != nil { + log.Printf(ctx, "[Stream] Error sending stream result: %s", err) + return err + } + + errCh := make(chan error) + go func() { + for { + select { + case <-ctx.Done(): + return + default: + payload, err := stream.RecvWithContext(ctx) + if err != nil { + log.Printf(ctx, "[Stream] Error receiving stream payload: %s", err) + errCh <- err + return + } + log.Printf(ctx, "[Stream] Received stream payload: %s", payload.ID) + + result := &interceptors.CreateResult{ + ID: payload.ID, + Value: payload.Value, + Tenant: string(p.TenantID), + Status: 201, + } + + s.records.Store(result.ID, result) + log.Printf(ctx, "[Stream] Sending stream result: %s", result.ID) + err = stream.SendWithContext(ctx, &interceptors.StreamResult{ + ID: result.ID, + Value: result.Value, + Tenant: result.Tenant, + Status: 200, + }) + if err != nil { + log.Printf(ctx, "[Stream] Error sending stream result: %s", err) + errCh <- err + return + } + } + } + }() + for { + select { + case <-ctx.Done(): + log.Printf(ctx, "[Stream] Context done") + return nil + case err := <-errCh: + return err + } + } +} diff --git a/interceptors/interceptors/interceptors_client.go b/interceptors/interceptors/interceptors_client.go new file mode 100644 index 000000000..6fc8c739b --- /dev/null +++ b/interceptors/interceptors/interceptors_client.go @@ -0,0 +1,64 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors example client interceptors +// +// Command: +// $ goa example goa.design/examples/interceptors/design + +package interceptors + +import ( + "context" + + "goa.design/clue/log" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goa "goa.design/goa/v3/pkg" +) + +// InterceptorsClientInterceptors implements the client interceptors for the interceptors service. +type InterceptorsClientInterceptors struct { +} + +// NewInterceptorsClientInterceptors creates a new client interceptor for the interceptors service. +func NewInterceptorsClientInterceptors() *InterceptorsClientInterceptors { + return &InterceptorsClientInterceptors{} +} + +// Client-side interceptor which writes the tenant ID to the signed JWT +// contained in the Authorization header +func (i *InterceptorsClientInterceptors) EncodeTenant(ctx context.Context, info *interceptors.EncodeTenantInfo, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[EncodeTenant] Sending request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[EncodeTenant] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[EncodeTenant] Received response: %v", resp) + return resp, nil +} + +// Client-side interceptor which implements smart retry logic with exponential +// backoff +func (i *InterceptorsClientInterceptors) Retry(ctx context.Context, info *interceptors.RetryInfo, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[Retry] Sending request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[Retry] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[Retry] Received response: %v", resp) + return resp, nil +} + +// Server-side and client-side interceptor that adds trace context to the +// bidirectional stream payload +func (i *InterceptorsClientInterceptors) TraceBidirectionalStream(ctx context.Context, info *interceptors.TraceBidirectionalStreamInfo, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[TraceBidirectionalStream] Sending request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[TraceBidirectionalStream] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[TraceBidirectionalStream] Received response: %v", resp) + return resp, nil +} diff --git a/interceptors/interceptors/interceptors_server.go b/interceptors/interceptors/interceptors_server.go new file mode 100644 index 000000000..72fd1dbd3 --- /dev/null +++ b/interceptors/interceptors/interceptors_server.go @@ -0,0 +1,100 @@ +// Code generated by goa v3.19.1, DO NOT EDIT. +// +// interceptors example server interceptors +// +// Command: +// $ goa example goa.design/examples/interceptors/design + +package interceptors + +import ( + "context" + + "goa.design/clue/log" + interceptors "goa.design/examples/interceptors/gen/interceptors" + goa "goa.design/goa/v3/pkg" +) + +// InterceptorsServerInterceptors implements the server interceptor for the interceptors service. +type InterceptorsServerInterceptors struct { +} + +// NewInterceptorsServerInterceptors creates a new server interceptor for the interceptors service. +func NewInterceptorsServerInterceptors() *InterceptorsServerInterceptors { + return &InterceptorsServerInterceptors{} +} + +// Server-side interceptor which implements a transparent cache for loaded +// records +func (i *InterceptorsServerInterceptors) Cache(ctx context.Context, info *interceptors.CacheInfo, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[Cache] Processing request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[Cache] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[Cache] Response: %v", resp) + return resp, nil +} + +// Server-side interceptor that validates JWT token and tenant ID +func (i *InterceptorsServerInterceptors) JWTAuth(ctx context.Context, info *interceptors.JWTAuthInfo, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[JWTAuth] Processing request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[JWTAuth] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[JWTAuth] Response: %v", resp) + return resp, nil +} + +// Server-side interceptor that provides comprehensive request/response audit +// logging +func (i *InterceptorsServerInterceptors) RequestAudit(ctx context.Context, info *interceptors.RequestAuditInfo, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[RequestAudit] Processing request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[RequestAudit] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[RequestAudit] Response: %v", resp) + return resp, nil +} + +// Server-side interceptor which sets the context deadline for the request +func (i *InterceptorsServerInterceptors) SetDeadline(ctx context.Context, info *interceptors.SetDeadlineInfo, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[SetDeadline] Processing request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[SetDeadline] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[SetDeadline] Response: %v", resp) + return resp, nil +} + +// Server-side and client-side interceptor that adds trace context to the +// bidirectional stream payload +func (i *InterceptorsServerInterceptors) TraceBidirectionalStream(ctx context.Context, info *interceptors.TraceBidirectionalStreamInfo, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[TraceBidirectionalStream] Processing request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[TraceBidirectionalStream] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[TraceBidirectionalStream] Response: %v", resp) + return resp, nil +} + +// Server-side interceptor that adds trace context to the request payload +func (i *InterceptorsServerInterceptors) TraceRequest(ctx context.Context, info *interceptors.TraceRequestInfo, next goa.Endpoint) (any, error) { + log.Printf(ctx, "[TraceRequest] Processing request: %v", info.RawPayload()) + resp, err := next(ctx, info.RawPayload()) + if err != nil { + log.Printf(ctx, "[TraceRequest] Error: %v", err) + return nil, err + } + log.Printf(ctx, "[TraceRequest] Response: %v", resp) + return resp, nil +} diff --git a/interceptors/run-service.sh b/interceptors/run-service.sh new file mode 100755 index 000000000..7739042e2 --- /dev/null +++ b/interceptors/run-service.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -e + +echo "Building interceptors service..." +go build -o bin/interceptors ./cmd/interceptors +go build -o bin/interceptors-cli ./cmd/interceptors-cli + +echo "Starting interceptors service..." +./bin/interceptors --http-port=8088 & +SERVICE_PID=$! + +# Ensure we kill the service when the script exits +trap "kill $SERVICE_PID" EXIT + +echo "Service is running on http://localhost:8088" +echo "Press Ctrl+C to stop the service" + +# Keep the script running +wait $SERVICE_PID diff --git a/multipart/Makefile b/multipart/Makefile index 0382e8064..e648e30e5 100644 --- a/multipart/Makefile +++ b/multipart/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=multipart - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! - -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" +# Makefile for Goa v3 multipart example -test: - @echo TESTING... - @go test ./... > /dev/null +APP=resume -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../common.mk diff --git a/multipart/go.mod b/multipart/go.mod index f4e1a2b7b..6825f8c0b 100644 --- a/multipart/go.mod +++ b/multipart/go.mod @@ -13,7 +13,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/multipart/go.sum b/multipart/go.sum index 4a6d9c950..e77c6890c 100644 --- a/multipart/go.sum +++ b/multipart/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -12,15 +13,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -36,7 +40,7 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/security/hierarchy/Makefile b/security/hierarchy/Makefile index 5348fe204..30542ad20 100644 --- a/security/hierarchy/Makefile +++ b/security/hierarchy/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=hierarchy - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 security hierarchy example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=hierarchy -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../../common.mk diff --git a/security/hierarchy/go.mod b/security/hierarchy/go.mod index 57b7c6ac9..92ae170af 100644 --- a/security/hierarchy/go.mod +++ b/security/hierarchy/go.mod @@ -13,7 +13,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/security/hierarchy/go.sum b/security/hierarchy/go.sum index 4a6d9c950..e77c6890c 100644 --- a/security/hierarchy/go.sum +++ b/security/hierarchy/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -12,15 +13,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -36,7 +40,7 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/security/multiauth/Makefile b/security/multiauth/Makefile index a626415b5..7ce30f5ff 100644 --- a/security/multiauth/Makefile +++ b/security/multiauth/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=multi_auth - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 security multiauth example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=multi_auth -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../../common.mk diff --git a/security/multiauth/go.mod b/security/multiauth/go.mod index 80e7e4bac..623087c63 100644 --- a/security/multiauth/go.mod +++ b/security/multiauth/go.mod @@ -18,7 +18,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/security/multiauth/go.sum b/security/multiauth/go.sum index fa050d7cb..338e8f4e6 100644 --- a/security/multiauth/go.sum +++ b/security/multiauth/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -20,15 +21,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -64,7 +68,7 @@ google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40Rmc 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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/streaming/Makefile b/streaming/Makefile index 00a0b41ce..8740122de 100644 --- a/streaming/Makefile +++ b/streaming/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=chatter - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 streaming example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=chatter -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../common.mk diff --git a/streaming/go.mod b/streaming/go.mod index 9f27b7eb3..50261e3e8 100644 --- a/streaming/go.mod +++ b/streaming/go.mod @@ -18,7 +18,7 @@ require ( github.com/go-chi/chi/v5 v5.2.1 // indirect github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/streaming/go.sum b/streaming/go.sum index fa050d7cb..338e8f4e6 100644 --- a/streaming/go.sum +++ b/streaming/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -20,15 +21,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -64,7 +68,7 @@ google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40Rmc 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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tracing/cmd/calc/grpc.go b/tracing/cmd/calc/grpc.go index 0cf9c680c..ff28d56d6 100644 --- a/tracing/cmd/calc/grpc.go +++ b/tracing/cmd/calc/grpc.go @@ -18,7 +18,7 @@ import ( // handleGRPCServer starts configures and starts a gRPC server on the given // URL. It shuts down the server if any error is received in the error channel. -func handleGRPCServer(ctx context.Context, u *url.URL, calcEndpoints *calcsvc.Endpoints, wg *sync.WaitGroup, errc chan error, logger *log.Logger, debug bool, daemon string) { +func handleGRPCServer(ctx context.Context, u *url.URL, calcEndpoints *calcsvc.Endpoints, wg *sync.WaitGroup, errc chan error, logger *log.Logger, _ bool, daemon string) { // Setup goa log adapter. var ( diff --git a/tracing/cmd/calc/main.go b/tracing/cmd/calc/main.go index 1f872721f..e1a8de160 100644 --- a/tracing/cmd/calc/main.go +++ b/tracing/cmd/calc/main.go @@ -43,7 +43,7 @@ func main() { calcSvc calcsvc.Service ) { - calcSvc = calc.NewCalc(logger) + calcSvc = calc.NewCalc() } // Wrap the services in endpoints that can be invoked from other services diff --git a/tracing/go.mod b/tracing/go.mod index 584064fe7..484da8963 100644 --- a/tracing/go.mod +++ b/tracing/go.mod @@ -1,23 +1,24 @@ module goa.design/examples/tracing -go 1.21.3 +go 1.22.7 + +toolchain go1.23.3 require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 goa.design/examples/basic v0.0.0-20231014231032-46da41257452 - goa.design/goa/v3 v3.13.2 - google.golang.org/grpc v1.58.3 + goa.design/goa/v3 v3.19.1 + google.golang.org/grpc v1.68.0 ) require ( - github.com/go-chi/chi/v5 v5.0.10 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/uuid v1.3.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect + github.com/go-chi/chi/v5 v5.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/pkg/errors v0.9.1 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/net v0.31.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/protobuf v1.35.1 // indirect ) diff --git a/tracing/go.sum b/tracing/go.sum index 612a16e2d..bf53d4a03 100644 --- a/tracing/go.sum +++ b/tracing/go.sum @@ -11,8 +11,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -22,17 +21,11 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -55,8 +48,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -65,8 +57,7 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= goa.design/examples/basic v0.0.0-20231014231032-46da41257452 h1:7jwVE2EZoOLCqena3MSY3ydXwo96D/xieaoBTt20kqY= goa.design/examples/basic v0.0.0-20231014231032-46da41257452/go.mod h1:VgNWbu1m4GXqe4EahlPZbDsIA0ynKoyP2t1cdUkSRHg= -goa.design/goa/v3 v3.13.2 h1:RclNIpo7891ZqGRVO4fpBjT7Fs7LjBNm78i8J41KHrI= -goa.design/goa/v3 v3.13.2/go.mod h1:VvZsuC8CSIUQOHVqk6Ep3MFSFz21OjOv87UPqCHiB94= +goa.design/goa/v3 v3.19.1 h1:jpV3LEy7YANzPMwm++Lu17RoThRJgXrPxdEM0A1nlOE= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -85,8 +76,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -99,12 +89,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -123,19 +111,14 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -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/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= 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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/tus/Makefile b/tus/Makefile index 6066a8bac..2f1245697 100644 --- a/tus/Makefile +++ b/tus/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=upload - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 tus example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=upload -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../common.mk diff --git a/tus/go.mod b/tus/go.mod index ce1938b95..0a6f0e854 100644 --- a/tus/go.mod +++ b/tus/go.mod @@ -16,7 +16,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/tus/go.sum b/tus/go.sum index ccefce09b..7b0e9db9c 100644 --- a/tus/go.sum +++ b/tus/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -12,17 +13,23 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -38,7 +45,7 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/upload_download/Makefile b/upload_download/Makefile index f9cf3cfc8..42f9017ca 100644 --- a/upload_download/Makefile +++ b/upload_download/Makefile @@ -1,101 +1,7 @@ #! /usr/bin/make # -# Makefile for Goa examples -# -# Targets: -# - "depend" retrieves the Go packages needed to run the linter and tests -# - "gen" invokes the "goa" tool to generate the examples source code -# - "build" compiles the example microservices and client CLIs -# - "clean" deletes the output of "build" -# - "lint" runs the linter and checks the code format using goimports -# - "test" runs the tests -# -# Meta targets: -# - "all" is the default target, it runs all the targets in the order above. -# -GO_FILES=$(shell find . -type f -name '*.go') -MODULE=$(shell go list -m) -APP=upload_download - -# Only list test and build dependencies -# Standard dependencies are installed via go get -DEPEND=\ - github.com/hashicorp/go-getter \ - github.com/cheggaaa/pb \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/golang/protobuf/proto \ - goa.design/goa/... \ - golang.org/x/lint/golint \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck - -.phony: all depend lint test build clean - -all: gen lint test - @echo DONE! +# Makefile for Goa v3 upload/download example -# Install protoc -GOOS=$(shell go env GOOS) -PROTOC_VERSION=3.6.1 -ifeq ($(GOOS),linux) -PROTOC=protoc-$(PROTOC_VERSION)-linux-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin -else - ifeq ($(GOOS),darwin) -PROTOC=protoc-$(PROTOC_VERSION)-osx-x86_64 -PROTOC_EXEC=$(PROTOC)/bin/protoc -GOBIN=$(GOPATH)/bin - else - ifeq ($(GOOS),windows) -PROTOC=protoc-$(PROTOC_VERSION)-win32 -PROTOC_EXEC="$(PROTOC)\bin\protoc.exe" -GOBIN="$(GOPATH)\bin" - endif - endif -endif -depend: - @echo INSTALLING DEPENDENCIES... - @go get -v $(DEPEND) - @go install github.com/hashicorp/go-getter/cmd/go-getter && \ - go-getter https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC).zip $(PROTOC) && \ - cp $(PROTOC_EXEC) $(GOBIN) && \ - rm -r $(PROTOC) - @go install github.com/golang/protobuf/protoc-gen-go - @go get -t -v ./... - -lint: - @echo LINTING CODE... - @if [ "`goimports -l $(GO_FILES) | grep -v .pb.go | tee /dev/stderr`" ]; then \ - echo "^ - Repo contains improperly formatted go files" && echo && exit 1; \ - fi - @if [ "`staticcheck ./... | grep -v ".pb.go" | tee /dev/stderr`" ]; then \ - echo "^ - staticcheck errors!" && echo && exit 1; \ - fi - -.PHONY: gen -gen: - @# NOTE: not all command line tools are generated - @echo GENERATING CODE... - @goa gen "$(MODULE)/design" && \ - goa example "$(MODULE)/design" - -build: - @go build "./cmd/$(APP)" && go build "./cmd/$(APP)-cli" - -clean: - @rm -rf "./cmd/$(APP)" "./cmd/$(APP)-cli" - -test: - @echo TESTING... - @go test ./... > /dev/null +APP=upload_download -check-freshness: - @if [ "`git diff | wc -l`" -gt "0" ]; then \ - echo "[ERROR] generated code not in-sync with design:"; \ - echo; \ - git status -s; \ - git --no-pager diff; \ - echo; \ - exit 1; \ - fi +include ../common.mk diff --git a/upload_download/go.mod b/upload_download/go.mod index ca660f871..37749822b 100644 --- a/upload_download/go.mod +++ b/upload_download/go.mod @@ -13,7 +13,7 @@ require ( github.com/gohugoio/hashstructure v0.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.10.0 // indirect diff --git a/upload_download/go.sum b/upload_download/go.sum index 4a6d9c950..e77c6890c 100644 --- a/upload_download/go.sum +++ b/upload_download/go.sum @@ -1,3 +1,4 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 h1:MGKhKyiYrvMDZsmLR/+RGffQSXwEkXgfLSA08qDn9AI= @@ -12,15 +13,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d h1:Zj+PHjnhRYWBK6RqCDBcAhLXoi3TzC27Zad/Vn+gnVQ= github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d/go.mod h1:WZy8Q5coAB1zhY9AOBJP0O6J4BuDfbupUDavKY+I3+s= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b h1:3E44bLeN8uKYdfQqVQycPnaVviZdBLbizFhU49mtbe4= github.com/manveru/gobdd v0.0.0-20131210092515-f1a17fdd710b/go.mod h1:Bj8LjjP0ReT1eKt5QlKjwgi5AFm5mI6O1A2G4ChI0Ag= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= @@ -36,7 +40,7 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=