diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..412624400a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,50 @@ +name: CI + +on: + push: + pull_request: + +jobs: + style: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.22.x' + + - name: Ensure module deps + run: go mod download + + - name: Check go fmt + shell: bash + run: | + set -euo pipefail + fmt="$(gofmt -l .)" + if [[ -n "$fmt" ]]; then + echo "The following files are not gofmt-ed:" + echo "$fmt" + exit 1 + fi + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Run staticcheck + run: $(go env GOPATH)/bin/staticcheck ./... + + - name: Run unit tests + run: go test ./... + + # 👇 Assignment bits + - name: Install gosec + run: go install github.com/securego/gosec/v2/cmd/gosec@latest + + - name: Run gosec (expect failure first time) + # gosec exits non-zero on findings, which is what the checkpoint wants + run: $(go env GOPATH)/bin/gosec ./... + + diff --git a/README.md b/README.md index c2bec0368b..b0b24991dc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![Tests](https://github.com/KaliBytes/learn-cicd-starter/actions/workflows/ci.yml/badge.svg) + # learn-cicd-starter (Notely) This repo contains the starter code for the "Notely" application for the "Learn CICD" course on [Boot.dev](https://boot.dev). @@ -21,3 +23,4 @@ go build -o notely && ./notely *This starts the server in non-database mode.* It will serve a simple webpage at `http://localhost:8080`. You do *not* need to set up a database or any interactivity on the webpage yet. Instructions for that will come later in the course! + diff --git a/go.mod b/go.mod index 09e04f9c12..3170e8bf4a 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/bootdotdev/learn-cicd-starter go 1.22 require ( - github.com/go-chi/chi v1.5.4 + github.com/go-chi/chi/v5 v5.2.3 github.com/go-chi/cors v1.2.1 github.com/google/uuid v1.3.0 github.com/joho/godotenv v1.5.1 diff --git a/go.sum b/go.sum index e3c6163bd0..524f028795 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= -github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= +github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= +github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -26,8 +26,10 @@ github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/E github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.4.0/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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -37,6 +39,7 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= @@ -46,8 +49,10 @@ github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475 h1:6Pf github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475/go.mod h1:20nXSmcf0nAscrzqsXeC2/tA3KkV2eCiJqYuyAgl+ss= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -64,14 +69,17 @@ golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfU golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= diff --git a/internal/database/models.go b/internal/database/models.go index 70333ba1ab..050e28b38b 100644 --- a/internal/database/models.go +++ b/internal/database/models.go @@ -4,8 +4,6 @@ package database -import () - type Note struct { ID string CreatedAt string diff --git a/json.go b/json.go index 1e6e7985e1..b4d23670cb 100644 --- a/json.go +++ b/json.go @@ -13,9 +13,11 @@ func respondWithError(w http.ResponseWriter, code int, msg string, logErr error) if code > 499 { log.Printf("Responding with 5XX error: %s", msg) } + type errorResponse struct { Error string `json:"error"` } + respondWithJSON(w, code, errorResponse{ Error: msg, }) @@ -25,10 +27,14 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { w.Header().Set("Content-Type", "application/json") dat, err := json.Marshal(payload) if err != nil { - log.Printf("Error marshalling JSON: %s", err) + log.Printf("Error marshalling JSON: %v", err) w.WriteHeader(500) return } + w.WriteHeader(code) - w.Write(dat) + + if _, err := w.Write(dat); err != nil { + log.Printf("error writing response body: %v", err) + } } diff --git a/main.go b/main.go index 19d7366c5f..27914651ab 100644 --- a/main.go +++ b/main.go @@ -7,8 +7,9 @@ import ( "log" "net/http" "os" + "time" - "github.com/go-chi/chi" + "github.com/go-chi/chi/v5" "github.com/go-chi/cors" "github.com/joho/godotenv" @@ -89,8 +90,12 @@ func main() { router.Mount("/v1", v1Router) srv := &http.Server{ - Addr: ":" + port, - Handler: router, + Addr: ":" + port, + Handler: router, + ReadHeaderTimeout: 10 * time.Second, + ReadTimeout: 15 * time.Second, + WriteTimeout: 15 * time.Second, + IdleTimeout: 60 * time.Second, } log.Printf("Serving on port: %s\n", port) diff --git a/vendor/github.com/go-chi/chi/.gitignore b/vendor/github.com/go-chi/chi/v5/.gitignore similarity index 100% rename from vendor/github.com/go-chi/chi/.gitignore rename to vendor/github.com/go-chi/chi/v5/.gitignore diff --git a/vendor/github.com/go-chi/chi/CHANGELOG.md b/vendor/github.com/go-chi/chi/v5/CHANGELOG.md similarity index 84% rename from vendor/github.com/go-chi/chi/CHANGELOG.md rename to vendor/github.com/go-chi/chi/v5/CHANGELOG.md index 7dd079157f..25b45b9743 100644 --- a/vendor/github.com/go-chi/chi/CHANGELOG.md +++ b/vendor/github.com/go-chi/chi/v5/CHANGELOG.md @@ -1,5 +1,77 @@ # Changelog +## v5.0.12 (2024-02-16) + +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.11...v5.0.12 + + +## v5.0.11 (2023-12-19) + +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.10...v5.0.11 + + +## v5.0.10 (2023-07-13) + +- Fixed small edge case in tests of v5.0.9 for older Go versions +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.9...v5.0.10 + + +## v5.0.9 (2023-07-13) + +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.8...v5.0.9 + + +## v5.0.8 (2022-12-07) + +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.7...v5.0.8 + + +## v5.0.7 (2021-11-18) + +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.6...v5.0.7 + + +## v5.0.6 (2021-11-15) + +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.5...v5.0.6 + + +## v5.0.5 (2021-10-27) + +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.4...v5.0.5 + + +## v5.0.4 (2021-08-29) + +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.3...v5.0.4 + + +## v5.0.3 (2021-04-29) + +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.2...v5.0.3 + + +## v5.0.2 (2021-03-25) + +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.1...v5.0.2 + + +## v5.0.1 (2021-03-10) + +- Small improvements +- History of changes: see https://github.com/go-chi/chi/compare/v5.0.0...v5.0.1 + + +## v5.0.0 (2021-02-27) + +- chi v5, `github.com/go-chi/chi/v5` introduces the adoption of Go's SIV to adhere to the current state-of-the-tools in Go. +- chi v1.5.x did not work out as planned, as the Go tooling is too powerful and chi's adoption is too wide. + The most responsible thing to do for everyone's benefit is to just release v5 with SIV, so I present to you all, + chi v5 at `github.com/go-chi/chi/v5`. I hope someday the developer experience and ergonomics I've been seeking + will still come to fruition in some form, see https://github.com/golang/go/issues/44550 +- History of changes: see https://github.com/go-chi/chi/compare/v1.5.4...v5.0.0 + + ## v1.5.4 (2021-02-27) - Undo prior retraction in v1.5.3 as we prepare for v5.0.0 release @@ -39,14 +111,14 @@ incremental, with the architecture and api being the same today as it was origin makes chi a pretty easy project to maintain, as well thanks to the many amazing community contributions over the years to who all help make chi better (total of 86 contributors to date -- thanks all!). -Chi has been an labour of love, art and engineering, with the goals to offer beautiful ergonomics, flexibility, performance +Chi has been a labour of love, art and engineering, with the goals to offer beautiful ergonomics, flexibility, performance and simplicity when building HTTP services with Go. I've strived to keep the router very minimal in surface area / code size, and always improving the code wherever possible -- and as of today the `chi` package is just 1082 lines of code (not counting middlewares, which are all optional). As well, I don't have the exact metrics, but from my analysis and email exchanges from companies and developers, chi is used by thousands of projects around the world -- thank you all as there is no better form of joy for me than to have art I had started be helpful and enjoyed by others. And of course I use chi in all of my own projects too :) -For me, the asthetics of chi's code and usage are very important. With the introduction of Go's module support +For me, the aesthetics of chi's code and usage are very important. With the introduction of Go's module support (which I'm a big fan of), chi's past versioning scheme choice to v2, v3 and v4 would mean I'd require the import path of "github.com/go-chi/chi/v4", leading to the lengthy discussion at https://github.com/go-chi/chi/issues/462. Haha, to some, you may be scratching your head why I've spent > 1 year stalling to adopt "/vXX" convention in the import @@ -238,13 +310,13 @@ Cheers all, happy coding! ## v2.0.0-rc1 (2016-07-26) -- Huge update! chi v2 is a large refactor targetting Go 1.7+. As of Go 1.7, the popular +- Huge update! chi v2 is a large refactor targeting Go 1.7+. As of Go 1.7, the popular community `"net/context"` package has been included in the standard library as `"context"` and utilized by `"net/http"` and `http.Request` to managing deadlines, cancelation signals and other request-scoped values. We're very excited about the new context addition and are proud to introduce chi v2, a minimal and powerful routing package for building large HTTP services, with zero external dependencies. Chi focuses on idiomatic design and encourages the use of - stdlib HTTP handlers and middlwares. + stdlib HTTP handlers and middlewares. - chi v2 deprecates its `chi.Handler` interface and requires `http.Handler` or `http.HandlerFunc` - chi v2 stores URL routing parameters and patterns in the standard request context: `r.Context()` - chi v2 lower-level routing context is accessible by `chi.RouteContext(r.Context()) *chi.Context`, diff --git a/vendor/github.com/go-chi/chi/CONTRIBUTING.md b/vendor/github.com/go-chi/chi/v5/CONTRIBUTING.md similarity index 58% rename from vendor/github.com/go-chi/chi/CONTRIBUTING.md rename to vendor/github.com/go-chi/chi/v5/CONTRIBUTING.md index c0ac2dfe85..b4a6268d57 100644 --- a/vendor/github.com/go-chi/chi/CONTRIBUTING.md +++ b/vendor/github.com/go-chi/chi/v5/CONTRIBUTING.md @@ -14,7 +14,7 @@ A typical workflow is: -1. [Fork the repository.][fork] [This tip maybe also helpful.][go-fork-tip] +1. [Fork the repository.][fork] 2. [Create a topic branch.][branch] 3. Add tests for your change. 4. Run `go test`. If your tests pass, return to the step 3. @@ -24,8 +24,8 @@ A typical workflow is: 8. [Submit a pull request.][pull-req] [go-install]: https://golang.org/doc/install -[go-fork-tip]: http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html -[fork]: https://help.github.com/articles/fork-a-repo -[branch]: http://learn.github.com/p/branching.html -[git-help]: https://guides.github.com -[pull-req]: https://help.github.com/articles/using-pull-requests +[fork]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo +[branch]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches +[git-help]: https://docs.github.com/en +[pull-req]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests + diff --git a/vendor/github.com/go-chi/chi/LICENSE b/vendor/github.com/go-chi/chi/v5/LICENSE similarity index 100% rename from vendor/github.com/go-chi/chi/LICENSE rename to vendor/github.com/go-chi/chi/v5/LICENSE diff --git a/vendor/github.com/go-chi/chi/Makefile b/vendor/github.com/go-chi/chi/v5/Makefile similarity index 75% rename from vendor/github.com/go-chi/chi/Makefile rename to vendor/github.com/go-chi/chi/v5/Makefile index b96c92dd21..e0f18c7da2 100644 --- a/vendor/github.com/go-chi/chi/Makefile +++ b/vendor/github.com/go-chi/chi/v5/Makefile @@ -1,14 +1,22 @@ +.PHONY: all all: @echo "**********************************************************" @echo "** chi build tool **" @echo "**********************************************************" +.PHONY: test test: go clean -testcache && $(MAKE) test-router && $(MAKE) test-middleware +.PHONY: test-router test-router: go test -race -v . +.PHONY: test-middleware test-middleware: go test -race -v ./middleware + +.PHONY: docs +docs: + npx docsify-cli serve ./docs diff --git a/vendor/github.com/go-chi/chi/README.md b/vendor/github.com/go-chi/chi/v5/README.md similarity index 93% rename from vendor/github.com/go-chi/chi/README.md rename to vendor/github.com/go-chi/chi/v5/README.md index 1b96d360d7..c58a0e20ce 100644 --- a/vendor/github.com/go-chi/chi/README.md +++ b/vendor/github.com/go-chi/chi/v5/README.md @@ -1,7 +1,7 @@ # chi -[![GoDoc Widget]][GoDoc] [![Travis Widget]][Travis] +[![GoDoc Widget]][GoDoc] `chi` is a lightweight, idiomatic and composable router for building Go HTTP services. It's especially good at helping you write large REST API services that are kept maintainable as your @@ -20,7 +20,9 @@ and [docgen](https://github.com/go-chi/docgen). We hope you enjoy it too! ## Install -`go get -u github.com/go-chi/chi` +```sh +go get -u github.com/go-chi/chi/v5 +``` ## Features @@ -30,9 +32,9 @@ and [docgen](https://github.com/go-chi/docgen). We hope you enjoy it too! * **100% compatible with net/http** - use any http or middleware pkg in the ecosystem that is also compatible with `net/http` * **Designed for modular/composable APIs** - middlewares, inline middlewares, route groups and sub-router mounting * **Context control** - built on new `context` package, providing value chaining, cancellations and timeouts -* **Robust** - in production at Pressly, CloudFlare, Heroku, 99Designs, and many others (see [discussion](https://github.com/go-chi/chi/issues/91)) +* **Robust** - in production at Pressly, Cloudflare, Heroku, 99Designs, and many others (see [discussion](https://github.com/go-chi/chi/issues/91)) * **Doc generation** - `docgen` auto-generates routing documentation from your source to JSON or Markdown -* **Go.mod support** - v1.x of chi (starting from v1.5.0), now has go.mod support (see [CHANGELOG](https://github.com/go-chi/chi/blob/master/CHANGELOG.md#v150-2020-11-12---now-with-gomod-support)) +* **Go.mod support** - as of v5, go.mod support (see [CHANGELOG](https://github.com/go-chi/chi/blob/master/CHANGELOG.md)) * **No external dependencies** - plain ol' Go stdlib + net/http @@ -49,8 +51,8 @@ package main import ( "net/http" - "github.com/go-chi/chi" - "github.com/go-chi/chi/middleware" + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" ) func main() { @@ -65,7 +67,7 @@ func main() { **REST Preview:** -Here is a little preview of how routing looks like with chi. Also take a look at the generated routing docs +Here is a little preview of what routing looks like with chi. Also take a look at the generated routing docs in JSON ([routes.json](https://github.com/go-chi/chi/blob/master/_examples/rest/routes.json)) and in Markdown ([routes.md](https://github.com/go-chi/chi/blob/master/_examples/rest/routes.md)). @@ -76,8 +78,8 @@ above, they will show you all the features of chi and serve as a good form of do import ( //... "context" - "github.com/go-chi/chi" - "github.com/go-chi/chi/middleware" + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" ) func main() { @@ -194,7 +196,7 @@ type Router interface { // path, with a fresh middleware stack for the inline-Router. Group(fn func(r Router)) Router - // Route mounts a sub-Router along a `pattern`` string. + // Route mounts a sub-Router along a `pattern` string. Route(pattern string, fn func(r Router)) Router // Mount attaches another http.Handler along ./pattern/* @@ -347,13 +349,14 @@ with `net/http` can be used with chi's mux. | [Logger] | Logs the start and end of each request with the elapsed processing time | | [NoCache] | Sets response headers to prevent clients from caching | | [Profiler] | Easily attach net/http/pprof to your routers | -| [RealIP] | Sets a http.Request's RemoteAddr to either X-Forwarded-For or X-Real-IP | +| [RealIP] | Sets a http.Request's RemoteAddr to either X-Real-IP or X-Forwarded-For | | [Recoverer] | Gracefully absorb panics and prints the stack trace | | [RequestID] | Injects a request ID into the context of each request | | [RedirectSlashes] | Redirect slashes on routing paths | | [RouteHeaders] | Route handling for request headers | | [SetHeader] | Short-hand middleware to set a response header key/value | | [StripSlashes] | Strip slashes on routing paths | +| [Sunset] | Sunset set Deprecation/Sunset header to response | | [Throttle] | Puts a ceiling on the number of concurrent requests | | [Timeout] | Signals to the request context when the timeout deadline is reached | | [URLFormat] | Parse extension from url and put it on request context | @@ -380,6 +383,7 @@ with `net/http` can be used with chi's mux. [RouteHeaders]: https://pkg.go.dev/github.com/go-chi/chi/middleware#RouteHeaders [SetHeader]: https://pkg.go.dev/github.com/go-chi/chi/middleware#SetHeader [StripSlashes]: https://pkg.go.dev/github.com/go-chi/chi/middleware#StripSlashes +[Sunset]: https://pkg.go.dev/github.com/go-chi/chi/v5/middleware#Sunset [Throttle]: https://pkg.go.dev/github.com/go-chi/chi/middleware#Throttle [ThrottleBacklog]: https://pkg.go.dev/github.com/go-chi/chi/middleware#ThrottleBacklog [ThrottleWithOpts]: https://pkg.go.dev/github.com/go-chi/chi/middleware#ThrottleWithOpts @@ -463,22 +467,12 @@ on the duplicated (alloc'd) request and returns it the new request object. This how setting context on a request in Go works. -## Go module support & note on chi's versioning - -* Go.mod support means we reset our versioning starting from v1.5 (see [CHANGELOG](https://github.com/go-chi/chi/blob/master/CHANGELOG.md#v150-2020-11-12---now-with-gomod-support)) -* All older tags are preserved, are backwards-compatible and will "just work" as they -* Brand new systems can run `go get -u github.com/go-chi/chi` as normal, or `go get -u github.com/go-chi/chi@latest` -to install chi, which will install v1.x+ built with go.mod support, starting from v1.5.0. -* For existing projects who want to upgrade to the latest go.mod version, run: `go get -u github.com/go-chi/chi@v1.5.0`, -which will get you on the go.mod version line (as Go's mod cache may still remember v4.x). -* Any breaking changes will bump a "minor" release and backwards-compatible improvements/fixes will bump a "tiny" release. - - ## Credits * Carl Jackson for https://github.com/zenazn/goji * Parts of chi's thinking comes from goji, and chi's middleware package - sources from goji. + sources from [goji](https://github.com/zenazn/goji/tree/master/web/middleware). + * Please see goji's [LICENSE](https://github.com/zenazn/goji/blob/master/LICENSE) (MIT) * Armon Dadgar for https://github.com/armon/go-radix * Contributions: [@VojtechVitek](https://github.com/VojtechVitek) @@ -505,7 +499,7 @@ Copyright (c) 2015-present [Peter Kieltyka](https://github.com/pkieltyka) Licensed under [MIT License](./LICENSE) -[GoDoc]: https://pkg.go.dev/github.com/go-chi/chi?tab=versions +[GoDoc]: https://pkg.go.dev/github.com/go-chi/chi/v5 [GoDoc Widget]: https://godoc.org/github.com/go-chi/chi?status.svg [Travis]: https://travis-ci.org/go-chi/chi [Travis Widget]: https://travis-ci.org/go-chi/chi.svg?branch=master diff --git a/vendor/github.com/go-chi/chi/v5/SECURITY.md b/vendor/github.com/go-chi/chi/v5/SECURITY.md new file mode 100644 index 0000000000..7e937f87f3 --- /dev/null +++ b/vendor/github.com/go-chi/chi/v5/SECURITY.md @@ -0,0 +1,5 @@ +# Reporting Security Issues + +We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions. + +To report a security issue, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/go-chi/chi/security/advisories/new) tab. diff --git a/vendor/github.com/go-chi/chi/chain.go b/vendor/github.com/go-chi/chi/v5/chain.go similarity index 94% rename from vendor/github.com/go-chi/chi/chain.go rename to vendor/github.com/go-chi/chi/v5/chain.go index 88e6846138..a2278414f4 100644 --- a/vendor/github.com/go-chi/chi/chain.go +++ b/vendor/github.com/go-chi/chi/v5/chain.go @@ -10,21 +10,21 @@ func Chain(middlewares ...func(http.Handler) http.Handler) Middlewares { // Handler builds and returns a http.Handler from the chain of middlewares, // with `h http.Handler` as the final handler. func (mws Middlewares) Handler(h http.Handler) http.Handler { - return &ChainHandler{mws, h, chain(mws, h)} + return &ChainHandler{h, chain(mws, h), mws} } // HandlerFunc builds and returns a http.Handler from the chain of middlewares, // with `h http.Handler` as the final handler. func (mws Middlewares) HandlerFunc(h http.HandlerFunc) http.Handler { - return &ChainHandler{mws, h, chain(mws, h)} + return &ChainHandler{h, chain(mws, h), mws} } // ChainHandler is a http.Handler with support for handler composition and // execution. type ChainHandler struct { - Middlewares Middlewares Endpoint http.Handler chain http.Handler + Middlewares Middlewares } func (c *ChainHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { diff --git a/vendor/github.com/go-chi/chi/chi.go b/vendor/github.com/go-chi/chi/v5/chi.go similarity index 80% rename from vendor/github.com/go-chi/chi/chi.go rename to vendor/github.com/go-chi/chi/v5/chi.go index b7063dc297..2b6ebd337c 100644 --- a/vendor/github.com/go-chi/chi/chi.go +++ b/vendor/github.com/go-chi/chi/v5/chi.go @@ -1,29 +1,29 @@ -// // Package chi is a small, idiomatic and composable router for building HTTP services. // -// chi requires Go 1.10 or newer. +// chi requires Go 1.14 or newer. // // Example: -// package main // -// import ( -// "net/http" +// package main +// +// import ( +// "net/http" // -// "github.com/go-chi/chi" -// "github.com/go-chi/chi/middleware" -// ) +// "github.com/go-chi/chi/v5" +// "github.com/go-chi/chi/v5/middleware" +// ) // -// func main() { -// r := chi.NewRouter() -// r.Use(middleware.Logger) -// r.Use(middleware.Recoverer) +// func main() { +// r := chi.NewRouter() +// r.Use(middleware.Logger) +// r.Use(middleware.Recoverer) // -// r.Get("/", func(w http.ResponseWriter, r *http.Request) { -// w.Write([]byte("root.")) -// }) +// r.Get("/", func(w http.ResponseWriter, r *http.Request) { +// w.Write([]byte("root.")) +// }) // -// http.ListenAndServe(":3333", r) -// } +// http.ListenAndServe(":3333", r) +// } // // See github.com/go-chi/chi/_examples/ for more in-depth examples. // @@ -37,8 +37,7 @@ // // A placeholder with a name followed by a colon allows a regular // expression match, for example {number:\\d+}. The regular expression -// syntax is Go's normal regexp RE2 syntax, except that regular expressions -// including { or } are not supported, and / will never be +// syntax is Go's normal regexp RE2 syntax, except that / will never be // matched. An anonymous regexp pattern is allowed, using an empty string // before the colon in the placeholder, such as {:\\d+} // @@ -47,12 +46,12 @@ // placeholder which will match / characters. // // Examples: -// "/user/{name}" matches "/user/jsmith" but not "/user/jsmith/info" or "/user/jsmith/" -// "/user/{name}/info" matches "/user/jsmith/info" -// "/page/*" matches "/page/intro/latest" -// "/page/*/index" also matches "/page/intro/latest" -// "/date/{yyyy:\\d\\d\\d\\d}/{mm:\\d\\d}/{dd:\\d\\d}" matches "/date/2017/04/01" // +// "/user/{name}" matches "/user/jsmith" but not "/user/jsmith/info" or "/user/jsmith/" +// "/user/{name}/info" matches "/user/jsmith/info" +// "/page/*" matches "/page/intro/latest" +// "/page/{other}/latest" also matches "/page/intro/latest" +// "/date/{yyyy:\\d\\d\\d\\d}/{mm:\\d\\d}/{dd:\\d\\d}" matches "/date/2017/04/01" package chi import "net/http" @@ -127,6 +126,10 @@ type Routes interface { // the method/path - similar to routing a http request, but without // executing the handler thereafter. Match(rctx *Context, method, path string) bool + + // Find searches the routing tree for the pattern that matches + // the method/path. + Find(rctx *Context, method, path string) string } // Middlewares type is a slice of standard middleware handlers with methods diff --git a/vendor/github.com/go-chi/chi/context.go b/vendor/github.com/go-chi/chi/v5/context.go similarity index 79% rename from vendor/github.com/go-chi/chi/context.go rename to vendor/github.com/go-chi/chi/v5/context.go index 8c97f214a9..82220730e9 100644 --- a/vendor/github.com/go-chi/chi/context.go +++ b/vendor/github.com/go-chi/chi/v5/context.go @@ -45,37 +45,37 @@ var ( type Context struct { Routes Routes + // parentCtx is the parent of this one, for using Context as a + // context.Context directly. This is an optimization that saves + // 1 allocation. + parentCtx context.Context + // Routing path/method override used during the route search. // See Mux#routeHTTP method. RoutePath string RouteMethod string - // Routing pattern stack throughout the lifecycle of the request, - // across all connected routers. It is a record of all matching - // patterns across a stack of sub-routers. - RoutePatterns []string - // URLParams are the stack of routeParams captured during the // routing lifecycle across a stack of sub-routers. URLParams RouteParams + // Route parameters matched for the current sub-router. It is + // intentionally unexported so it can't be tampered. + routeParams RouteParams + // The endpoint routing pattern that matched the request URI path // or `RoutePath` of the current sub-router. This value will update // during the lifecycle of a request passing through a stack of // sub-routers. routePattern string - // Route parameters matched for the current sub-router. It is - // intentionally unexported so it cant be tampered. - routeParams RouteParams + // Routing pattern stack throughout the lifecycle of the request, + // across all connected routers. It is a record of all matching + // patterns across a stack of sub-routers. + RoutePatterns []string - // methodNotAllowed hint + methodsAllowed []methodTyp // allowed methods in case of a 405 methodNotAllowed bool - - // parentCtx is the parent of this one, for using Context as a - // context.Context directly. This is an optimization that saves - // 1 allocation. - parentCtx context.Context } // Reset a routing context to its initial state. @@ -91,6 +91,7 @@ func (x *Context) Reset() { x.routeParams.Keys = x.routeParams.Keys[:0] x.routeParams.Values = x.routeParams.Values[:0] x.methodNotAllowed = false + x.methodsAllowed = x.methodsAllowed[:0] x.parentCtx = nil } @@ -108,29 +109,37 @@ func (x *Context) URLParam(key string) string { // RoutePattern builds the routing pattern string for the particular // request, at the particular point during routing. This means, the value // will change throughout the execution of a request in a router. That is -// why its advised to only use this value after calling the next handler. +// why it's advised to only use this value after calling the next handler. // // For example, // -// func Instrument(next http.Handler) http.Handler { -// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -// next.ServeHTTP(w, r) -// routePattern := chi.RouteContext(r.Context()).RoutePattern() -// measure(w, r, routePattern) -// }) -// } +// func Instrument(next http.Handler) http.Handler { +// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +// next.ServeHTTP(w, r) +// routePattern := chi.RouteContext(r.Context()).RoutePattern() +// measure(w, r, routePattern) +// }) +// } func (x *Context) RoutePattern() string { + if x == nil { + return "" + } routePattern := strings.Join(x.RoutePatterns, "") - return replaceWildcards(routePattern) + routePattern = replaceWildcards(routePattern) + if routePattern != "/" { + routePattern = strings.TrimSuffix(routePattern, "//") + routePattern = strings.TrimSuffix(routePattern, "/") + } + return routePattern } -// replaceWildcards takes a route pattern and recursively replaces all -// occurrences of "/*/" to "/". +// replaceWildcards takes a route pattern and replaces all occurrences of +// "/*/" with "/". It iteratively runs until no wildcards remain to +// correctly handle consecutive wildcards. func replaceWildcards(p string) string { - if strings.Contains(p, "/*/") { - return replaceWildcards(strings.Replace(p, "/*/", "/", -1)) + for strings.Contains(p, "/*/") { + p = strings.ReplaceAll(p, "/*/", "/") } - return p } diff --git a/vendor/github.com/go-chi/chi/mux.go b/vendor/github.com/go-chi/chi/v5/mux.go similarity index 86% rename from vendor/github.com/go-chi/chi/mux.go rename to vendor/github.com/go-chi/chi/v5/mux.go index 146643b04c..ad66bba91c 100644 --- a/vendor/github.com/go-chi/chi/mux.go +++ b/vendor/github.com/go-chi/chi/v5/mux.go @@ -19,29 +19,32 @@ var _ Router = &Mux{} // particularly useful for writing large REST API services that break a handler // into many smaller parts composed of middlewares and end handlers. type Mux struct { + // The computed mux handler made of the chained middleware stack and + // the tree router + handler http.Handler + // The radix trie router tree *node - // The middleware stack - middlewares []func(http.Handler) http.Handler + // Custom method not allowed handler + methodNotAllowedHandler http.HandlerFunc - // Controls the behaviour of middleware chain generation when a mux - // is registered as an inline group inside another mux. - inline bool + // A reference to the parent mux used by subrouters when mounting + // to a parent mux parent *Mux - // The computed mux handler made of the chained middleware stack and - // the tree router - handler http.Handler - // Routing context pool pool *sync.Pool // Custom route not found handler notFoundHandler http.HandlerFunc - // Custom method not allowed handler - methodNotAllowedHandler http.HandlerFunc + // The middleware stack + middlewares []func(http.Handler) http.Handler + + // Controls the behaviour of middleware chain generation when a mux + // is registered as an inline group inside another mux. + inline bool } // NewMux returns a newly initialized Mux object that implements the Router @@ -104,13 +107,19 @@ func (mx *Mux) Use(middlewares ...func(http.Handler) http.Handler) { // Handle adds the route `pattern` that matches any http method to // execute the `handler` http.Handler. func (mx *Mux) Handle(pattern string, handler http.Handler) { + if i := strings.IndexAny(pattern, " \t"); i >= 0 { + method, rest := pattern[:i], strings.TrimLeft(pattern[i+1:], " \t") + mx.Method(method, rest, handler) + return + } + mx.handle(mALL, pattern, handler) } // HandleFunc adds the route `pattern` that matches any http method to // execute the `handlerFn` http.HandlerFunc. func (mx *Mux) HandleFunc(pattern string, handlerFn http.HandlerFunc) { - mx.handle(mALL, pattern, handlerFn) + mx.Handle(pattern, handlerFn) } // Method adds the route `pattern` that matches `method` http method to @@ -153,7 +162,7 @@ func (mx *Mux) Head(pattern string, handlerFn http.HandlerFunc) { mx.handle(mHEAD, pattern, handlerFn) } -// Options adds the route `pattern` that matches a OPTIONS http method to +// Options adds the route `pattern` that matches an OPTIONS http method to // execute the `handlerFn` http.HandlerFunc. func (mx *Mux) Options(pattern string, handlerFn http.HandlerFunc) { mx.handle(mOPTIONS, pattern, handlerFn) @@ -188,16 +197,17 @@ func (mx *Mux) Trace(pattern string, handlerFn http.HandlerFunc) { func (mx *Mux) NotFound(handlerFn http.HandlerFunc) { // Build NotFound handler chain m := mx - h := Chain(mx.middlewares...).HandlerFunc(handlerFn).ServeHTTP + hFn := handlerFn if mx.inline && mx.parent != nil { m = mx.parent + hFn = Chain(mx.middlewares...).HandlerFunc(hFn).ServeHTTP } // Update the notFoundHandler from this point forward - m.notFoundHandler = h + m.notFoundHandler = hFn m.updateSubRoutes(func(subMux *Mux) { if subMux.notFoundHandler == nil { - subMux.NotFound(h) + subMux.NotFound(hFn) } }) } @@ -207,16 +217,17 @@ func (mx *Mux) NotFound(handlerFn http.HandlerFunc) { func (mx *Mux) MethodNotAllowed(handlerFn http.HandlerFunc) { // Build MethodNotAllowed handler chain m := mx - h := Chain(mx.middlewares...).HandlerFunc(handlerFn).ServeHTTP + hFn := handlerFn if mx.inline && mx.parent != nil { m = mx.parent + hFn = Chain(mx.middlewares...).HandlerFunc(hFn).ServeHTTP } // Update the methodNotAllowedHandler from this point forward - m.methodNotAllowedHandler = h + m.methodNotAllowedHandler = hFn m.updateSubRoutes(func(subMux *Mux) { if subMux.methodNotAllowedHandler == nil { - subMux.MethodNotAllowed(h) + subMux.MethodNotAllowed(hFn) } }) } @@ -245,20 +256,19 @@ func (mx *Mux) With(middlewares ...func(http.Handler) http.Handler) Router { return im } -// Group creates a new inline-Mux with a fresh middleware stack. It's useful +// Group creates a new inline-Mux with a copy of middleware stack. It's useful // for a group of handlers along the same routing path that use an additional // set of middlewares. See _examples/. func (mx *Mux) Group(fn func(r Router)) Router { - im := mx.With().(*Mux) + im := mx.With() if fn != nil { fn(im) } return im } -// Route creates a new Mux with a fresh middleware stack and mounts it -// along the `pattern` as a subrouter. Effectively, this is a short-hand -// call to Mount. See _examples/. +// Route creates a new Mux and mounts it along the `pattern` as a subrouter. +// Effectively, this is a short-hand call to Mount. See _examples/. func (mx *Mux) Route(pattern string, fn func(r Router)) Router { if fn == nil { panic(fmt.Sprintf("chi: attempting to Route() a nil subrouter on '%s'", pattern)) @@ -347,19 +357,40 @@ func (mx *Mux) Middlewares() Middlewares { // Note: the *Context state is updated during execution, so manage // the state carefully or make a NewRouteContext(). func (mx *Mux) Match(rctx *Context, method, path string) bool { + return mx.Find(rctx, method, path) != "" +} + +// Find searches the routing tree for the pattern that matches +// the method/path. +// +// Note: the *Context state is updated during execution, so manage +// the state carefully or make a NewRouteContext(). +func (mx *Mux) Find(rctx *Context, method, path string) string { m, ok := methodMap[method] if !ok { - return false + return "" } - node, _, h := mx.tree.FindRoute(rctx, m, path) + node, _, _ := mx.tree.FindRoute(rctx, m, path) + pattern := rctx.routePattern + + if node != nil { + if node.subroutes == nil { + e := node.endpoints[m] + return e.pattern + } - if node != nil && node.subroutes != nil { rctx.RoutePath = mx.nextRoutePath(rctx) - return node.subroutes.Match(rctx, method, rctx.RoutePath) + subPattern := node.subroutes.Find(rctx, method, rctx.RoutePath) + if subPattern == "" { + return "" + } + + pattern = strings.TrimSuffix(pattern, "/*") + pattern += subPattern } - return h != nil + return pattern } // NotFoundHandler returns the default Mux 404 responder whenever a route @@ -373,11 +404,11 @@ func (mx *Mux) NotFoundHandler() http.HandlerFunc { // MethodNotAllowedHandler returns the default Mux 405 responder whenever // a method cannot be resolved for a route. -func (mx *Mux) MethodNotAllowedHandler() http.HandlerFunc { +func (mx *Mux) MethodNotAllowedHandler(methodsAllowed ...methodTyp) http.HandlerFunc { if mx.methodNotAllowedHandler != nil { return mx.methodNotAllowedHandler } - return methodNotAllowedHandler + return methodNotAllowedHandler(methodsAllowed...) } // handle registers a http.Handler in the routing tree for a particular http method @@ -419,6 +450,9 @@ func (mx *Mux) routeHTTP(w http.ResponseWriter, r *http.Request) { } else { routePath = r.URL.Path } + if routePath == "" { + routePath = "/" + } } // Check if method is supported by chi @@ -433,11 +467,18 @@ func (mx *Mux) routeHTTP(w http.ResponseWriter, r *http.Request) { // Find the route if _, _, h := mx.tree.FindRoute(rctx, method, routePath); h != nil { + if supportsPathValue { + setPathValue(rctx, r) + } + if supportsPattern { + setPattern(rctx, r) + } + h.ServeHTTP(w, r) return } if rctx.methodNotAllowed { - mx.MethodNotAllowedHandler().ServeHTTP(w, r) + mx.MethodNotAllowedHandler(rctx.methodsAllowed...).ServeHTTP(w, r) } else { mx.NotFoundHandler().ServeHTTP(w, r) } @@ -472,8 +513,14 @@ func (mx *Mux) updateRouteHandler() { } // methodNotAllowedHandler is a helper function to respond with a 405, -// method not allowed. -func methodNotAllowedHandler(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(405) - w.Write(nil) +// method not allowed. It sets the Allow header with the list of allowed +// methods for the route. +func methodNotAllowedHandler(methodsAllowed ...methodTyp) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + for _, m := range methodsAllowed { + w.Header().Add("Allow", reverseMethodMap[m]) + } + w.WriteHeader(405) + w.Write(nil) + } } diff --git a/vendor/github.com/go-chi/chi/v5/path_value.go b/vendor/github.com/go-chi/chi/v5/path_value.go new file mode 100644 index 0000000000..3ff983ac4e --- /dev/null +++ b/vendor/github.com/go-chi/chi/v5/path_value.go @@ -0,0 +1,20 @@ +//go:build go1.22 && !tinygo +// +build go1.22,!tinygo + +package chi + +import "net/http" + +// supportsPathValue is true if the Go version is 1.22 and above. +// +// If this is true, `net/http.Request` has methods `SetPathValue` and `PathValue`. +const supportsPathValue = true + +// setPathValue sets the path values in the Request value +// based on the provided request context. +func setPathValue(rctx *Context, r *http.Request) { + for i, key := range rctx.URLParams.Keys { + value := rctx.URLParams.Values[i] + r.SetPathValue(key, value) + } +} diff --git a/vendor/github.com/go-chi/chi/v5/path_value_fallback.go b/vendor/github.com/go-chi/chi/v5/path_value_fallback.go new file mode 100644 index 0000000000..749a8520a7 --- /dev/null +++ b/vendor/github.com/go-chi/chi/v5/path_value_fallback.go @@ -0,0 +1,19 @@ +//go:build !go1.22 || tinygo +// +build !go1.22 tinygo + +package chi + +import "net/http" + +// supportsPathValue is true if the Go version is 1.22 and above. +// +// If this is true, `net/http.Request` has methods `SetPathValue` and `PathValue`. +const supportsPathValue = false + +// setPathValue sets the path values in the Request value +// based on the provided request context. +// +// setPathValue is only supported in Go 1.22 and above so +// this is just a blank function so that it compiles. +func setPathValue(rctx *Context, r *http.Request) { +} diff --git a/vendor/github.com/go-chi/chi/v5/pattern.go b/vendor/github.com/go-chi/chi/v5/pattern.go new file mode 100644 index 0000000000..890a2c217f --- /dev/null +++ b/vendor/github.com/go-chi/chi/v5/pattern.go @@ -0,0 +1,16 @@ +//go:build go1.23 && !tinygo +// +build go1.23,!tinygo + +package chi + +import "net/http" + +// supportsPattern is true if the Go version is 1.23 and above. +// +// If this is true, `net/http.Request` has field `Pattern`. +const supportsPattern = true + +// setPattern sets the mux matched pattern in the http Request. +func setPattern(rctx *Context, r *http.Request) { + r.Pattern = rctx.routePattern +} diff --git a/vendor/github.com/go-chi/chi/v5/pattern_fallback.go b/vendor/github.com/go-chi/chi/v5/pattern_fallback.go new file mode 100644 index 0000000000..48a94ef82d --- /dev/null +++ b/vendor/github.com/go-chi/chi/v5/pattern_fallback.go @@ -0,0 +1,17 @@ +//go:build !go1.23 || tinygo +// +build !go1.23 tinygo + +package chi + +import "net/http" + +// supportsPattern is true if the Go version is 1.23 and above. +// +// If this is true, `net/http.Request` has field `Pattern`. +const supportsPattern = false + +// setPattern sets the mux matched pattern in the http Request. +// +// setPattern is only supported in Go 1.23 and above so +// this is just a blank function so that it compiles. +func setPattern(rctx *Context, r *http.Request) {} diff --git a/vendor/github.com/go-chi/chi/tree.go b/vendor/github.com/go-chi/chi/v5/tree.go similarity index 95% rename from vendor/github.com/go-chi/chi/tree.go rename to vendor/github.com/go-chi/chi/v5/tree.go index 8057c52813..bcb86b6f17 100644 --- a/vendor/github.com/go-chi/chi/tree.go +++ b/vendor/github.com/go-chi/chi/v5/tree.go @@ -13,7 +13,7 @@ import ( "strings" ) -type methodTyp int +type methodTyp uint const ( mSTUB methodTyp = 1 << iota @@ -43,6 +43,18 @@ var methodMap = map[string]methodTyp{ http.MethodTrace: mTRACE, } +var reverseMethodMap = map[methodTyp]string{ + mCONNECT: http.MethodConnect, + mDELETE: http.MethodDelete, + mGET: http.MethodGet, + mHEAD: http.MethodHead, + mOPTIONS: http.MethodOptions, + mPATCH: http.MethodPatch, + mPOST: http.MethodPost, + mPUT: http.MethodPut, + mTRACE: http.MethodTrace, +} + // RegisterMethod adds support for custom HTTP method handlers, available // via Router#Method and Router#MethodFunc func RegisterMethod(method string) { @@ -72,17 +84,8 @@ const ( ) type node struct { - // node type: static, regexp, param, catchAll - typ nodeTyp - - // first byte of the prefix - label byte - - // first byte of the child prefix - tail byte - - // prefix is the common prefix we ignore - prefix string + // subroutes on the leaf node + subroutes Routes // regexp matcher for regexp nodes rex *regexp.Regexp @@ -90,12 +93,21 @@ type node struct { // HTTP handler endpoints on the leaf node endpoints endpoints - // subroutes on the leaf node - subroutes Routes + // prefix is the common prefix we ignore + prefix string // child nodes should be stored in-order for iteration, // in groups of the node type. children [ntCatchAll + 1]nodes + + // first byte of the child prefix + tail byte + + // node type: static, regexp, param, catchAll + typ nodeTyp + + // first byte of the prefix + label byte } // endpoints is a mapping of http method constants to handlers @@ -454,6 +466,13 @@ func (n *node) findRoute(rctx *Context, method methodTyp, path string) *node { return xn } + for endpoints := range xn.endpoints { + if endpoints == mALL || endpoints == mSTUB { + continue + } + rctx.methodsAllowed = append(rctx.methodsAllowed, endpoints) + } + // flag that the routing context found a route, but not a corresponding // supported method rctx.methodNotAllowed = true @@ -493,6 +512,13 @@ func (n *node) findRoute(rctx *Context, method methodTyp, path string) *node { return xn } + for endpoints := range xn.endpoints { + if endpoints == mALL || endpoints == mSTUB { + continue + } + rctx.methodsAllowed = append(rctx.methodsAllowed, endpoints) + } + // flag that the routing context found a route, but not a corresponding // supported method rctx.methodNotAllowed = true @@ -624,14 +650,12 @@ func (n *node) routes() []Route { if h.handler == nil { continue } - m := methodTypString(mt) - if m == "" { - continue + if m, ok := reverseMethodMap[mt]; ok { + hs[m] = h.handler } - hs[m] = h.handler } - rt := Route{p, hs, subroutes} + rt := Route{subroutes, hs, p} rts = append(rts, rt) } @@ -704,11 +728,9 @@ func patNextSegment(pattern string) (nodeTyp, string, string, byte, int, int) { tail = pattern[pe] } - var rexpat string - if idx := strings.Index(key, ":"); idx >= 0 { + key, rexpat, isRegexp := strings.Cut(key, ":") + if isRegexp { nt = ntRegexp - rexpat = key[idx+1:] - key = key[:idx] } if len(rexpat) > 0 { @@ -764,15 +786,6 @@ func longestPrefix(k1, k2 string) int { return i } -func methodTypString(method methodTyp) string { - for s, t := range methodMap { - if method == t { - return s - } - } - return "" -} - type nodes []*node // Sort the list of nodes by label @@ -815,9 +828,9 @@ func (ns nodes) findEdge(label byte) *node { // Route describes the details of a routing handler. // Handlers map key is an HTTP method type Route struct { - Pattern string - Handlers map[string]http.Handler SubRoutes Routes + Handlers map[string]http.Handler + Pattern string } // WalkFunc is the type of the function called for each method and route visited by Walk. diff --git a/vendor/github.com/go-chi/cors/cors.go b/vendor/github.com/go-chi/cors/cors.go index 8df81636e3..75196ab91c 100644 --- a/vendor/github.com/go-chi/cors/cors.go +++ b/vendor/github.com/go-chi/cors/cors.go @@ -3,15 +3,15 @@ // // You can configure it by passing an option struct to cors.New: // -// c := cors.New(cors.Options{ -// AllowedOrigins: []string{"foo.com"}, -// AllowedMethods: []string{"GET", "POST", "DELETE"}, -// AllowCredentials: true, -// }) +// c := cors.New(cors.Options{ +// AllowedOrigins: []string{"foo.com"}, +// AllowedMethods: []string{"GET", "POST", "DELETE"}, +// AllowCredentials: true, +// }) // // Then insert the handler in the chain: // -// handler = c.Handler(handler) +// handler = c.Handler(handler) // // See Options documentation for more options. // diff --git a/vendor/github.com/google/uuid/dce.go b/vendor/github.com/google/uuid/dce.go index fa820b9d30..9302a1c1bb 100644 --- a/vendor/github.com/google/uuid/dce.go +++ b/vendor/github.com/google/uuid/dce.go @@ -42,7 +42,7 @@ func NewDCESecurity(domain Domain, id uint32) (UUID, error) { // NewDCEPerson returns a DCE Security (Version 2) UUID in the person // domain with the id returned by os.Getuid. // -// NewDCESecurity(Person, uint32(os.Getuid())) +// NewDCESecurity(Person, uint32(os.Getuid())) func NewDCEPerson() (UUID, error) { return NewDCESecurity(Person, uint32(os.Getuid())) } @@ -50,7 +50,7 @@ func NewDCEPerson() (UUID, error) { // NewDCEGroup returns a DCE Security (Version 2) UUID in the group // domain with the id returned by os.Getgid. // -// NewDCESecurity(Group, uint32(os.Getgid())) +// NewDCESecurity(Group, uint32(os.Getgid())) func NewDCEGroup() (UUID, error) { return NewDCESecurity(Group, uint32(os.Getgid())) } diff --git a/vendor/github.com/google/uuid/hash.go b/vendor/github.com/google/uuid/hash.go index b404f4bec2..24ccde6464 100644 --- a/vendor/github.com/google/uuid/hash.go +++ b/vendor/github.com/google/uuid/hash.go @@ -39,7 +39,7 @@ func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { // NewMD5 returns a new MD5 (Version 3) UUID based on the // supplied name space and data. It is the same as calling: // -// NewHash(md5.New(), space, data, 3) +// NewHash(md5.New(), space, data, 3) func NewMD5(space UUID, data []byte) UUID { return NewHash(md5.New(), space, data, 3) } @@ -47,7 +47,7 @@ func NewMD5(space UUID, data []byte) UUID { // NewSHA1 returns a new SHA1 (Version 5) UUID based on the // supplied name space and data. It is the same as calling: // -// NewHash(sha1.New(), space, data, 5) +// NewHash(sha1.New(), space, data, 5) func NewSHA1(space UUID, data []byte) UUID { return NewHash(sha1.New(), space, data, 5) } diff --git a/vendor/github.com/google/uuid/node_js.go b/vendor/github.com/google/uuid/node_js.go index 24b78edc90..96090351a9 100644 --- a/vendor/github.com/google/uuid/node_js.go +++ b/vendor/github.com/google/uuid/node_js.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build js // +build js package uuid diff --git a/vendor/github.com/google/uuid/node_net.go b/vendor/github.com/google/uuid/node_net.go index 0cbbcddbd6..e91358f7d9 100644 --- a/vendor/github.com/google/uuid/node_net.go +++ b/vendor/github.com/google/uuid/node_net.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !js // +build !js package uuid diff --git a/vendor/github.com/google/uuid/null.go b/vendor/github.com/google/uuid/null.go index d7fcbf2865..06ecf9de2a 100644 --- a/vendor/github.com/google/uuid/null.go +++ b/vendor/github.com/google/uuid/null.go @@ -17,15 +17,14 @@ var jsonNull = []byte("null") // NullUUID implements the SQL driver.Scanner interface so // it can be used as a scan destination: // -// var u uuid.NullUUID -// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u) -// ... -// if u.Valid { -// // use u.UUID -// } else { -// // NULL value -// } -// +// var u uuid.NullUUID +// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u) +// ... +// if u.Valid { +// // use u.UUID +// } else { +// // NULL value +// } type NullUUID struct { UUID UUID Valid bool // Valid is true if UUID is not NULL diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go index 7697802e4d..62ac273815 100644 --- a/vendor/github.com/google/uuid/version4.go +++ b/vendor/github.com/google/uuid/version4.go @@ -9,7 +9,7 @@ import "io" // New creates a new random UUID or panics. New is equivalent to // the expression // -// uuid.Must(uuid.NewRandom()) +// uuid.Must(uuid.NewRandom()) func New() UUID { return Must(NewRandom()) } @@ -17,7 +17,7 @@ func New() UUID { // NewString creates a new random UUID and returns it as a string or panics. // NewString is equivalent to the expression // -// uuid.New().String() +// uuid.New().String() func NewString() string { return Must(NewRandom()).String() } @@ -31,11 +31,11 @@ func NewString() string { // // A note about uniqueness derived from the UUID Wikipedia entry: // -// Randomly generated UUIDs have 122 random bits. One's annual risk of being -// hit by a meteorite is estimated to be one chance in 17 billion, that -// means the probability is about 0.00000000006 (6 × 10−11), -// equivalent to the odds of creating a few tens of trillions of UUIDs in a -// year and having one duplicate. +// Randomly generated UUIDs have 122 random bits. One's annual risk of being +// hit by a meteorite is estimated to be one chance in 17 billion, that +// means the probability is about 0.00000000006 (6 × 10−11), +// equivalent to the odds of creating a few tens of trillions of UUIDs in a +// year and having one duplicate. func NewRandom() (UUID, error) { if !poolEnabled { return NewRandomFromReader(rander) diff --git a/vendor/modules.txt b/vendor/modules.txt index 9fefa57685..d05c626612 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,9 +1,9 @@ # github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 ## explicit; go 1.18 github.com/antlr/antlr4/runtime/Go/antlr/v4 -# github.com/go-chi/chi v1.5.4 -## explicit; go 1.16 -github.com/go-chi/chi +# github.com/go-chi/chi/v5 v5.2.3 +## explicit; go 1.20 +github.com/go-chi/chi/v5 # github.com/go-chi/cors v1.2.1 ## explicit; go 1.14 github.com/go-chi/cors diff --git a/vendor/nhooyr.io/websocket/accept.go b/vendor/nhooyr.io/websocket/accept.go index 18536bdb2c..b54471312e 100644 --- a/vendor/nhooyr.io/websocket/accept.go +++ b/vendor/nhooyr.io/websocket/accept.go @@ -1,3 +1,4 @@ +//go:build !js // +build !js package websocket diff --git a/vendor/nhooyr.io/websocket/close_notjs.go b/vendor/nhooyr.io/websocket/close_notjs.go index 4251311d2e..8cafaa9dcf 100644 --- a/vendor/nhooyr.io/websocket/close_notjs.go +++ b/vendor/nhooyr.io/websocket/close_notjs.go @@ -1,3 +1,4 @@ +//go:build !js // +build !js package websocket diff --git a/vendor/nhooyr.io/websocket/compress_notjs.go b/vendor/nhooyr.io/websocket/compress_notjs.go index 809a272c3d..e094513b35 100644 --- a/vendor/nhooyr.io/websocket/compress_notjs.go +++ b/vendor/nhooyr.io/websocket/compress_notjs.go @@ -1,3 +1,4 @@ +//go:build !js // +build !js package websocket diff --git a/vendor/nhooyr.io/websocket/conn_notjs.go b/vendor/nhooyr.io/websocket/conn_notjs.go index 0c85ab7711..3c1361c5b2 100644 --- a/vendor/nhooyr.io/websocket/conn_notjs.go +++ b/vendor/nhooyr.io/websocket/conn_notjs.go @@ -1,3 +1,4 @@ +//go:build !js // +build !js package websocket diff --git a/vendor/nhooyr.io/websocket/dial.go b/vendor/nhooyr.io/websocket/dial.go index 7a7787ff71..7b91713e9c 100644 --- a/vendor/nhooyr.io/websocket/dial.go +++ b/vendor/nhooyr.io/websocket/dial.go @@ -1,3 +1,4 @@ +//go:build !js // +build !js package websocket diff --git a/vendor/nhooyr.io/websocket/doc.go b/vendor/nhooyr.io/websocket/doc.go index efa920e3b6..a2b873c722 100644 --- a/vendor/nhooyr.io/websocket/doc.go +++ b/vendor/nhooyr.io/websocket/doc.go @@ -1,3 +1,4 @@ +//go:build !js // +build !js // Package websocket implements the RFC 6455 WebSocket protocol. @@ -16,7 +17,7 @@ // // More documentation at https://nhooyr.io/websocket. // -// Wasm +// # Wasm // // The client side supports compiling to Wasm. // It wraps the WebSocket browser API. @@ -25,8 +26,8 @@ // // Some important caveats to be aware of: // -// - Accept always errors out -// - Conn.Ping is no-op -// - HTTPClient, HTTPHeader and CompressionMode in DialOptions are no-op -// - *http.Response from Dial is &http.Response{} with a 101 status code on success +// - Accept always errors out +// - Conn.Ping is no-op +// - HTTPClient, HTTPHeader and CompressionMode in DialOptions are no-op +// - *http.Response from Dial is &http.Response{} with a 101 status code on success package websocket // import "nhooyr.io/websocket" diff --git a/vendor/nhooyr.io/websocket/internal/wsjs/wsjs_js.go b/vendor/nhooyr.io/websocket/internal/wsjs/wsjs_js.go index 26ffb45625..88e8f43f69 100644 --- a/vendor/nhooyr.io/websocket/internal/wsjs/wsjs_js.go +++ b/vendor/nhooyr.io/websocket/internal/wsjs/wsjs_js.go @@ -1,3 +1,4 @@ +//go:build js // +build js // Package wsjs implements typed access to the browser javascript WebSocket API. diff --git a/vendor/nhooyr.io/websocket/read.go b/vendor/nhooyr.io/websocket/read.go index ae05cf93ed..0f10afef62 100644 --- a/vendor/nhooyr.io/websocket/read.go +++ b/vendor/nhooyr.io/websocket/read.go @@ -1,3 +1,4 @@ +//go:build !js // +build !js package websocket diff --git a/vendor/nhooyr.io/websocket/write.go b/vendor/nhooyr.io/websocket/write.go index 2210cf817a..9528e5acd7 100644 --- a/vendor/nhooyr.io/websocket/write.go +++ b/vendor/nhooyr.io/websocket/write.go @@ -1,3 +1,4 @@ +//go:build !js // +build !js package websocket