diff options
author | 2022-09-28 18:30:40 +0100 | |
---|---|---|
committer | 2022-09-28 18:30:40 +0100 | |
commit | a156188b3eb5cb3da44aa1b7452265f5fa38a607 (patch) | |
tree | 7097fa48d56fbabc7c2c8750b1f3bc9321d71c0f /vendor/github.com/gin-gonic/gin | |
parent | [bugfix] Fix emphasis being added to emoji shortcodes with markdown parsing (... (diff) | |
download | gotosocial-a156188b3eb5cb3da44aa1b7452265f5fa38a607.tar.xz |
[chore] update dependencies, bump to Go 1.19.1 (#826)
* update dependencies, bump Go version to 1.19
* bump test image Go version
* update golangci-lint
* update gotosocial-drone-build
* sign
* linting, go fmt
* update swagger docs
* update swagger docs
* whitespace
* update contributing.md
* fuckin whoopsie doopsie
* linterino, linteroni
* fix followrequest test not starting processor
* fix other api/client tests not starting processor
* fix remaining tests where processor not started
* bump go-runners version
* don't check last-webfingered-at, processor may have updated this
* update swagger command
* update bun to latest version
* fix embed to work the same as before with new bun
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
Diffstat (limited to 'vendor/github.com/gin-gonic/gin')
58 files changed, 1403 insertions, 748 deletions
diff --git a/vendor/github.com/gin-gonic/gin/.golangci.yml b/vendor/github.com/gin-gonic/gin/.golangci.yml new file mode 100644 index 000000000..c5e1de388 --- /dev/null +++ b/vendor/github.com/gin-gonic/gin/.golangci.yml @@ -0,0 +1,39 @@ +run: + timeout: 5m +linters: + enable: + - asciicheck + - depguard + - dogsled + - durationcheck + - errcheck + - errorlint + - exportloopref + - gci + - gofmt + - goimports + - gosec + - misspell + - nakedret + - nilerr + - nolintlint + - revive + - wastedassign +issues: + exclude-rules: + - linters: + - structcheck + - unused + text: "`data` is unused" + - linters: + - staticcheck + text: "SA1019:" + - linters: + - revive + text: "var-naming:" + - linters: + - revive + text: "exported:" + - path: _test\.go + linters: + - gosec # security is not make sense in tests diff --git a/vendor/github.com/gin-gonic/gin/.goreleaser.yaml b/vendor/github.com/gin-gonic/gin/.goreleaser.yaml new file mode 100644 index 000000000..e435e56aa --- /dev/null +++ b/vendor/github.com/gin-gonic/gin/.goreleaser.yaml @@ -0,0 +1,57 @@ +project_name: gin + +builds: + - + # If true, skip the build. + # Useful for library projects. + # Default is false + skip: true + +changelog: + # Set it to true if you wish to skip the changelog generation. + # This may result in an empty release notes on GitHub/GitLab/Gitea. + skip: false + + # Changelog generation implementation to use. + # + # Valid options are: + # - `git`: uses `git log`; + # - `github`: uses the compare GitHub API, appending the author login to the changelog. + # - `gitlab`: uses the compare GitLab API, appending the author name and email to the changelog. + # - `github-native`: uses the GitHub release notes generation API, disables the groups feature. + # + # Defaults to `git`. + use: git + + # Sorts the changelog by the commit's messages. + # Could either be asc, desc or empty + # Default is empty + sort: asc + + # Group commits messages by given regex and title. + # Order value defines the order of the groups. + # Proving no regex means all commits will be grouped under the default group. + # Groups are disabled when using github-native, as it already groups things by itself. + # + # Default is no groups. + groups: + - title: Features + regexp: "^.*feat[(\\w)]*:+.*$" + order: 0 + - title: 'Bug fixes' + regexp: "^.*fix[(\\w)]*:+.*$" + order: 1 + - title: 'Enhancements' + regexp: "^.*chore[(\\w)]*:+.*$" + order: 2 + - title: Others + order: 999 + + filters: + # Commit messages matching the regexp listed here will be removed from + # the changelog + # Default is empty + exclude: + - '^docs' + - 'CICD' + - typo diff --git a/vendor/github.com/gin-gonic/gin/.travis.yml b/vendor/github.com/gin-gonic/gin/.travis.yml deleted file mode 100644 index bcc21414d..000000000 --- a/vendor/github.com/gin-gonic/gin/.travis.yml +++ /dev/null @@ -1,48 +0,0 @@ -language: go - -matrix: - fast_finish: true - include: - - go: 1.13.x - - go: 1.13.x - env: - - TESTTAGS=nomsgpack - - go: 1.14.x - - go: 1.14.x - env: - - TESTTAGS=nomsgpack - - go: 1.15.x - - go: 1.15.x - env: - - TESTTAGS=nomsgpack - - go: master - -git: - depth: 10 - -before_install: - - if [[ "${GO111MODULE}" = "on" ]]; then mkdir "${HOME}/go"; export GOPATH="${HOME}/go"; fi - -install: - - if [[ "${GO111MODULE}" = "on" ]]; then go mod download; fi - - if [[ "${GO111MODULE}" = "on" ]]; then export PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"; fi - - if [[ "${GO111MODULE}" = "on" ]]; then make tools; fi - -go_import_path: github.com/gin-gonic/gin - -script: - - make vet - - make fmt-check - - make misspell-check - - make test - -after_success: - - bash <(curl -s https://codecov.io/bash) - -notifications: - webhooks: - urls: - - https://webhooks.gitter.im/e/7f95bf605c4d356372f4 - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: false # default: false diff --git a/vendor/github.com/gin-gonic/gin/AUTHORS.md b/vendor/github.com/gin-gonic/gin/AUTHORS.md index c634e6be0..b4773ef3d 100644 --- a/vendor/github.com/gin-gonic/gin/AUTHORS.md +++ b/vendor/github.com/gin-gonic/gin/AUTHORS.md @@ -2,232 +2,405 @@ List of all the awesome people working to make Gin the best Web Framework in Go. ## gin 1.x series authors -**Gin Core Team:** Bo-Yi Wu (@appleboy), 田欧 (@thinkerou), Javier Provecho (@javierprovecho) +**Gin Core Team:** Bo-Yi Wu (@appleboy), thinkerou (@thinkerou), Javier Provecho (@javierprovecho) ## gin 0.x series authors **Maintainers:** Manu Martinez-Almeida (@manucorporat), Javier Provecho (@javierprovecho) -People and companies, who have contributed, in alphabetical order. - -**@858806258 (杰哥)** -- Fix typo in example - - -**@achedeuzot (Klemen Sever)** -- Fix newline debug printing - - -**@adammck (Adam Mckaig)** -- Add MIT license - - -**@AlexanderChen1989 (Alexander)** -- Typos in README - - -**@alexanderdidenko (Aleksandr Didenko)** -- Add support multipart/form-data - - -**@alexandernyquist (Alexander Nyquist)** -- Using template.Must to fix multiple return issue -- ★ Added support for OPTIONS verb -- ★ Setting response headers before calling WriteHeader -- Improved documentation for model binding -- ★ Added Content.Redirect() -- ★ Added tons of Unit tests - - -**@austinheap (Austin Heap)** -- Added travis CI integration - - -**@andredublin (Andre Dublin)** -- Fix typo in comment - - -**@bredov (Ludwig Valda Vasquez)** -- Fix html templating in debug mode - - -**@bluele (Jun Kimura)** -- Fixes code examples in README - - -**@chad-russell** -- ★ Support for serializing gin.H into XML - - -**@dickeyxxx (Jeff Dickey)** -- Typos in README -- Add example about serving static files - - -**@donileo (Adonis)** -- Add NoMethod handler - - -**@dutchcoders (DutchCoders)** -- ★ Fix security bug that allows client to spoof ip -- Fix typo. r.HTMLTemplates -> SetHTMLTemplate - - -**@el3ctro- (Joshua Loper)** -- Fix typo in example - - -**@ethankan (Ethan Kan)** -- Unsigned integers in binding - - -**(Evgeny Persienko)** -- Validate sub structures - - -**@frankbille (Frank Bille)** -- Add support for HTTP Realm Auth - - -**@fmd (Fareed Dudhia)** -- Fix typo. SetHTTPTemplate -> SetHTMLTemplate - - -**@ironiridis (Christopher Harrington)** -- Remove old reference - - -**@jammie-stackhouse (Jamie Stackhouse)** -- Add more shortcuts for router methods - - -**@jasonrhansen** -- Fix spelling and grammar errors in documentation - - -**@JasonSoft (Jason Lee)** -- Fix typo in comment - - -**@joiggama (Ignacio Galindo)** -- Add utf-8 charset header on renders - - -**@julienschmidt (Julien Schmidt)** -- gofmt the code examples - - -**@kelcecil (Kel Cecil)** -- Fix readme typo - - -**@kyledinh (Kyle Dinh)** -- Adds RunTLS() - - -**@LinusU (Linus Unnebäck)** -- Small fixes in README - - -**@loongmxbt (Saint Asky)** -- Fix typo in example - - -**@lucas-clemente (Lucas Clemente)** -- ★ work around path.Join removing trailing slashes from routes - - -**@mattn (Yasuhiro Matsumoto)** -- Improve color logger - - -**@mdigger (Dmitry Sedykh)** -- Fixes Form binding when content-type is x-www-form-urlencoded -- No repeat call c.Writer.Status() in gin.Logger -- Fixes Content-Type for json render - - -**@mirzac (Mirza Ceric)** -- Fix debug printing - - -**@mopemope (Yutaka Matsubara)** -- ★ Adds Godep support (Dependencies Manager) -- Fix variadic parameter in the flexible render API -- Fix Corrupted plain render -- Add Pluggable View Renderer Example - - -**@msemenistyi (Mykyta Semenistyi)** -- update Readme.md. Add code to String method - - -**@msoedov (Sasha Myasoedov)** -- ★ Adds tons of unit tests. - - -**@ngerakines (Nick Gerakines)** -- ★ Improves API, c.GET() doesn't panic -- Adds MustGet() method - - -**@r8k (Rajiv Kilaparti)** -- Fix Port usage in README. - - -**@rayrod2030 (Ray Rodriguez)** -- Fix typo in example - - -**@rns** -- Fix typo in example - - -**@RobAWilkinson (Robert Wilkinson)** -- Add example of forms and params - - -**@rogierlommers (Rogier Lommers)** -- Add updated static serve example - -**@rw-access (Ross Wolf)** -- Added support to mix exact and param routes - -**@se77en (Damon Zhao)** -- Improve color logging - - -**@silasb (Silas Baronda)** -- Fixing quotes in README - - -**@SkuliOskarsson (Skuli Oskarsson)** -- Fixes some texts in README II - - -**@slimmy (Jimmy Pettersson)** -- Added messages for required bindings - - -**@smira (Andrey Smirnov)** -- Add support for ignored/unexported fields in binding - - -**@superalsrk (SRK.Lyu)** -- Update httprouter godeps - - -**@tebeka (Miki Tebeka)** -- Use net/http constants instead of numeric values - - -**@techjanitor** -- Update context.go reserved IPs - - -**@yosssi (Keiji Yoshida)** -- Fix link in README +------ +People and companies, who have contributed, in alphabetical order. -**@yuyabee** -- Fixed README +- 178inaba <178inaba@users.noreply.github.com> +- A. F <hello@clivern.com> +- ABHISHEK SONI <abhishek.rocks26@gmail.com> +- Abhishek Chanda <achanda@users.noreply.github.com> +- Abner Chen <houjunchen@gmail.com> +- AcoNCodes <acongame@gmail.com> +- Adam Dratwinski <adam.dratwinski@gmail.com> +- Adam Mckaig <adam.mckaig@gmail.com> +- Adam Zielinski <MusicAdam@users.noreply.github.com> +- Adonis <donileo@gmail.com> +- Alan Wang <azzwacb9001@126.com> +- Albin Gilles <gilles.albin@gmail.com> +- Aleksandr Didenko <aa.didenko@yandex.ru> +- Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> +- Alex <AWulkan@users.noreply.github.com> +- Alexander <alexanderchenmh@gmail.com> +- Alexander Lokhman <alex.lokhman@gmail.com> +- Alexander Melentyev <55826637+alexander-melentyev@users.noreply.github.com> +- Alexander Nyquist <nyquist.alexander@gmail.com> +- Allen Ren <kulong0105@gmail.com> +- AllinGo <tanhp@outlook.com> +- Ammar Bandukwala <ammar@ammar.io> +- An Xiao (Luffy) <hac@zju.edu.cn> +- Andre Dublin <81dublin@gmail.com> +- Andrew Szeto <github@jabagawee.com> +- Andrey Abramov <andreyabramov.aaa@gmail.com> +- Andrey Nering <andrey.nering@gmail.com> +- Andrey Smirnov <Smirnov.Andrey@gmail.com> +- Andrii Bubis <firstrow@gmail.com> +- André Bazaglia <bazaglia@users.noreply.github.com> +- Andy Pan <panjf2000@gmail.com> +- Antoine GIRARD <sapk@users.noreply.github.com> +- Anup Kumar Panwar <1anuppanwar@gmail.com> +- Aravinth Sundaram <gosh.aravind@gmail.com> +- Artem <horechek@gmail.com> +- Ashwani <ashwanisharma686@gmail.com> +- Aurelien Regat-Barrel <arb@cyberkarma.net> +- Austin Heap <me@austinheap.com> +- Barnabus <jbampton@users.noreply.github.com> +- Bo-Yi Wu <appleboy.tw@gmail.com> +- Boris Borshevsky <BorisBorshevsky@gmail.com> +- Boyi Wu <p581581@gmail.com> +- BradyBromley <51128276+BradyBromley@users.noreply.github.com> +- Brendan Fosberry <brendan@shopkeep.com> +- Brian Wigginton <brianwigginton@gmail.com> +- Carlos Eduardo <carlosedp@gmail.com> +- Chad Russell <chaddouglasrussell@gmail.com> +- Charles <cxjava@gmail.com> +- Christian Muehlhaeuser <muesli@gmail.com> +- Christian Persson <saser@live.se> +- Christopher Harrington <ironiridis@gmail.com> +- Damon Zhao <yijun.zhao@outlook.com> +- Dan Markham <dmarkham@gmail.com> +- Dang Nguyen <hoangdang.me@gmail.com> +- Daniel Krom <kromdan@gmail.com> +- Daniel M. Lambea <dmlambea@gmail.com> +- Danieliu <liudanking@gmail.com> +- David Irvine <aviddiviner@gmail.com> +- David Zhang <crispgm@gmail.com> +- Davor Kapsa <dvrkps@users.noreply.github.com> +- DeathKing <DeathKing@users.noreply.github.com> +- Dennis Cho <47404603+forest747@users.noreply.github.com> +- Dmitry Dorogin <dmirogin@ya.ru> +- Dmitry Kutakov <vkd.castle@gmail.com> +- Dmitry Sedykh <dmitrys@d3h.local> +- Don2Quixote <35610661+Don2Quixote@users.noreply.github.com> +- Donn Pebe <iam@donnpebe.com> +- Dustin Decker <dustindecker@protonmail.com> +- Eason Lin <easonlin404@gmail.com> +- Edward Betts <edward@4angle.com> +- Egor Seredin <4819888+agmt@users.noreply.github.com> +- Emmanuel Goh <emmanuel@visenze.com> +- Equim <sayaka@ekyu.moe> +- Eren A. Akyol <eren@redmc.me> +- Eric_Lee <xplzv@126.com> +- Erik Bender <erik.bender@develerik.dev> +- Ethan Kan <ethankan@neoplot.com> +- Evgeny Persienko <e.persienko@office.ngs.ru> +- Faisal Alam <ifaisalalam@gmail.com> +- Fareed Dudhia <fareeddudhia@googlemail.com> +- Filip Figiel <figiel.filip@gmail.com> +- Florian Polster <couchpolster@icqmail.com> +- Frank Bille <github@frankbille.dk> +- Franz Bettag <franz@bett.ag> +- Ganlv <ganlvtech@users.noreply.github.com> +- Gaozhen Ying <yinggaozhen@hotmail.com> +- George Gabolaev <gabolaev98@gmail.com> +- George Kirilenko <necryin@users.noreply.github.com> +- Georges Varouchas <georges.varouchas@gmail.com> +- Gordon Tyler <gordon@doxxx.net> +- Harindu Perera <harinduenator@gmail.com> +- Helios <674876158@qq.com> +- Henry Kwan <piengeng@users.noreply.github.com> +- Henry Yee <henry@yearning.io> +- Himanshu Mishra <OrkoHunter@users.noreply.github.com> +- Hiroyuki Tanaka <h.tanaka.0325@gmail.com> +- Ibraheem Ahmed <ibrah1440@gmail.com> +- Ignacio Galindo <joiggama@gmail.com> +- Igor H. Vieira <zignd.igor@gmail.com> +- Ildar1111 <54001462+Ildar1111@users.noreply.github.com> +- Iskander (Alex) Sharipov <iskander.sharipov@intel.com> +- Ismail Gjevori <isgjevori@protonmail.com> +- Ivan Chen <allenivan@gmail.com> +- JINNOUCHI Yasushi <delphinus@remora.cx> +- James Pettyjohn <japettyjohn@users.noreply.github.com> +- Jamie Stackhouse <jamie.stackhouse@redspace.com> +- Jason Lee <jawc@hotmail.com> +- Javier Provecho <j.provecho@dartekstudios.com> +- Javier Provecho <javier.provecho@bq.com> +- Javier Provecho <javiertitan@gmail.com> +- Javier Provecho Fernandez <j.provecho@dartekstudios.com> +- Javier Provecho Fernandez <javiertitan@gmail.com> +- Jean-Christophe Lebreton <jclebreton@gmail.com> +- Jeff <laojianzi1994@gmail.com> +- Jeremy Loy <jeremy.b.loy@icloud.com> +- Jim Filippou <p3160253@aueb.gr> +- Jimmy Pettersson <jimmy@expertmaker.com> +- John Bampton <jbampton@users.noreply.github.com> +- Johnny Dallas <johnnydallas0308@gmail.com> +- Johnny Dallas <theonlyjohnny@theonlyjohnny.sh> +- Jonathan (JC) Chen <jc@dijonkitchen.org> +- Josep Jesus Bigorra Algaba <42377845+averageflow@users.noreply.github.com> +- Josh Horowitz <joshua.m.horowitz@gmail.com> +- Joshua Loper <josh.el3@gmail.com> +- Julien Schmidt <github@julienschmidt.com> +- Jun Kimura <jksmphone@gmail.com> +- Justin Beckwith <justin.beckwith@gmail.com> +- Justin Israel <justinisrael@gmail.com> +- Justin Mayhew <mayhew@live.ca> +- Jérôme Laforge <jerome-laforge@users.noreply.github.com> +- Kacper Bąk <56700396+53jk1@users.noreply.github.com> +- Kamron Batman <kamronbatman@users.noreply.github.com> +- Kane Rogers <kane@cleanstream.com.au> +- Kaushik Neelichetty <kaushikneelichetty6132@gmail.com> +- Keiji Yoshida <yoshida.keiji.84@gmail.com> +- Kel Cecil <kel.cecil@listhub.com> +- Kevin Mulvey <kmulvey@linux.com> +- Kevin Zhu <ipandtcp@gmail.com> +- Kirill Motkov <motkov.kirill@gmail.com> +- Klemen Sever <ksever@student.42.fr> +- Kristoffer A. Iversen <kristoffer.a.iversen@gmail.com> +- Krzysztof Szafrański <k.p.szafranski@gmail.com> +- Kumar McMillan <kumar.mcmillan@gmail.com> +- Kyle Mcgill <email@kylescottmcgill.com> +- Lanco <35420416+lancoLiu@users.noreply.github.com> +- Levi Olson <olson.levi@gmail.com> +- Lin Kao-Yuan <mosdeo@gmail.com> +- Linus Unnebäck <linus@folkdatorn.se> +- Lucas Clemente <lucas@clemente.io> +- Ludwig Valda Vasquez <bredov@gmail.com> +- Luis GG <lggomez@users.noreply.github.com> +- MW Lim <williamchange@gmail.com> +- Maksimov Sergey <konjoot@gmail.com> +- Manjusaka <lizheao940510@gmail.com> +- Manu MA <manu.mtza@gmail.com> +- Manu MA <manu.valladolid@gmail.com> +- Manu Mtz-Almeida <manu.valladolid@gmail.com> +- Manu Mtz.-Almeida <manu.valladolid@gmail.com> +- Manuel Alonso <manuelalonso@invisionapp.com> +- Mara Kim <hacker.root@gmail.com> +- Mario Kostelac <mario@intercom.io> +- Martin Karlsch <martin@karlsch.com> +- Matt Newberry <mnewberry@opentable.com> +- Matt Williams <gh@mattyw.net> +- Matthieu MOREL <mmorel-35@users.noreply.github.com> +- Max Hilbrunner <mhilbrunner@users.noreply.github.com> +- Maxime Soulé <btik-git@scoubidou.com> +- MetalBreaker <johnymichelson@gmail.com> +- Michael Puncel <mpuncel@squareup.com> +- MichaelDeSteven <51652084+MichaelDeSteven@users.noreply.github.com> +- Mike <38686456+icy4ever@users.noreply.github.com> +- Mike Stipicevic <mst@ableton.com> +- Miki Tebeka <miki.tebeka@gmail.com> +- Miles <MilesLin@users.noreply.github.com> +- Mirza Ceric <mirza.ceric@b2match.com> +- Mykyta Semenistyi <nikeiwe@gmail.com> +- Naoki Takano <honten@tinkermode.com> +- Ngalim Siregar <ngalim.siregar@gmail.com> +- Ni Hao <supernihaooo@qq.com> +- Nick Gerakines <nick@gerakines.net> +- Nikifor Seryakov <nikandfor@gmail.com> +- Notealot <714804968@qq.com> +- Olivier Mengué <dolmen@cpan.org> +- Olivier Robardet <orobardet@users.noreply.github.com> +- Pablo Moncada <pablo.moncada@bq.com> +- Pablo Moncada <pmoncadaisla@gmail.com> +- Panmax <967168@qq.com> +- Peperoncino <2wua4nlyi@gmail.com> +- Philipp Meinen <philipp@bind.ch> +- Pierre Massat <pierre@massat.io> +- Qt <golang.chen@gmail.com> +- Quentin ROYER <aydendevg@gmail.com> +- README Bot <35302948+codetriage-readme-bot@users.noreply.github.com> +- Rafal Zajac <rzajac@gmail.com> +- Rahul Datta Roy <rahuldroy@users.noreply.github.com> +- Rajiv Kilaparti <rajivk085@gmail.com> +- Raphael Gavache <raphael.gavache@datadoghq.com> +- Ray Rodriguez <rayrod2030@gmail.com> +- Regner Blok-Andersen <shadowdf@gmail.com> +- Remco <remco@dutchcoders.io> +- Rex Lee(李俊) <duguying2008@gmail.com> +- Richard Lee <dlackty@gmail.com> +- Riverside <wangyb65@gmail.com> +- Robert Wilkinson <wilkinson.robert.a@gmail.com> +- Rogier Lommers <rogier@lommers.org> +- Rohan Pai <me@rohanpai.com> +- Romain Beuque <rbeuque74@gmail.com> +- Roman Belyakovsky <ihryamzik@gmail.com> +- Roman Zaynetdinov <627197+zaynetro@users.noreply.github.com> +- Roman Zaynetdinov <roman.zaynetdinov@lekane.com> +- Ronald Petty <ronald.petty@rx-m.com> +- Ross Wolf <31489089+rw-access@users.noreply.github.com> +- Roy Lou <roylou@gmail.com> +- Rubi <14269809+codenoid@users.noreply.github.com> +- Ryan <46182144+ryanker@users.noreply.github.com> +- Ryan J. Yoder <me@ryanjyoder.com> +- SRK.Lyu <superalsrk@gmail.com> +- Sai <sairoutine@gmail.com> +- Samuel Abreu <sdepaula@gmail.com> +- Santhosh Kumar <santhoshkumarr1096@gmail.com> +- Sasha Melentyev <sasha@melentyev.io> +- Sasha Myasoedov <msoedov@gmail.com> +- Segev Finer <segev208@gmail.com> +- Sergey Egorov <egorovhome@gmail.com> +- Sergey Fedchenko <seregayoga@bk.ru> +- Sergey Gonimar <sergey.gonimar@gmail.com> +- Sergey Ponomarev <me@sergey-ponomarev.ru> +- Serica <943914044@qq.com> +- Shamus Taylor <Shamus03@me.com> +- Shilin Wang <jarvisfironman@gmail.com> +- Shuo <openset.wang@gmail.com> +- Skuli Oskarsson <skuli@codeiak.io> +- Snawoot <vladislav-ex-github@vm-0.com> +- Sridhar Ratnakumar <srid@srid.ca> +- Steeve Chailloux <steeve@chaahk.com> +- Sudhir Mishra <sudhirxps@gmail.com> +- Suhas Karanth <sudo-suhas@users.noreply.github.com> +- TaeJun Park <miking38@gmail.com> +- Tatsuya Hoshino <tatsuya7.hoshino7@gmail.com> +- Tevic <tevic.tt@gmail.com> +- Tevin Jeffrey <tev.jeffrey@gmail.com> +- The Gitter Badger <badger@gitter.im> +- Thibault Jamet <tjamet@users.noreply.github.com> +- Thomas Boerger <thomas@webhippie.de> +- Thomas Schaffer <loopfz@gmail.com> +- Tommy Chu <tommychu2256@gmail.com> +- Tudor Roman <tudurom@gmail.com> +- Uwe Dauernheim <djui@users.noreply.github.com> +- Valentine Oragbakosi <valentine13400@gmail.com> +- Vas N <pnvasanth@users.noreply.github.com> +- Vasilyuk Vasiliy <By-Vasiliy@users.noreply.github.com> +- Victor Castell <victor@victorcastell.com> +- Vince Yuan <vince.yuan@gmail.com> +- Vyacheslav Dubinin <vyacheslav.dubinin@gmail.com> +- Waynerv <ampedee@gmail.com> +- Weilin Shi <934587911@qq.com> +- Xudong Cai <fifsky@gmail.com> +- Yasuhiro Matsumoto <mattn.jp@gmail.com> +- Yehezkiel Syamsuhadi <ybs@ybs.im> +- Yoshiki Nakagawa <yyoshiki41@gmail.com> +- Yoshiyuki Kinjo <yskkin+github@gmail.com> +- Yue Yang <g1enyy0ung@gmail.com> +- ZYunH <zyunhjob@163.com> +- Zach Newburgh <zach.newburgh@gmail.com> +- Zasda Yusuf Mikail <zasdaym@gmail.com> +- ZhangYunHao <zyunhjob@163.com> +- ZhiFeng Hu <hufeng1987@gmail.com> +- Zhu Xi <zhuxi910511@163.com> +- a2tt <usera2tt@gmail.com> +- ahuigo <1781999+ahuigo@users.noreply.github.com> +- ali <anio@users.noreply.github.com> +- aljun <salameryy@163.com> +- andrea <crypto.andrea@protonmail.ch> +- andriikushch <andrii.kushch@gmail.com> +- anoty <anjunyou@foxmail.com> +- awkj <hzzbiu@gmail.com> +- axiaoxin <254606826@qq.com> +- bbiao <bbbiao@gmail.com> +- bestgopher <84328409@qq.com> +- betahu <zhong.wenhuang@foxmail.com> +- bigwheel <k.bigwheel+eng@gmail.com> +- bn4t <17193640+bn4t@users.noreply.github.com> +- bullgare <bullgare@gmail.com> +- chainhelen <chainhelen@gmail.com> +- chenyang929 <chenyang929code@gmail.com> +- chriswhelix <chris.williams@helix.com> +- collinmsn <4130944@qq.com> +- cssivision <cssivision@gmail.com> +- danielalves <alves.lopes.dan@gmail.com> +- delphinus <delphinus@remora.cx> +- dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> +- dickeyxxx <jeff@dickeyxxx.com> +- edebernis <emeric.debernis@gmail.com> +- error10 <error@ioerror.us> +- esplo <esplo@users.noreply.github.com> +- eudore <30709860+eudore@users.noreply.github.com> +- ffhelicopter <32922889+ffhelicopter@users.noreply.github.com> +- filikos <11477309+filikos@users.noreply.github.com> +- forging2012 <forging2012@users.noreply.github.com> +- goqihoo <goqihoo@gmail.com> +- grapeVine <treeui.old@gmail.com> +- guonaihong <guonaihong@qq.com> +- heige <daheige@users.noreply.github.com> +- heige <zhuwei313@hotmail.com> +- hellojukay <hellojukay@163.com> +- henrylee2cn <henrylee2cn@gmail.com> +- htobenothing <htobenothing@gmail.com> +- iamhesir <78344375+iamhesir@users.noreply.github.com> +- ijaa <kailiu2013@gmail.com> +- ishanray <ishan.iipm@gmail.com> +- ishanray <ishanray@users.noreply.github.com> +- itcloudy <272685110@qq.com> +- jarodsong6 <jarodsong6@gmail.com> +- jasonrhansen <jasonrodneyhansen@gmail.com> +- jincheng9 <perfume0607@gmail.com> +- joeADSP <75027008+joeADSP@users.noreply.github.com> +- junfengye <junfeng.yejf@gmail.com> +- kaiiak <aNxFi37X@outlook.com> +- kebo <kevinke2020@outlook.com> +- keke <19yamashita15@gmail.com> +- kishor kunal raj <68464660+kishorkunal-raj@users.noreply.github.com> +- kyledinh <kyledinh@gmail.com> +- lantw44 <lantw44@gmail.com> +- likakuli <1154584512@qq.com> +- linfangrong <linfangrong.liuxin@qq.com> +- linzi <873804682@qq.com> +- llgoer <yanghuxiao@vip.qq.com> +- long-road <13412081338@163.com> +- mbesancon <mathieu.besancon@gmail.com> +- mehdy <mehdy.khoshnoody@gmail.com> +- metal A-wing <freedom.awing.777@gmail.com> +- micanzhang <micanzhang@gmail.com> +- minarc <ragnhildmowinckel@gmail.com> +- mllu <mornlyn@gmail.com> +- mopemoepe <yutaka.matsubara@gmail.com> +- msoedov <msoedov@gmail.com> +- mstmdev <mstmdev@gmail.com> +- novaeye <fcoffee@gmail.com> +- olebedev <oolebedev@gmail.com> +- phithon <phith0n@users.noreply.github.com> +- pjgg <pablo.gonzalez.granados@gmail.com> +- qm012 <67568757+qm012@users.noreply.github.com> +- raymonder jin <rayjingithub@gmail.com> +- rns <ruslan.shvedov@gmail.com> +- root@andrea:~# <crypto.andrea@protonmail.ch> +- sekky0905 <20237968+sekky0905@users.noreply.github.com> +- senhtry <w169q169@gmail.com> +- shadrus <shadrus@gmail.com> +- silasb <silas.baronda@gmail.com> +- solos <lxl1217@gmail.com> +- songjiayang <songjiayang@users.noreply.github.com> +- sope <shenshouer@163.com> +- srt180 <30768686+srt180@users.noreply.github.com> +- stackerzzq <foo_stacker@yeah.net> +- sunshineplan <sunshineplan@users.noreply.github.com> +- syssam <s.y.s.sam.sys@gmail.com> +- techjanitor <puntme@gmail.com> +- techjanitor <techjanitor@users.noreply.github.com> +- thinkerou <thinkerou@gmail.com> +- thinkgo <49174849+thinkgos@users.noreply.github.com> +- tsirolnik <tsirolnik@users.noreply.github.com> +- tyltr <31768692+tylitianrui@users.noreply.github.com> +- vinhha96 <anhvinha1@gmail.com> +- voidman <retmain@foxmail.com> +- vz <vzvway@gmail.com> +- wei <wei840222@gmail.com> +- weibaohui <weibaohui@yeah.net> +- whirosan <whirosan@users.noreply.github.com> +- willnewrelic <will@newrelic.com> +- wssccc <wssccc@qq.com> +- wuhuizuo <wuhuizuo@126.com> +- xyb <xyb4638@gmail.com> +- y-yagi <yuuji.yaginuma@gmail.com> +- yiranzai <wuqingdzx@gmail.com> +- youzeliang <youzel@126.com> +- yugu <chenzilong_1227@foxmail.com> +- yuyabe <yuyabee@gmail.com> +- zebozhuang <zebozhuang@163.com> +- zero11-0203 <93071220+zero11-0203@users.noreply.github.com> +- zesani <7sin@outlook.co.th> +- zhanweidu <zhanweidu@163.com> +- zhing <zqwillseven@gmail.com> +- ziheng <zihenglv@gmail.com> +- zzjin <zzjin@users.noreply.github.com> +- 森 優太 <59682979+uta-mori@users.noreply.github.com> +- 杰哥 <858806258@qq.com> +- 涛叔 <hi@taoshu.in> +- 市民233 <mengrenxiong@gmail.com> +- 尹宝强 <wmdandme@gmail.com> +- 梦溪笔谈 <loongmxbt@gmail.com> +- 飞雪无情 <ls8707@gmail.com> +- 寻寻觅觅的Gopher <zoujh99@qq.com> diff --git a/vendor/github.com/gin-gonic/gin/CHANGELOG.md b/vendor/github.com/gin-gonic/gin/CHANGELOG.md index 4c806a5a7..1bc51a8c9 100644 --- a/vendor/github.com/gin-gonic/gin/CHANGELOG.md +++ b/vendor/github.com/gin-gonic/gin/CHANGELOG.md @@ -1,5 +1,53 @@ # Gin ChangeLog +## Gin v1.8.1 + +### ENHANCEMENTS + +* feat(context): add ContextWithFallback feature flag [#3172](https://github.com/gin-gonic/gin/pull/3172) + +## Gin v1.8.0 + +## Break Changes + +* TrustedProxies: Add default IPv6 support and refactor [#2967](https://github.com/gin-gonic/gin/pull/2967). Please replace `RemoteIP() (net.IP, bool)` with `RemoteIP() net.IP` +* gin.Context with fallback value from gin.Context.Request.Context() [#2751](https://github.com/gin-gonic/gin/pull/2751) + +### BUGFIXES + +* Fixed SetOutput() panics on go 1.17 [#2861](https://github.com/gin-gonic/gin/pull/2861) +* Fix: wrong when wildcard follows named param [#2983](https://github.com/gin-gonic/gin/pull/2983) +* Fix: missing sameSite when do context.reset() [#3123](https://github.com/gin-gonic/gin/pull/3123) + +### ENHANCEMENTS + +* Use Header() instead of deprecated HeaderMap [#2694](https://github.com/gin-gonic/gin/pull/2694) +* RouterGroup.Handle regular match optimization of http method [#2685](https://github.com/gin-gonic/gin/pull/2685) +* Add support go-json, another drop-in json replacement [#2680](https://github.com/gin-gonic/gin/pull/2680) +* Use errors.New to replace fmt.Errorf will much better [#2707](https://github.com/gin-gonic/gin/pull/2707) +* Use Duration.Truncate for truncating precision [#2711](https://github.com/gin-gonic/gin/pull/2711) +* Get client IP when using Cloudflare [#2723](https://github.com/gin-gonic/gin/pull/2723) +* Optimize code adjust [#2700](https://github.com/gin-gonic/gin/pull/2700/files) +* Optimize code and reduce code cyclomatic complexity [#2737](https://github.com/gin-gonic/gin/pull/2737) +* Improve sliceValidateError.Error performance [#2765](https://github.com/gin-gonic/gin/pull/2765) +* Support custom struct tag [#2720](https://github.com/gin-gonic/gin/pull/2720) +* Improve router group tests [#2787](https://github.com/gin-gonic/gin/pull/2787) +* Fallback Context.Deadline() Context.Done() Context.Err() to Context.Request.Context() [#2769](https://github.com/gin-gonic/gin/pull/2769) +* Some codes optimize [#2830](https://github.com/gin-gonic/gin/pull/2830) [#2834](https://github.com/gin-gonic/gin/pull/2834) [#2838](https://github.com/gin-gonic/gin/pull/2838) [#2837](https://github.com/gin-gonic/gin/pull/2837) [#2788](https://github.com/gin-gonic/gin/pull/2788) [#2848](https://github.com/gin-gonic/gin/pull/2848) [#2851](https://github.com/gin-gonic/gin/pull/2851) [#2701](https://github.com/gin-gonic/gin/pull/2701) +* TrustedProxies: Add default IPv6 support and refactor [#2967](https://github.com/gin-gonic/gin/pull/2967) +* Test(route): expose performRequest func [#3012](https://github.com/gin-gonic/gin/pull/3012) +* Support h2c with prior knowledge [#1398](https://github.com/gin-gonic/gin/pull/1398) +* Feat attachment filename support utf8 [#3071](https://github.com/gin-gonic/gin/pull/3071) +* Feat: add StaticFileFS [#2749](https://github.com/gin-gonic/gin/pull/2749) +* Feat(context): return GIN Context from Value method [#2825](https://github.com/gin-gonic/gin/pull/2825) +* Feat: automatically SetMode to TestMode when run go test [#3139](https://github.com/gin-gonic/gin/pull/3139) +* Add TOML bining for gin [#3081](https://github.com/gin-gonic/gin/pull/3081) +* IPv6 add default trusted proxies [#3033](https://github.com/gin-gonic/gin/pull/3033) + +### DOCS + +* Add note about nomsgpack tag to the readme [#2703](https://github.com/gin-gonic/gin/pull/2703) + ## Gin v1.7.7 ### BUGFIXES diff --git a/vendor/github.com/gin-gonic/gin/CONTRIBUTING.md b/vendor/github.com/gin-gonic/gin/CONTRIBUTING.md index 97daa808f..d1c723c67 100644 --- a/vendor/github.com/gin-gonic/gin/CONTRIBUTING.md +++ b/vendor/github.com/gin-gonic/gin/CONTRIBUTING.md @@ -8,6 +8,6 @@ - With pull requests: - Open your pull request against `master` - Your pull request should have no more than two commits, if not you should squash them. - - It should pass all tests in the available continuous integration systems such as TravisCI. + - It should pass all tests in the available continuous integration systems such as GitHub Actions. - You should add/modify tests to cover your proposed code changes. - If your pull request contains a new feature, please document it on the README. diff --git a/vendor/github.com/gin-gonic/gin/Makefile b/vendor/github.com/gin-gonic/gin/Makefile index 1a9919395..5d55b444c 100644 --- a/vendor/github.com/gin-gonic/gin/Makefile +++ b/vendor/github.com/gin-gonic/gin/Makefile @@ -1,5 +1,6 @@ GO ?= go GOFMT ?= gofmt "-s" +GO_VERSION=$(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2) PACKAGES ?= $(shell $(GO) list ./...) VETPACKAGES ?= $(shell $(GO) list ./... | grep -v /examples/) GOFILES := $(shell find . -name "*.go") @@ -67,5 +68,10 @@ misspell: .PHONY: tools tools: - go install golang.org/x/lint/golint; \ - go install github.com/client9/misspell/cmd/misspell; + @if [ $(GO_VERSION) -gt 15 ]; then \ + $(GO) install golang.org/x/lint/golint@latest; \ + $(GO) install github.com/client9/misspell/cmd/misspell@latest; \ + elif [ $(GO_VERSION) -lt 16 ]; then \ + $(GO) install golang.org/x/lint/golint; \ + $(GO) install github.com/client9/misspell/cmd/misspell; \ + fi diff --git a/vendor/github.com/gin-gonic/gin/README.md b/vendor/github.com/gin-gonic/gin/README.md index 9bf459b09..5cc8321b6 100644 --- a/vendor/github.com/gin-gonic/gin/README.md +++ b/vendor/github.com/gin-gonic/gin/README.md @@ -2,7 +2,7 @@ <img align="right" width="159px" src="https://raw.githubusercontent.com/gin-gonic/logo/master/color.png"> -[](https://travis-ci.org/gin-gonic/gin) +[](https://github.com/gin-gonic/gin/actions?query=branch%3Amaster) [](https://codecov.io/gh/gin-gonic/gin) [](https://goreportcard.com/report/github.com/gin-gonic/gin) [](https://pkg.go.dev/github.com/gin-gonic/gin?tab=doc) @@ -23,7 +23,8 @@ Gin is a web framework written in Go (Golang). It features a martini-like API wi - [Quick start](#quick-start) - [Benchmarks](#benchmarks) - [Gin v1. stable](#gin-v1-stable) - - [Build with jsoniter](#build-with-jsoniter) + - [Build with jsoniter/go-json](#build-with-json-replacement) + - [Build without `MsgPack` rendering feature](#build-without-msgpack-rendering-feature) - [API Examples](#api-examples) - [Using GET, POST, PUT, PATCH, DELETE and OPTIONS](#using-get-post-put-patch-delete-and-options) - [Parameters in path](#parameters-in-path) @@ -77,7 +78,7 @@ Gin is a web framework written in Go (Golang). It features a martini-like API wi - [http2 server push](#http2-server-push) - [Define format for the log of routes](#define-format-for-the-log-of-routes) - [Set and get a cookie](#set-and-get-a-cookie) - - [Don't trust all proxies](#don't-trust-all-proxies) + - [Don't trust all proxies](#dont-trust-all-proxies) - [Testing](#testing) - [Users](#users) @@ -85,7 +86,7 @@ Gin is a web framework written in Go (Golang). It features a martini-like API wi To install Gin package, you need to install Go and set your Go workspace first. -1. The first need [Go](https://golang.org/) installed (**version 1.13+ is required**), then you can use the below Go command to install Gin. +1. You first need [Go](https://golang.org/) installed (**version 1.14+ is required**), then you can use the below Go command to install Gin. ```sh $ go get -u github.com/gin-gonic/gin @@ -113,12 +114,16 @@ $ cat example.go ```go package main -import "github.com/gin-gonic/gin" +import ( + "net/http" + + "github.com/gin-gonic/gin" +) func main() { r := gin.Default() r.GET("/ping", func(c *gin.Context) { - c.JSON(200, gin.H{ + c.JSON(http.StatusOK, gin.H{ "message": "pong", }) }) @@ -183,13 +188,28 @@ Gin uses a custom version of [HttpRouter](https://github.com/julienschmidt/httpr - [x] Battle tested. - [x] API frozen, new releases will not break your code. -## Build with [jsoniter](https://github.com/json-iterator/go) +## Build with json replacement -Gin uses `encoding/json` as default json package but you can change to [jsoniter](https://github.com/json-iterator/go) by build from other tags. +Gin uses `encoding/json` as default json package but you can change it by build from other tags. +[jsoniter](https://github.com/json-iterator/go) ```sh $ go build -tags=jsoniter . ``` +[go-json](https://github.com/goccy/go-json) +```sh +$ go build -tags=go_json . +``` + +## Build without `MsgPack` rendering feature + +Gin enables `MsgPack` rendering feature by default. But you can disable this feature by specifying `nomsgpack` build tag. + +```sh +$ go build -tags=nomsgpack . +``` + +This is useful to reduce the binary size of executable files. See the [detail information](https://github.com/gin-gonic/gin/pull/1852). ## API Examples @@ -241,14 +261,15 @@ func main() { // For each matched request Context will hold the route definition router.POST("/user/:name/*action", func(c *gin.Context) { - c.FullPath() == "/user/:name/*action" // true + b := c.FullPath() == "/user/:name/*action" // true + c.String(http.StatusOK, "%t", b) }) // This handler will add a new router for /user/groups. // Exact routes are resolved before param routes, regardless of the order they were defined. // Routes starting with /user/groups are never interpreted as /user/:name/... routes router.GET("/user/groups", func(c *gin.Context) { - c.String(http.StatusOK, "The available groups are [...]", name) + c.String(http.StatusOK, "The available groups are [...]") }) router.Run(":8080") @@ -283,7 +304,7 @@ func main() { message := c.PostForm("message") nick := c.DefaultPostForm("nick", "anonymous") - c.JSON(200, gin.H{ + c.JSON(http.StatusOK, gin.H{ "status": "posted", "message": message, "nick": nick, @@ -367,7 +388,7 @@ func main() { // Set a lower memory limit for multipart forms (default is 32 MiB) router.MaxMultipartMemory = 8 << 20 // 8 MiB router.POST("/upload", func(c *gin.Context) { - // single file + // Single file file, _ := c.FormFile("file") log.Println(file.Filename) @@ -496,6 +517,7 @@ func main() { // nested group testing := authorized.Group("testing") + // visit 0.0.0.0:8080/testing/analytics testing.GET("/analytics", analyticsEndpoint) } @@ -552,7 +574,7 @@ func main() { router := gin.Default() router.GET("/ping", func(c *gin.Context) { - c.String(200, "pong") + c.String(http.StatusOK, "pong") }) router.Run(":8080") @@ -584,7 +606,7 @@ func main() { router.Use(gin.Recovery()) router.GET("/ping", func(c *gin.Context) { - c.String(200, "pong") + c.String(http.StatusOK, "pong") }) router.Run(":8080") @@ -612,7 +634,7 @@ func main() { router := gin.Default() router.GET("/ping", func(c *gin.Context) { - c.String(200, "pong") + c.String(http.StatusOK, "pong") }) router.Run(":8080") @@ -631,7 +653,7 @@ func main() { router := gin.Default() router.GET("/ping", func(c *gin.Context) { - c.String(200, "pong") + c.String(http.StatusOK, "pong") }) router.Run(":8080") @@ -640,7 +662,7 @@ func main() { ### Model binding and validation -To bind a request body into a type, use model binding. We currently support binding of JSON, XML, YAML and standard form values (foo=bar&boo=baz). +To bind a request body into a type, use model binding. We currently support binding of JSON, XML, YAML, TOML and standard form values (foo=bar&boo=baz). Gin uses [**go-playground/validator/v10**](https://github.com/go-playground/validator) for validation. Check the full docs on tags usage [here](https://godoc.org/github.com/go-playground/validator#hdr-Baked_In_Validators_and_Tags). @@ -648,10 +670,10 @@ Note that you need to set the corresponding binding tag on all fields you want t Also, Gin provides two sets of methods for binding: - **Type** - Must bind - - **Methods** - `Bind`, `BindJSON`, `BindXML`, `BindQuery`, `BindYAML`, `BindHeader` + - **Methods** - `Bind`, `BindJSON`, `BindXML`, `BindQuery`, `BindYAML`, `BindHeader`, `BindTOML` - **Behavior** - These methods use `MustBindWith` under the hood. If there is a binding error, the request is aborted with `c.AbortWithError(400, err).SetType(ErrorTypeBind)`. This sets the response status code to 400 and the `Content-Type` header is set to `text/plain; charset=utf-8`. Note that if you try to set the response code after this, it will result in a warning `[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422`. If you wish to have greater control over the behavior, consider using the `ShouldBind` equivalent method. - **Type** - Should bind - - **Methods** - `ShouldBind`, `ShouldBindJSON`, `ShouldBindXML`, `ShouldBindQuery`, `ShouldBindYAML`, `ShouldBindHeader` + - **Methods** - `ShouldBind`, `ShouldBindJSON`, `ShouldBindXML`, `ShouldBindQuery`, `ShouldBindYAML`, `ShouldBindHeader`, `ShouldBindTOML`, - **Behavior** - These methods use `ShouldBindWith` under the hood. If there is a binding error, the error is returned and it is the developer's responsibility to handle the request and error appropriately. When using the Bind-method, Gin tries to infer the binder depending on the Content-Type header. If you are sure what you are binding, you can use `MustBindWith` or `ShouldBindWith`. @@ -687,7 +709,7 @@ func main() { // Example for binding XML ( // <?xml version="1.0" encoding="UTF-8"?> // <root> - // <user>user</user> + // <user>manu</user> // <password>123</password> // </root>) router.POST("/loginXML", func(c *gin.Context) { @@ -830,6 +852,7 @@ package main import ( "log" + "net/http" "github.com/gin-gonic/gin" ) @@ -852,7 +875,7 @@ func startPage(c *gin.Context) { log.Println(person.Name) log.Println(person.Address) } - c.String(200, "Success") + c.String(http.StatusOK, "Success") } ``` @@ -866,6 +889,7 @@ package main import ( "log" + "net/http" "time" "github.com/gin-gonic/gin" @@ -889,7 +913,7 @@ func startPage(c *gin.Context) { var person Person // If `GET`, only `Form` binding engine (`query`) used. // If `POST`, first checks the `content-type` for `JSON` or `XML`, then uses `Form` (`form-data`). - // See more at https://github.com/gin-gonic/gin/blob/master/binding/binding.go#L48 + // See more at https://github.com/gin-gonic/gin/blob/master/binding/binding.go#L88 if c.ShouldBind(&person) == nil { log.Println(person.Name) log.Println(person.Address) @@ -898,7 +922,7 @@ func startPage(c *gin.Context) { log.Println(person.UnixTime) } - c.String(200, "Success") + c.String(http.StatusOK, "Success") } ``` @@ -914,7 +938,11 @@ See the [detail information](https://github.com/gin-gonic/gin/issues/846). ```go package main -import "github.com/gin-gonic/gin" +import ( + "net/http" + + "github.com/gin-gonic/gin" +) type Person struct { ID string `uri:"id" binding:"required,uuid"` @@ -926,10 +954,10 @@ func main() { route.GET("/:name/:id", func(c *gin.Context) { var person Person if err := c.ShouldBindUri(&person); err != nil { - c.JSON(400, gin.H{"msg": err}) + c.JSON(http.StatusBadRequest, gin.H{"msg": err.Error()}) return } - c.JSON(200, gin.H{"name": person.Name, "uuid": person.ID}) + c.JSON(http.StatusOK, gin.H{"name": person.Name, "uuid": person.ID}) }) route.Run(":8088") } @@ -948,6 +976,8 @@ package main import ( "fmt" + "net/http" + "github.com/gin-gonic/gin" ) @@ -962,11 +992,11 @@ func main() { h := testHeader{} if err := c.ShouldBindHeader(&h); err != nil { - c.JSON(200, err) + c.JSON(http.StatusOK, err) } fmt.Printf("%#v\n", h) - c.JSON(200, gin.H{"Rate": h.Rate, "Domain": h.Domain}) + c.JSON(http.StatusOK, gin.H{"Rate": h.Rate, "Domain": h.Domain}) }) r.Run() @@ -996,7 +1026,7 @@ type myForm struct { func formHandler(c *gin.Context) { var fakeForm myForm c.ShouldBind(&fakeForm) - c.JSON(200, gin.H{"color": fakeForm.Colors}) + c.JSON(http.StatusOK, gin.H{"color": fakeForm.Colors}) } ... @@ -1201,14 +1231,14 @@ func main() { // Serves unicode entities r.GET("/json", func(c *gin.Context) { - c.JSON(200, gin.H{ + c.JSON(http.StatusOK, gin.H{ "html": "<b>Hello, world!</b>", }) }) // Serves literal characters r.GET("/purejson", func(c *gin.Context) { - c.PureJSON(200, gin.H{ + c.PureJSON(http.StatusOK, gin.H{ "html": "<b>Hello, world!</b>", }) }) @@ -1226,7 +1256,8 @@ func main() { router.Static("/assets", "./assets") router.StaticFS("/more_static", http.Dir("my_file_system")) router.StaticFile("/favicon.ico", "./resources/favicon.ico") - + router.StaticFileFS("/more_favicon.ico", "more_favicon.ico", http.Dir("my_file_system")) + // Listen and serve on 0.0.0.0:8080 router.Run(":8080") } @@ -1392,7 +1423,7 @@ import ( func formatAsDate(t time.Time) string { year, month, day := t.Date() - return fmt.Sprintf("%d%02d/%02d", year, month, day) + return fmt.Sprintf("%d/%02d/%02d", year, month, day) } func main() { @@ -1454,7 +1485,7 @@ r.GET("/test", func(c *gin.Context) { r.HandleContext(c) }) r.GET("/test2", func(c *gin.Context) { - c.JSON(200, gin.H{"hello": "world"}) + c.JSON(http.StatusOK, gin.H{"hello": "world"}) }) ``` @@ -1607,6 +1638,7 @@ package main import ( "log" + "net/http" "github.com/gin-gonic/autotls" "github.com/gin-gonic/gin" @@ -1617,7 +1649,7 @@ func main() { // Ping handler r.GET("/ping", func(c *gin.Context) { - c.String(200, "pong") + c.String(http.StatusOK, "pong") }) log.Fatal(autotls.Run(r, "example1.com", "example2.com")) @@ -1631,6 +1663,7 @@ package main import ( "log" + "net/http" "github.com/gin-gonic/autotls" "github.com/gin-gonic/gin" @@ -1642,7 +1675,7 @@ func main() { // Ping handler r.GET("/ping", func(c *gin.Context) { - c.String(200, "pong") + c.String(http.StatusOK, "pong") }) m := autocert.Manager{ @@ -1811,7 +1844,7 @@ func main() { quit := make(chan os.Signal) // kill (no param) default send syscall.SIGTERM // kill -2 is syscall.SIGINT - // kill -9 is syscall.SIGKILL but can't be catch, so don't need add it + // kill -9 is syscall.SIGKILL but can't be caught, so don't need to add it signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit log.Println("Shutting down server...") @@ -1903,7 +1936,7 @@ type StructD struct { func GetDataB(c *gin.Context) { var b StructB c.Bind(&b) - c.JSON(200, gin.H{ + c.JSON(http.StatusOK, gin.H{ "a": b.NestedStruct, "b": b.FieldB, }) @@ -1912,7 +1945,7 @@ func GetDataB(c *gin.Context) { func GetDataC(c *gin.Context) { var b StructC c.Bind(&b) - c.JSON(200, gin.H{ + c.JSON(http.StatusOK, gin.H{ "a": b.NestedStructPointer, "c": b.FieldC, }) @@ -1921,7 +1954,7 @@ func GetDataC(c *gin.Context) { func GetDataD(c *gin.Context) { var b StructD c.Bind(&b) - c.JSON(200, gin.H{ + c.JSON(http.StatusOK, gin.H{ "x": b.NestedAnonyStruct, "d": b.FieldD, }) @@ -1984,7 +2017,7 @@ func SomeHandler(c *gin.Context) { objA := formA{} objB := formB{} // This reads c.Request.Body and stores the result into the context. - if errA := c.ShouldBindBodyWith(&objA, binding.JSON); errA == nil { + if errA := c.ShouldBindBodyWith(&objA, binding.Form); errA == nil { c.String(http.StatusOK, `the body should be formA`) // At this time, it reuses body stored in the context. } else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil { @@ -2006,6 +2039,61 @@ enough to call binding at once. can be called by `c.ShouldBind()` multiple times without any damage to performance (See [#1341](https://github.com/gin-gonic/gin/pull/1341)). +### Bind form-data request with custom struct and custom tag + +```go +const ( + customerTag = "url" + defaultMemory = 32 << 20 +) + +type customerBinding struct {} + +func (customerBinding) Name() string { + return "form" +} + +func (customerBinding) Bind(req *http.Request, obj interface{}) error { + if err := req.ParseForm(); err != nil { + return err + } + if err := req.ParseMultipartForm(defaultMemory); err != nil { + if err != http.ErrNotMultipart { + return err + } + } + if err := binding.MapFormWithTag(obj, req.Form, customerTag); err != nil { + return err + } + return validate(obj) +} + +func validate(obj interface{}) error { + if binding.Validator == nil { + return nil + } + return binding.Validator.ValidateStruct(obj) +} + +// Now we can do this!!! +// FormA is a external type that we can't modify it's tag +type FormA struct { + FieldA string `url:"field_a"` +} + +func ListHandler(s *Service) func(ctx *gin.Context) { + return func(ctx *gin.Context) { + var urlBinding = customerBinding{} + var opt FormA + err := ctx.MustBindWith(&opt, urlBinding) + if err != nil { + ... + } + ... + } +} +``` + ### http2 server push http.Pusher is supported only **go1.8+**. See the [golang blog](https://blog.golang.org/h2push) for detail information. @@ -2016,6 +2104,7 @@ package main import ( "html/template" "log" + "net/http" "github.com/gin-gonic/gin" ) @@ -2044,7 +2133,7 @@ func main() { log.Printf("Failed to push: %v", err) } } - c.HTML(200, "https", gin.H{ + c.HTML(http.StatusOK, "https", gin.H{ "status": "success", }) }) @@ -2200,10 +2289,16 @@ The `net/http/httptest` package is preferable way for HTTP testing. ```go package main +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + func setupRouter() *gin.Engine { r := gin.Default() r.GET("/ping", func(c *gin.Context) { - c.String(200, "pong") + c.String(http.StatusOK, "pong") }) return r } @@ -2231,10 +2326,10 @@ func TestPingRoute(t *testing.T) { router := setupRouter() w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/ping", nil) + req, _ := http.NewRequest(http.MethodGet, "/ping", nil) router.ServeHTTP(w, req) - assert.Equal(t, 200, w.Code) + assert.Equal(t, http.StatusOK, w.Code) assert.Equal(t, "pong", w.Body.String()) } ``` @@ -2250,3 +2345,4 @@ Awesome project lists using [Gin](https://github.com/gin-gonic/gin) web framewor * [picfit](https://github.com/thoas/picfit): An image resizing server written in Go. * [brigade](https://github.com/brigadecore/brigade): Event-based Scripting for Kubernetes. * [dkron](https://github.com/distribworks/dkron): Distributed, fault tolerant job scheduling system. + diff --git a/vendor/github.com/gin-gonic/gin/any.go b/vendor/github.com/gin-gonic/gin/any.go new file mode 100644 index 000000000..42b1ea46f --- /dev/null +++ b/vendor/github.com/gin-gonic/gin/any.go @@ -0,0 +1,10 @@ +// Copyright 2022 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +//go:build !go1.18 +// +build !go1.18 + +package gin + +type any = interface{} diff --git a/vendor/github.com/gin-gonic/gin/auth.go b/vendor/github.com/gin-gonic/gin/auth.go index 4d8a6ce48..2503c5156 100644 --- a/vendor/github.com/gin-gonic/gin/auth.go +++ b/vendor/github.com/gin-gonic/gin/auth.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -31,7 +31,7 @@ func (a authPairs) searchCredential(authValue string) (string, bool) { return "", false } for _, pair := range a { - if subtle.ConstantTimeCompare([]byte(pair.value), []byte(authValue)) == 1 { + if subtle.ConstantTimeCompare(bytesconv.StringToBytes(pair.value), bytesconv.StringToBytes(authValue)) == 1 { return pair.user, true } } diff --git a/vendor/github.com/gin-gonic/gin/binding/any.go b/vendor/github.com/gin-gonic/gin/binding/any.go new file mode 100644 index 000000000..d8251a7c2 --- /dev/null +++ b/vendor/github.com/gin-gonic/gin/binding/any.go @@ -0,0 +1,10 @@ +// Copyright 2022 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +//go:build !go1.18 +// +build !go1.18 + +package binding + +type any = interface{} diff --git a/vendor/github.com/gin-gonic/gin/binding/binding.go b/vendor/github.com/gin-gonic/gin/binding/binding.go index 5caeb581a..a58924ed3 100644 --- a/vendor/github.com/gin-gonic/gin/binding/binding.go +++ b/vendor/github.com/gin-gonic/gin/binding/binding.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -22,6 +22,7 @@ const ( MIMEMSGPACK = "application/x-msgpack" MIMEMSGPACK2 = "application/msgpack" MIMEYAML = "application/x-yaml" + MIMETOML = "application/toml" ) // Binding describes the interface which needs to be implemented for binding the @@ -29,27 +30,27 @@ const ( // the form POST. type Binding interface { Name() string - Bind(*http.Request, interface{}) error + Bind(*http.Request, any) error } // BindingBody adds BindBody method to Binding. BindBody is similar with Bind, // but it reads the body from supplied bytes instead of req.Body. type BindingBody interface { Binding - BindBody([]byte, interface{}) error + BindBody([]byte, any) error } // BindingUri adds BindUri method to Binding. BindUri is similar with Bind, -// but it read the Params. +// but it reads the Params. type BindingUri interface { Name() string - BindUri(map[string][]string, interface{}) error + BindUri(map[string][]string, any) error } // StructValidator is the minimal interface which needs to be implemented in // order for it to be used as the validator engine for ensuring the correctness // of the request. Gin provides a default implementation for this using -// https://github.com/go-playground/validator/tree/v8.18.2. +// https://github.com/go-playground/validator/tree/v10.6.1. type StructValidator interface { // ValidateStruct can receive any kind of type and it should never panic, even if the configuration is not right. // If the received type is a slice|array, the validation should be performed travel on every element. @@ -57,15 +58,15 @@ type StructValidator interface { // If the received type is a struct or pointer to a struct, the validation should be performed. // If the struct is not valid or the validation itself fails, a descriptive error should be returned. // Otherwise nil must be returned. - ValidateStruct(interface{}) error + ValidateStruct(any) error // Engine returns the underlying validator engine which powers the // StructValidator implementation. - Engine() interface{} + Engine() any } // Validator is the default validator which implements the StructValidator -// interface. It uses https://github.com/go-playground/validator/tree/v8.18.2 +// interface. It uses https://github.com/go-playground/validator/tree/v10.6.1 // under the hood. var Validator StructValidator = &defaultValidator{} @@ -83,6 +84,7 @@ var ( YAML = yamlBinding{} Uri = uriBinding{} Header = headerBinding{} + TOML = tomlBinding{} ) // Default returns the appropriate Binding instance based on the HTTP method @@ -103,6 +105,8 @@ func Default(method, contentType string) Binding { return MsgPack case MIMEYAML: return YAML + case MIMETOML: + return TOML case MIMEMultipartPOSTForm: return FormMultipart default: // case MIMEPOSTForm: @@ -110,7 +114,7 @@ func Default(method, contentType string) Binding { } } -func validate(obj interface{}) error { +func validate(obj any) error { if Validator == nil { return nil } diff --git a/vendor/github.com/gin-gonic/gin/binding/binding_nomsgpack.go b/vendor/github.com/gin-gonic/gin/binding/binding_nomsgpack.go index 9afa3dcf6..7f6a904ab 100644 --- a/vendor/github.com/gin-gonic/gin/binding/binding_nomsgpack.go +++ b/vendor/github.com/gin-gonic/gin/binding/binding_nomsgpack.go @@ -20,6 +20,7 @@ const ( MIMEMultipartPOSTForm = "multipart/form-data" MIMEPROTOBUF = "application/x-protobuf" MIMEYAML = "application/x-yaml" + MIMETOML = "application/toml" ) // Binding describes the interface which needs to be implemented for binding the @@ -27,42 +28,42 @@ const ( // the form POST. type Binding interface { Name() string - Bind(*http.Request, interface{}) error + Bind(*http.Request, any) error } // BindingBody adds BindBody method to Binding. BindBody is similar with Bind, // but it reads the body from supplied bytes instead of req.Body. type BindingBody interface { Binding - BindBody([]byte, interface{}) error + BindBody([]byte, any) error } // BindingUri adds BindUri method to Binding. BindUri is similar with Bind, -// but it read the Params. +// but it reads the Params. type BindingUri interface { Name() string - BindUri(map[string][]string, interface{}) error + BindUri(map[string][]string, any) error } // StructValidator is the minimal interface which needs to be implemented in // order for it to be used as the validator engine for ensuring the correctness // of the request. Gin provides a default implementation for this using -// https://github.com/go-playground/validator/tree/v8.18.2. +// https://github.com/go-playground/validator/tree/v10.6.1. type StructValidator interface { // ValidateStruct can receive any kind of type and it should never panic, even if the configuration is not right. // If the received type is not a struct, any validation should be skipped and nil must be returned. // If the received type is a struct or pointer to a struct, the validation should be performed. // If the struct is not valid or the validation itself fails, a descriptive error should be returned. // Otherwise nil must be returned. - ValidateStruct(interface{}) error + ValidateStruct(any) error // Engine returns the underlying validator engine which powers the // StructValidator implementation. - Engine() interface{} + Engine() any } // Validator is the default validator which implements the StructValidator -// interface. It uses https://github.com/go-playground/validator/tree/v8.18.2 +// interface. It uses https://github.com/go-playground/validator/tree/v10.6.1 // under the hood. var Validator StructValidator = &defaultValidator{} @@ -79,6 +80,7 @@ var ( YAML = yamlBinding{} Uri = uriBinding{} Header = headerBinding{} + TOML = tomlBinding{} ) // Default returns the appropriate Binding instance based on the HTTP method @@ -99,12 +101,14 @@ func Default(method, contentType string) Binding { return YAML case MIMEMultipartPOSTForm: return FormMultipart + case MIMETOML: + return TOML default: // case MIMEPOSTForm: return Form } } -func validate(obj interface{}) error { +func validate(obj any) error { if Validator == nil { return nil } diff --git a/vendor/github.com/gin-gonic/gin/binding/default_validator.go b/vendor/github.com/gin-gonic/gin/binding/default_validator.go index c57a120fc..c03afe75b 100644 --- a/vendor/github.com/gin-gonic/gin/binding/default_validator.go +++ b/vendor/github.com/gin-gonic/gin/binding/default_validator.go @@ -1,4 +1,4 @@ -// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -18,23 +18,35 @@ type defaultValidator struct { validate *validator.Validate } -type sliceValidateError []error +type SliceValidationError []error -func (err sliceValidateError) Error() string { - var errMsgs []string - for i, e := range err { - if e == nil { - continue +// Error concatenates all error elements in SliceValidationError into a single string separated by \n. +func (err SliceValidationError) Error() string { + n := len(err) + switch n { + case 0: + return "" + default: + var b strings.Builder + if err[0] != nil { + fmt.Fprintf(&b, "[%d]: %s", 0, err[0].Error()) + } + if n > 1 { + for i := 1; i < n; i++ { + if err[i] != nil { + b.WriteString("\n") + fmt.Fprintf(&b, "[%d]: %s", i, err[i].Error()) + } + } } - errMsgs = append(errMsgs, fmt.Sprintf("[%d]: %s", i, e.Error())) + return b.String() } - return strings.Join(errMsgs, "\n") } var _ StructValidator = &defaultValidator{} // ValidateStruct receives any kind of type, but only performed struct or pointer to struct type. -func (v *defaultValidator) ValidateStruct(obj interface{}) error { +func (v *defaultValidator) ValidateStruct(obj any) error { if obj == nil { return nil } @@ -47,7 +59,7 @@ func (v *defaultValidator) ValidateStruct(obj interface{}) error { return v.validateStruct(obj) case reflect.Slice, reflect.Array: count := value.Len() - validateRet := make(sliceValidateError, 0) + validateRet := make(SliceValidationError, 0) for i := 0; i < count; i++ { if err := v.ValidateStruct(value.Index(i).Interface()); err != nil { validateRet = append(validateRet, err) @@ -63,7 +75,7 @@ func (v *defaultValidator) ValidateStruct(obj interface{}) error { } // validateStruct receives struct type -func (v *defaultValidator) validateStruct(obj interface{}) error { +func (v *defaultValidator) validateStruct(obj any) error { v.lazyinit() return v.validate.Struct(obj) } @@ -71,8 +83,8 @@ func (v *defaultValidator) validateStruct(obj interface{}) error { // Engine returns the underlying validator engine which powers the default // Validator instance. This is useful if you want to register custom validations // or struct level validations. See validator GoDoc for more info - -// https://godoc.org/gopkg.in/go-playground/validator.v8 -func (v *defaultValidator) Engine() interface{} { +// https://pkg.go.dev/github.com/go-playground/validator/v10 +func (v *defaultValidator) Engine() any { v.lazyinit() return v.validate } diff --git a/vendor/github.com/gin-gonic/gin/binding/form.go b/vendor/github.com/gin-gonic/gin/binding/form.go index b93c34cf4..b17352bad 100644 --- a/vendor/github.com/gin-gonic/gin/binding/form.go +++ b/vendor/github.com/gin-gonic/gin/binding/form.go @@ -1,10 +1,11 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. package binding import ( + "errors" "net/http" ) @@ -18,14 +19,12 @@ func (formBinding) Name() string { return "form" } -func (formBinding) Bind(req *http.Request, obj interface{}) error { +func (formBinding) Bind(req *http.Request, obj any) error { if err := req.ParseForm(); err != nil { return err } - if err := req.ParseMultipartForm(defaultMemory); err != nil { - if err != http.ErrNotMultipart { - return err - } + if err := req.ParseMultipartForm(defaultMemory); err != nil && !errors.Is(err, http.ErrNotMultipart) { + return err } if err := mapForm(obj, req.Form); err != nil { return err @@ -37,7 +36,7 @@ func (formPostBinding) Name() string { return "form-urlencoded" } -func (formPostBinding) Bind(req *http.Request, obj interface{}) error { +func (formPostBinding) Bind(req *http.Request, obj any) error { if err := req.ParseForm(); err != nil { return err } @@ -51,7 +50,7 @@ func (formMultipartBinding) Name() string { return "multipart/form-data" } -func (formMultipartBinding) Bind(req *http.Request, obj interface{}) error { +func (formMultipartBinding) Bind(req *http.Request, obj any) error { if err := req.ParseMultipartForm(defaultMemory); err != nil { return err } diff --git a/vendor/github.com/gin-gonic/gin/binding/form_mapping.go b/vendor/github.com/gin-gonic/gin/binding/form_mapping.go index 2f4e45b40..98cebfecf 100644 --- a/vendor/github.com/gin-gonic/gin/binding/form_mapping.go +++ b/vendor/github.com/gin-gonic/gin/binding/form_mapping.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -16,22 +16,34 @@ import ( "github.com/gin-gonic/gin/internal/json" ) -var errUnknownType = errors.New("unknown type") +var ( + errUnknownType = errors.New("unknown type") -func mapUri(ptr interface{}, m map[string][]string) error { + // ErrConvertMapStringSlice can not covert to map[string][]string + ErrConvertMapStringSlice = errors.New("can not convert to map slices of strings") + + // ErrConvertToMapString can not convert to map[string]string + ErrConvertToMapString = errors.New("can not convert to map of strings") +) + +func mapURI(ptr any, m map[string][]string) error { return mapFormByTag(ptr, m, "uri") } -func mapForm(ptr interface{}, form map[string][]string) error { +func mapForm(ptr any, form map[string][]string) error { return mapFormByTag(ptr, form, "form") } +func MapFormWithTag(ptr any, form map[string][]string, tag string) error { + return mapFormByTag(ptr, form, tag) +} + var emptyField = reflect.StructField{} -func mapFormByTag(ptr interface{}, form map[string][]string, tag string) error { +func mapFormByTag(ptr any, form map[string][]string, tag string) error { // Check if ptr is a map ptrVal := reflect.ValueOf(ptr) - var pointed interface{} + var pointed any if ptrVal.Kind() == reflect.Ptr { ptrVal = ptrVal.Elem() pointed = ptrVal.Interface() @@ -49,7 +61,7 @@ func mapFormByTag(ptr interface{}, form map[string][]string, tag string) error { // setter tries to set value on a walking by fields of a struct type setter interface { - TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (isSetted bool, err error) + TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (isSet bool, err error) } type formSource map[string][]string @@ -57,11 +69,11 @@ type formSource map[string][]string var _ setter = formSource(nil) // TrySet tries to set a value by request's form source (like map[string][]string) -func (form formSource) TrySet(value reflect.Value, field reflect.StructField, tagValue string, opt setOptions) (isSetted bool, err error) { +func (form formSource) TrySet(value reflect.Value, field reflect.StructField, tagValue string, opt setOptions) (isSet bool, err error) { return setByForm(value, field, form, tagValue, opt) } -func mappingByPtr(ptr interface{}, setter setter, tag string) error { +func mappingByPtr(ptr any, setter setter, tag string) error { _, err := mapping(reflect.ValueOf(ptr), emptyField, setter, tag) return err } @@ -71,7 +83,7 @@ func mapping(value reflect.Value, field reflect.StructField, setter setter, tag return false, nil } - var vKind = value.Kind() + vKind := value.Kind() if vKind == reflect.Ptr { var isNew bool @@ -80,14 +92,14 @@ func mapping(value reflect.Value, field reflect.StructField, setter setter, tag isNew = true vPtr = reflect.New(value.Type().Elem()) } - isSetted, err := mapping(vPtr.Elem(), field, setter, tag) + isSet, err := mapping(vPtr.Elem(), field, setter, tag) if err != nil { return false, err } - if isNew && isSetted { + if isNew && isSet { value.Set(vPtr) } - return isSetted, nil + return isSet, nil } if vKind != reflect.Struct || !field.Anonymous { @@ -103,19 +115,19 @@ func mapping(value reflect.Value, field reflect.StructField, setter setter, tag if vKind == reflect.Struct { tValue := value.Type() - var isSetted bool + var isSet bool for i := 0; i < value.NumField(); i++ { sf := tValue.Field(i) if sf.PkgPath != "" && !sf.Anonymous { // unexported continue } - ok, err := mapping(value.Field(i), tValue.Field(i), setter, tag) + ok, err := mapping(value.Field(i), sf, setter, tag) if err != nil { return false, err } - isSetted = isSetted || ok + isSet = isSet || ok } - return isSetted, nil + return isSet, nil } return false, nil } @@ -152,7 +164,7 @@ func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter return setter.TrySet(value, field, tagValue, setOpt) } -func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSetted bool, err error) { +func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSet bool, err error) { vs, ok := form[tagValue] if !ok && !opt.isDefaultExists { return false, nil @@ -198,7 +210,7 @@ func setWithProperType(val string, value reflect.Value, field reflect.StructFiel case reflect.Int64: switch value.Interface().(type) { case time.Duration: - return setTimeDuration(val, value, field) + return setTimeDuration(val, value) } return setIntField(val, 64, value) case reflect.Uint: @@ -298,7 +310,6 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val t := time.Unix(tv/int64(d), tv%int64(d)) value.Set(reflect.ValueOf(t)) return nil - } if val == "" { @@ -348,7 +359,7 @@ func setSlice(vals []string, value reflect.Value, field reflect.StructField) err return nil } -func setTimeDuration(val string, value reflect.Value, field reflect.StructField) error { +func setTimeDuration(val string, value reflect.Value) error { d, err := time.ParseDuration(val) if err != nil { return err @@ -365,13 +376,13 @@ func head(str, sep string) (head string, tail string) { return str[:idx], str[idx+len(sep):] } -func setFormMap(ptr interface{}, form map[string][]string) error { +func setFormMap(ptr any, form map[string][]string) error { el := reflect.TypeOf(ptr).Elem() if el.Kind() == reflect.Slice { ptrMap, ok := ptr.(map[string][]string) if !ok { - return errors.New("cannot convert to map slices of strings") + return ErrConvertMapStringSlice } for k, v := range form { ptrMap[k] = v @@ -382,7 +393,7 @@ func setFormMap(ptr interface{}, form map[string][]string) error { ptrMap, ok := ptr.(map[string]string) if !ok { - return errors.New("cannot convert to map of strings") + return ErrConvertToMapString } for k, v := range form { ptrMap[k] = v[len(v)-1] // pick last diff --git a/vendor/github.com/gin-gonic/gin/binding/header.go b/vendor/github.com/gin-gonic/gin/binding/header.go index 179ce4ea2..03bc78dae 100644 --- a/vendor/github.com/gin-gonic/gin/binding/header.go +++ b/vendor/github.com/gin-gonic/gin/binding/header.go @@ -1,3 +1,7 @@ +// Copyright 2022 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + package binding import ( @@ -12,7 +16,7 @@ func (headerBinding) Name() string { return "header" } -func (headerBinding) Bind(req *http.Request, obj interface{}) error { +func (headerBinding) Bind(req *http.Request, obj any) error { if err := mapHeader(obj, req.Header); err != nil { return err @@ -21,7 +25,7 @@ func (headerBinding) Bind(req *http.Request, obj interface{}) error { return validate(obj) } -func mapHeader(ptr interface{}, h map[string][]string) error { +func mapHeader(ptr any, h map[string][]string) error { return mappingByPtr(ptr, headerSource(h), "header") } @@ -29,6 +33,6 @@ type headerSource map[string][]string var _ setter = headerSource(nil) -func (hs headerSource) TrySet(value reflect.Value, field reflect.StructField, tagValue string, opt setOptions) (isSetted bool, err error) { +func (hs headerSource) TrySet(value reflect.Value, field reflect.StructField, tagValue string, opt setOptions) (bool, error) { return setByForm(value, field, hs, textproto.CanonicalMIMEHeaderKey(tagValue), opt) } diff --git a/vendor/github.com/gin-gonic/gin/binding/json.go b/vendor/github.com/gin-gonic/gin/binding/json.go index d62e07059..36eb27a34 100644 --- a/vendor/github.com/gin-gonic/gin/binding/json.go +++ b/vendor/github.com/gin-gonic/gin/binding/json.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -6,7 +6,7 @@ package binding import ( "bytes" - "fmt" + "errors" "io" "net/http" @@ -30,18 +30,18 @@ func (jsonBinding) Name() string { return "json" } -func (jsonBinding) Bind(req *http.Request, obj interface{}) error { +func (jsonBinding) Bind(req *http.Request, obj any) error { if req == nil || req.Body == nil { - return fmt.Errorf("invalid request") + return errors.New("invalid request") } return decodeJSON(req.Body, obj) } -func (jsonBinding) BindBody(body []byte, obj interface{}) error { +func (jsonBinding) BindBody(body []byte, obj any) error { return decodeJSON(bytes.NewReader(body), obj) } -func decodeJSON(r io.Reader, obj interface{}) error { +func decodeJSON(r io.Reader, obj any) error { decoder := json.NewDecoder(r) if EnableDecoderUseNumber { decoder.UseNumber() diff --git a/vendor/github.com/gin-gonic/gin/binding/msgpack.go b/vendor/github.com/gin-gonic/gin/binding/msgpack.go index 2a442996a..d1f035e44 100644 --- a/vendor/github.com/gin-gonic/gin/binding/msgpack.go +++ b/vendor/github.com/gin-gonic/gin/binding/msgpack.go @@ -1,4 +1,4 @@ -// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -21,15 +21,15 @@ func (msgpackBinding) Name() string { return "msgpack" } -func (msgpackBinding) Bind(req *http.Request, obj interface{}) error { +func (msgpackBinding) Bind(req *http.Request, obj any) error { return decodeMsgPack(req.Body, obj) } -func (msgpackBinding) BindBody(body []byte, obj interface{}) error { +func (msgpackBinding) BindBody(body []byte, obj any) error { return decodeMsgPack(bytes.NewReader(body), obj) } -func decodeMsgPack(r io.Reader, obj interface{}) error { +func decodeMsgPack(r io.Reader, obj any) error { cdc := new(codec.MsgpackHandle) if err := codec.NewDecoder(r, cdc).Decode(&obj); err != nil { return err diff --git a/vendor/github.com/gin-gonic/gin/binding/multipart_form_mapping.go b/vendor/github.com/gin-gonic/gin/binding/multipart_form_mapping.go index f85a1aa60..4ebe83263 100644 --- a/vendor/github.com/gin-gonic/gin/binding/multipart_form_mapping.go +++ b/vendor/github.com/gin-gonic/gin/binding/multipart_form_mapping.go @@ -1,4 +1,4 @@ -// Copyright 2019 Gin Core Team. All rights reserved. +// Copyright 2019 Gin Core Team. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -15,8 +15,16 @@ type multipartRequest http.Request var _ setter = (*multipartRequest)(nil) +var ( + // ErrMultiFileHeader multipart.FileHeader invalid + ErrMultiFileHeader = errors.New("unsupported field type for multipart.FileHeader") + + // ErrMultiFileHeaderLenInvalid array for []*multipart.FileHeader len invalid + ErrMultiFileHeaderLenInvalid = errors.New("unsupported len of array for []*multipart.FileHeader") +) + // TrySet tries to set a value by the multipart request with the binding a form file -func (r *multipartRequest) TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (isSetted bool, err error) { +func (r *multipartRequest) TrySet(value reflect.Value, field reflect.StructField, key string, opt setOptions) (bool, error) { if files := r.MultipartForm.File[key]; len(files) != 0 { return setByMultipartFormFile(value, field, files) } @@ -24,7 +32,7 @@ func (r *multipartRequest) TrySet(value reflect.Value, field reflect.StructField return setByForm(value, field, r.MultipartForm.Value, key, opt) } -func setByMultipartFormFile(value reflect.Value, field reflect.StructField, files []*multipart.FileHeader) (isSetted bool, err error) { +func setByMultipartFormFile(value reflect.Value, field reflect.StructField, files []*multipart.FileHeader) (isSet bool, err error) { switch value.Kind() { case reflect.Ptr: switch value.Interface().(type) { @@ -40,26 +48,26 @@ func setByMultipartFormFile(value reflect.Value, field reflect.StructField, file } case reflect.Slice: slice := reflect.MakeSlice(value.Type(), len(files), len(files)) - isSetted, err = setArrayOfMultipartFormFiles(slice, field, files) - if err != nil || !isSetted { - return isSetted, err + isSet, err = setArrayOfMultipartFormFiles(slice, field, files) + if err != nil || !isSet { + return isSet, err } value.Set(slice) return true, nil case reflect.Array: return setArrayOfMultipartFormFiles(value, field, files) } - return false, errors.New("unsupported field type for multipart.FileHeader") + return false, ErrMultiFileHeader } -func setArrayOfMultipartFormFiles(value reflect.Value, field reflect.StructField, files []*multipart.FileHeader) (isSetted bool, err error) { +func setArrayOfMultipartFormFiles(value reflect.Value, field reflect.StructField, files []*multipart.FileHeader) (isSet bool, err error) { if value.Len() != len(files) { - return false, errors.New("unsupported len of array for []*multipart.FileHeader") + return false, ErrMultiFileHeaderLenInvalid } for i := range files { - setted, err := setByMultipartFormFile(value.Index(i), field, files[i:i+1]) - if err != nil || !setted { - return setted, err + set, err := setByMultipartFormFile(value.Index(i), field, files[i:i+1]) + if err != nil || !set { + return set, err } } return true, nil diff --git a/vendor/github.com/gin-gonic/gin/binding/protobuf.go b/vendor/github.com/gin-gonic/gin/binding/protobuf.go index f9ece928d..44f2fdb93 100644 --- a/vendor/github.com/gin-gonic/gin/binding/protobuf.go +++ b/vendor/github.com/gin-gonic/gin/binding/protobuf.go @@ -1,14 +1,15 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. package binding import ( + "errors" "io/ioutil" "net/http" - "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/proto" ) type protobufBinding struct{} @@ -17,7 +18,7 @@ func (protobufBinding) Name() string { return "protobuf" } -func (b protobufBinding) Bind(req *http.Request, obj interface{}) error { +func (b protobufBinding) Bind(req *http.Request, obj any) error { buf, err := ioutil.ReadAll(req.Body) if err != nil { return err @@ -25,8 +26,12 @@ func (b protobufBinding) Bind(req *http.Request, obj interface{}) error { return b.BindBody(buf, obj) } -func (protobufBinding) BindBody(body []byte, obj interface{}) error { - if err := proto.Unmarshal(body, obj.(proto.Message)); err != nil { +func (protobufBinding) BindBody(body []byte, obj any) error { + msg, ok := obj.(proto.Message) + if !ok { + return errors.New("obj is not ProtoMessage") + } + if err := proto.Unmarshal(body, msg); err != nil { return err } // Here it's same to return validate(obj), but util now we can't add diff --git a/vendor/github.com/gin-gonic/gin/binding/query.go b/vendor/github.com/gin-gonic/gin/binding/query.go index 219743f2a..c958b88bd 100644 --- a/vendor/github.com/gin-gonic/gin/binding/query.go +++ b/vendor/github.com/gin-gonic/gin/binding/query.go @@ -1,4 +1,4 @@ -// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -12,7 +12,7 @@ func (queryBinding) Name() string { return "query" } -func (queryBinding) Bind(req *http.Request, obj interface{}) error { +func (queryBinding) Bind(req *http.Request, obj any) error { values := req.URL.Query() if err := mapForm(obj, values); err != nil { return err diff --git a/vendor/github.com/gin-gonic/gin/binding/toml.go b/vendor/github.com/gin-gonic/gin/binding/toml.go new file mode 100644 index 000000000..a6b8a90ab --- /dev/null +++ b/vendor/github.com/gin-gonic/gin/binding/toml.go @@ -0,0 +1,35 @@ +// Copyright 2022 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import ( + "bytes" + "io" + "net/http" + + "github.com/pelletier/go-toml/v2" +) + +type tomlBinding struct{} + +func (tomlBinding) Name() string { + return "toml" +} + +func decodeToml(r io.Reader, obj any) error { + decoder := toml.NewDecoder(r) + if err := decoder.Decode(obj); err != nil { + return err + } + return decoder.Decode(obj) +} + +func (tomlBinding) Bind(req *http.Request, obj any) error { + return decodeToml(req.Body, obj) +} + +func (tomlBinding) BindBody(body []byte, obj any) error { + return decodeToml(bytes.NewReader(body), obj) +} diff --git a/vendor/github.com/gin-gonic/gin/binding/uri.go b/vendor/github.com/gin-gonic/gin/binding/uri.go index f91ec3819..29151064a 100644 --- a/vendor/github.com/gin-gonic/gin/binding/uri.go +++ b/vendor/github.com/gin-gonic/gin/binding/uri.go @@ -1,4 +1,4 @@ -// Copyright 2018 Gin Core Team. All rights reserved. +// Copyright 2018 Gin Core Team. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -10,8 +10,8 @@ func (uriBinding) Name() string { return "uri" } -func (uriBinding) BindUri(m map[string][]string, obj interface{}) error { - if err := mapUri(obj, m); err != nil { +func (uriBinding) BindUri(m map[string][]string, obj any) error { + if err := mapURI(obj, m); err != nil { return err } return validate(obj) diff --git a/vendor/github.com/gin-gonic/gin/binding/xml.go b/vendor/github.com/gin-gonic/gin/binding/xml.go index 4e9011496..a70f4ad36 100644 --- a/vendor/github.com/gin-gonic/gin/binding/xml.go +++ b/vendor/github.com/gin-gonic/gin/binding/xml.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -17,14 +17,14 @@ func (xmlBinding) Name() string { return "xml" } -func (xmlBinding) Bind(req *http.Request, obj interface{}) error { +func (xmlBinding) Bind(req *http.Request, obj any) error { return decodeXML(req.Body, obj) } -func (xmlBinding) BindBody(body []byte, obj interface{}) error { +func (xmlBinding) BindBody(body []byte, obj any) error { return decodeXML(bytes.NewReader(body), obj) } -func decodeXML(r io.Reader, obj interface{}) error { +func decodeXML(r io.Reader, obj any) error { decoder := xml.NewDecoder(r) if err := decoder.Decode(obj); err != nil { return err diff --git a/vendor/github.com/gin-gonic/gin/binding/yaml.go b/vendor/github.com/gin-gonic/gin/binding/yaml.go index a2d36d6a5..b0d36a358 100644 --- a/vendor/github.com/gin-gonic/gin/binding/yaml.go +++ b/vendor/github.com/gin-gonic/gin/binding/yaml.go @@ -1,4 +1,4 @@ -// Copyright 2018 Gin Core Team. All rights reserved. +// Copyright 2018 Gin Core Team. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -18,15 +18,15 @@ func (yamlBinding) Name() string { return "yaml" } -func (yamlBinding) Bind(req *http.Request, obj interface{}) error { +func (yamlBinding) Bind(req *http.Request, obj any) error { return decodeYAML(req.Body, obj) } -func (yamlBinding) BindBody(body []byte, obj interface{}) error { +func (yamlBinding) BindBody(body []byte, obj any) error { return decodeYAML(bytes.NewReader(body), obj) } -func decodeYAML(r io.Reader, obj interface{}) error { +func decodeYAML(r io.Reader, obj any) error { decoder := yaml.NewDecoder(r) if err := decoder.Decode(obj); err != nil { return err diff --git a/vendor/github.com/gin-gonic/gin/context.go b/vendor/github.com/gin-gonic/gin/context.go index 220d1bc7b..b1ad95e62 100644 --- a/vendor/github.com/gin-gonic/gin/context.go +++ b/vendor/github.com/gin-gonic/gin/context.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -6,7 +6,6 @@ package gin import ( "errors" - "fmt" "io" "io/ioutil" "log" @@ -35,12 +34,17 @@ const ( MIMEPOSTForm = binding.MIMEPOSTForm MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm MIMEYAML = binding.MIMEYAML + MIMETOML = binding.MIMETOML ) // BodyBytesKey indicates a default body bytes key. const BodyBytesKey = "_gin-gonic/gin/bodybyteskey" -const abortIndex int8 = math.MaxInt8 / 2 +// ContextKey is the key that a Context returns itself for. +const ContextKey = "_gin-gonic/gin/contextkey" + +// abortIndex represents a typical value used in abort functions. +const abortIndex int8 = math.MaxInt8 >> 1 // Context is the most important part of gin. It allows us to pass variables between middleware, // manage the flow, validate the JSON of a request and render a JSON response for example. @@ -58,11 +62,11 @@ type Context struct { params *Params skippedNodes *[]skippedNode - // This mutex protect Keys map + // This mutex protects Keys map. mu sync.RWMutex // Keys is a key/value pair exclusively for the context of each request. - Keys map[string]interface{} + Keys map[string]any // Errors is a list of errors attached to all the handlers/middlewares who used this context. Errors errorMsgs @@ -70,10 +74,10 @@ type Context struct { // Accepted defines a list of manually accepted formats for content negotiation. Accepted []string - // queryCache use url.ParseQuery cached the param query result from c.Request.URL.Query() + // queryCache caches the query result from c.Request.URL.Query(). queryCache url.Values - // formCache use url.ParseQuery cached PostForm contains the parsed form data from POST, PATCH, + // formCache caches c.Request.PostForm, which contains the parsed form data from POST, PATCH, // or PUT body parameters. formCache url.Values @@ -88,16 +92,17 @@ type Context struct { func (c *Context) reset() { c.Writer = &c.writermem - c.Params = c.Params[0:0] + c.Params = c.Params[:0] c.handlers = nil c.index = -1 c.fullPath = "" c.Keys = nil - c.Errors = c.Errors[0:0] + c.Errors = c.Errors[:0] c.Accepted = nil c.queryCache = nil c.formCache = nil + c.sameSite = 0 *c.params = (*c.params)[:0] *c.skippedNodes = (*c.skippedNodes)[:0] } @@ -115,7 +120,7 @@ func (c *Context) Copy() *Context { cp.Writer = &cp.writermem cp.index = abortIndex cp.handlers = nil - cp.Keys = map[string]interface{}{} + cp.Keys = map[string]any{} for k, v := range c.Keys { cp.Keys[k] = v } @@ -194,7 +199,7 @@ func (c *Context) AbortWithStatus(code int) { // AbortWithStatusJSON calls `Abort()` and then `JSON` internally. // This method stops the chain, writes the status code and return a JSON body. // It also sets the Content-Type as "application/json". -func (c *Context) AbortWithStatusJSON(code int, jsonObj interface{}) { +func (c *Context) AbortWithStatusJSON(code int, jsonObj any) { c.Abort() c.JSON(code, jsonObj) } @@ -221,7 +226,8 @@ func (c *Context) Error(err error) *Error { panic("err is nil") } - parsedError, ok := err.(*Error) + var parsedError *Error + ok := errors.As(err, &parsedError) if !ok { parsedError = &Error{ Err: err, @@ -239,10 +245,10 @@ func (c *Context) Error(err error) *Error { // Set is used to store a new key/value pair exclusively for this context. // It also lazy initializes c.Keys if it was not used previously. -func (c *Context) Set(key string, value interface{}) { +func (c *Context) Set(key string, value any) { c.mu.Lock() if c.Keys == nil { - c.Keys = make(map[string]interface{}) + c.Keys = make(map[string]any) } c.Keys[key] = value @@ -250,8 +256,8 @@ func (c *Context) Set(key string, value interface{}) { } // Get returns the value for the given key, ie: (value, true). -// If the value does not exists it returns (nil, false) -func (c *Context) Get(key string) (value interface{}, exists bool) { +// If the value does not exist it returns (nil, false) +func (c *Context) Get(key string) (value any, exists bool) { c.mu.RLock() value, exists = c.Keys[key] c.mu.RUnlock() @@ -259,7 +265,7 @@ func (c *Context) Get(key string) (value interface{}, exists bool) { } // MustGet returns the value for the given key if it exists, otherwise it panics. -func (c *Context) MustGet(key string) interface{} { +func (c *Context) MustGet(key string) any { if value, exists := c.Get(key); exists { return value } @@ -347,9 +353,9 @@ func (c *Context) GetStringSlice(key string) (ss []string) { } // GetStringMap returns the value associated with the key as a map of interfaces. -func (c *Context) GetStringMap(key string) (sm map[string]interface{}) { +func (c *Context) GetStringMap(key string) (sm map[string]any) { if val, ok := c.Get(key); ok && val != nil { - sm, _ = val.(map[string]interface{}) + sm, _ = val.(map[string]any) } return } @@ -384,6 +390,15 @@ func (c *Context) Param(key string) string { return c.Params.ByName(key) } +// AddParam adds param to context and +// replaces path param key with given value for e2e testing purposes +// Example Route: "/user/:id" +// AddParam("id", 1) +// Result: "/user/1" +func (c *Context) AddParam(key, value string) { + c.Params = append(c.Params, Param{Key: key, Value: value}) +} + // Query returns the keyed url query value if it exists, // otherwise it returns an empty string `("")`. // It is shortcut for `c.Request.URL.Query().Get(key)` @@ -392,9 +407,9 @@ func (c *Context) Param(key string) string { // c.Query("name") == "Manu" // c.Query("value") == "" // c.Query("wtf") == "" -func (c *Context) Query(key string) string { - value, _ := c.GetQuery(key) - return value +func (c *Context) Query(key string) (value string) { + value, _ = c.GetQuery(key) + return } // DefaultQuery returns the keyed url query value if it exists, @@ -428,9 +443,9 @@ func (c *Context) GetQuery(key string) (string, bool) { // QueryArray returns a slice of strings for a given query key. // The length of the slice depends on the number of params with the given key. -func (c *Context) QueryArray(key string) []string { - values, _ := c.GetQueryArray(key) - return values +func (c *Context) QueryArray(key string) (values []string) { + values, _ = c.GetQueryArray(key) + return } func (c *Context) initQueryCache() { @@ -445,18 +460,16 @@ func (c *Context) initQueryCache() { // GetQueryArray returns a slice of strings for a given query key, plus // a boolean value whether at least one value exists for the given key. -func (c *Context) GetQueryArray(key string) ([]string, bool) { +func (c *Context) GetQueryArray(key string) (values []string, ok bool) { c.initQueryCache() - if values, ok := c.queryCache[key]; ok && len(values) > 0 { - return values, true - } - return []string{}, false + values, ok = c.queryCache[key] + return } // QueryMap returns a map for a given query key. -func (c *Context) QueryMap(key string) map[string]string { - dicts, _ := c.GetQueryMap(key) - return dicts +func (c *Context) QueryMap(key string) (dicts map[string]string) { + dicts, _ = c.GetQueryMap(key) + return } // GetQueryMap returns a map for a given query key, plus a boolean value @@ -468,9 +481,9 @@ func (c *Context) GetQueryMap(key string) (map[string]string, bool) { // PostForm returns the specified key from a POST urlencoded form or multipart form // when it exists, otherwise it returns an empty string `("")`. -func (c *Context) PostForm(key string) string { - value, _ := c.GetPostForm(key) - return value +func (c *Context) PostForm(key string) (value string) { + value, _ = c.GetPostForm(key) + return } // DefaultPostForm returns the specified key from a POST urlencoded form or multipart form @@ -499,9 +512,9 @@ func (c *Context) GetPostForm(key string) (string, bool) { // PostFormArray returns a slice of strings for a given form key. // The length of the slice depends on the number of params with the given key. -func (c *Context) PostFormArray(key string) []string { - values, _ := c.GetPostFormArray(key) - return values +func (c *Context) PostFormArray(key string) (values []string) { + values, _ = c.GetPostFormArray(key) + return } func (c *Context) initFormCache() { @@ -509,7 +522,7 @@ func (c *Context) initFormCache() { c.formCache = make(url.Values) req := c.Request if err := req.ParseMultipartForm(c.engine.MaxMultipartMemory); err != nil { - if err != http.ErrNotMultipart { + if !errors.Is(err, http.ErrNotMultipart) { debugPrint("error on parse multipart form array: %v", err) } } @@ -519,18 +532,16 @@ func (c *Context) initFormCache() { // GetPostFormArray returns a slice of strings for a given form key, plus // a boolean value whether at least one value exists for the given key. -func (c *Context) GetPostFormArray(key string) ([]string, bool) { +func (c *Context) GetPostFormArray(key string) (values []string, ok bool) { c.initFormCache() - if values := c.formCache[key]; len(values) > 0 { - return values, true - } - return []string{}, false + values, ok = c.formCache[key] + return } // PostFormMap returns a map for a given form key. -func (c *Context) PostFormMap(key string) map[string]string { - dicts, _ := c.GetPostFormMap(key) - return dicts +func (c *Context) PostFormMap(key string) (dicts map[string]string) { + dicts, _ = c.GetPostFormMap(key) + return } // GetPostFormMap returns a map for a given form key, plus a boolean value @@ -594,47 +605,51 @@ func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error return err } -// Bind checks the Content-Type to select a binding engine automatically, -// Depending the "Content-Type" header different bindings are used: +// Bind checks the Method and Content-Type to select a binding engine automatically, +// Depending on the "Content-Type" header different bindings are used, for example: // "application/json" --> JSON binding // "application/xml" --> XML binding -// otherwise --> returns an error. // It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input. // It decodes the json payload into the struct specified as a pointer. // It writes a 400 error and sets Content-Type header "text/plain" in the response if input is not valid. -func (c *Context) Bind(obj interface{}) error { +func (c *Context) Bind(obj any) error { b := binding.Default(c.Request.Method, c.ContentType()) return c.MustBindWith(obj, b) } // BindJSON is a shortcut for c.MustBindWith(obj, binding.JSON). -func (c *Context) BindJSON(obj interface{}) error { +func (c *Context) BindJSON(obj any) error { return c.MustBindWith(obj, binding.JSON) } // BindXML is a shortcut for c.MustBindWith(obj, binding.BindXML). -func (c *Context) BindXML(obj interface{}) error { +func (c *Context) BindXML(obj any) error { return c.MustBindWith(obj, binding.XML) } // BindQuery is a shortcut for c.MustBindWith(obj, binding.Query). -func (c *Context) BindQuery(obj interface{}) error { +func (c *Context) BindQuery(obj any) error { return c.MustBindWith(obj, binding.Query) } // BindYAML is a shortcut for c.MustBindWith(obj, binding.YAML). -func (c *Context) BindYAML(obj interface{}) error { +func (c *Context) BindYAML(obj any) error { return c.MustBindWith(obj, binding.YAML) } +// BindTOML is a shortcut for c.MustBindWith(obj, binding.TOML). +func (c *Context) BindTOML(obj interface{}) error { + return c.MustBindWith(obj, binding.TOML) +} + // BindHeader is a shortcut for c.MustBindWith(obj, binding.Header). -func (c *Context) BindHeader(obj interface{}) error { +func (c *Context) BindHeader(obj any) error { return c.MustBindWith(obj, binding.Header) } // BindUri binds the passed struct pointer using binding.Uri. // It will abort the request with HTTP 400 if any error occurs. -func (c *Context) BindUri(obj interface{}) error { +func (c *Context) BindUri(obj any) error { if err := c.ShouldBindUri(obj); err != nil { c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck return err @@ -645,7 +660,7 @@ func (c *Context) BindUri(obj interface{}) error { // MustBindWith binds the passed struct pointer using the specified binding engine. // It will abort the request with HTTP 400 if any error occurs. // See the binding package. -func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error { +func (c *Context) MustBindWith(obj any, b binding.Binding) error { if err := c.ShouldBindWith(obj, b); err != nil { c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck return err @@ -653,46 +668,50 @@ func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error { return nil } -// ShouldBind checks the Content-Type to select a binding engine automatically, -// Depending the "Content-Type" header different bindings are used: +// ShouldBind checks the Method and Content-Type to select a binding engine automatically, +// Depending on the "Content-Type" header different bindings are used, for example: // "application/json" --> JSON binding // "application/xml" --> XML binding -// otherwise --> returns an error // It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input. // It decodes the json payload into the struct specified as a pointer. -// Like c.Bind() but this method does not set the response status code to 400 and abort if the json is not valid. -func (c *Context) ShouldBind(obj interface{}) error { +// Like c.Bind() but this method does not set the response status code to 400 or abort if input is not valid. +func (c *Context) ShouldBind(obj any) error { b := binding.Default(c.Request.Method, c.ContentType()) return c.ShouldBindWith(obj, b) } // ShouldBindJSON is a shortcut for c.ShouldBindWith(obj, binding.JSON). -func (c *Context) ShouldBindJSON(obj interface{}) error { +func (c *Context) ShouldBindJSON(obj any) error { return c.ShouldBindWith(obj, binding.JSON) } // ShouldBindXML is a shortcut for c.ShouldBindWith(obj, binding.XML). -func (c *Context) ShouldBindXML(obj interface{}) error { +func (c *Context) ShouldBindXML(obj any) error { return c.ShouldBindWith(obj, binding.XML) } // ShouldBindQuery is a shortcut for c.ShouldBindWith(obj, binding.Query). -func (c *Context) ShouldBindQuery(obj interface{}) error { +func (c *Context) ShouldBindQuery(obj any) error { return c.ShouldBindWith(obj, binding.Query) } // ShouldBindYAML is a shortcut for c.ShouldBindWith(obj, binding.YAML). -func (c *Context) ShouldBindYAML(obj interface{}) error { +func (c *Context) ShouldBindYAML(obj any) error { return c.ShouldBindWith(obj, binding.YAML) } +// ShouldBindTOML is a shortcut for c.ShouldBindWith(obj, binding.TOML). +func (c *Context) ShouldBindTOML(obj interface{}) error { + return c.ShouldBindWith(obj, binding.TOML) +} + // ShouldBindHeader is a shortcut for c.ShouldBindWith(obj, binding.Header). -func (c *Context) ShouldBindHeader(obj interface{}) error { +func (c *Context) ShouldBindHeader(obj any) error { return c.ShouldBindWith(obj, binding.Header) } // ShouldBindUri binds the passed struct pointer using the specified binding engine. -func (c *Context) ShouldBindUri(obj interface{}) error { +func (c *Context) ShouldBindUri(obj any) error { m := make(map[string][]string) for _, v := range c.Params { m[v.Key] = []string{v.Value} @@ -702,7 +721,7 @@ func (c *Context) ShouldBindUri(obj interface{}) error { // ShouldBindWith binds the passed struct pointer using the specified binding engine. // See the binding package. -func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error { +func (c *Context) ShouldBindWith(obj any, b binding.Binding) error { return b.Bind(c.Request, obj) } @@ -711,7 +730,7 @@ func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error { // // NOTE: This method reads the body before binding. So you should use // ShouldBindWith for better performance if you need to call only once. -func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (err error) { +func (c *Context) ShouldBindBodyWith(obj any, bb binding.BindingBody) (err error) { var body []byte if cb, ok := c.Get(BodyBytesKey); ok { if cbb, ok := cb.([]byte); ok { @@ -732,7 +751,7 @@ func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (e // It called c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not. // If it is it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]). // If the headers are not syntactically valid OR the remote IP does not correspond to a trusted proxy, -// the remote IP (coming form Request.RemoteAddr) is returned. +// the remote IP (coming from Request.RemoteAddr) is returned. func (c *Context) ClientIP() string { // Check if we're running on a trusted platform, continue running backwards if error if c.engine.TrustedPlatform != "" { @@ -750,10 +769,14 @@ func (c *Context) ClientIP() string { } } - remoteIP, trusted := c.RemoteIP() + // It also checks if the remoteIP is a trusted proxy or not. + // In order to perform this validation, it will see if the IP is contained within at least one of the CIDR blocks + // defined by Engine.SetTrustedProxies() + remoteIP := net.ParseIP(c.RemoteIP()) if remoteIP == nil { return "" } + trusted := c.engine.isTrustedProxy(remoteIP) if trusted && c.engine.ForwardedByClientIP && c.engine.RemoteIPHeaders != nil { for _, headerName := range c.engine.RemoteIPHeaders { @@ -766,53 +789,13 @@ func (c *Context) ClientIP() string { return remoteIP.String() } -func (e *Engine) isTrustedProxy(ip net.IP) bool { - if e.trustedCIDRs != nil { - for _, cidr := range e.trustedCIDRs { - if cidr.Contains(ip) { - return true - } - } - } - return false -} - // RemoteIP parses the IP from Request.RemoteAddr, normalizes and returns the IP (without the port). -// It also checks if the remoteIP is a trusted proxy or not. -// In order to perform this validation, it will see if the IP is contained within at least one of the CIDR blocks -// defined by Engine.SetTrustedProxies() -func (c *Context) RemoteIP() (net.IP, bool) { +func (c *Context) RemoteIP() string { ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr)) if err != nil { - return nil, false - } - remoteIP := net.ParseIP(ip) - if remoteIP == nil { - return nil, false - } - - return remoteIP, c.engine.isTrustedProxy(remoteIP) -} - -func (e *Engine) validateHeader(header string) (clientIP string, valid bool) { - if header == "" { - return "", false - } - items := strings.Split(header, ",") - for i := len(items) - 1; i >= 0; i-- { - ipStr := strings.TrimSpace(items[i]) - ip := net.ParseIP(ipStr) - if ip == nil { - return "", false - } - - // X-Forwarded-For is appended by proxy - // Check IPs in reverse order and stop when find untrusted proxy - if (i == 0) || (!e.isTrustedProxy(ip)) { - return ipStr, true - } + return "" } - return + return ip } // ContentType returns the Content-Type header of the request. @@ -856,7 +839,7 @@ func (c *Context) Status(code int) { c.Writer.WriteHeader(code) } -// Header is a intelligent shortcut for c.Writer.Header().Set(key, value). +// Header is an intelligent shortcut for c.Writer.Header().Set(key, value). // It writes a header in the response. // If value == "", this method removes the header `c.Writer.Header().Del(key)` func (c *Context) Header(key, value string) { @@ -872,7 +855,7 @@ func (c *Context) GetHeader(key string) string { return c.requestHeader(key) } -// GetRawData return stream data. +// GetRawData returns stream data. func (c *Context) GetRawData() ([]byte, error) { return ioutil.ReadAll(c.Request.Body) } @@ -932,30 +915,30 @@ func (c *Context) Render(code int, r render.Render) { // HTML renders the HTTP template specified by its file name. // It also updates the HTTP code and sets the Content-Type as "text/html". // See http://golang.org/doc/articles/wiki/ -func (c *Context) HTML(code int, name string, obj interface{}) { +func (c *Context) HTML(code int, name string, obj any) { instance := c.engine.HTMLRender.Instance(name, obj) c.Render(code, instance) } // IndentedJSON serializes the given struct as pretty JSON (indented + endlines) into the response body. // It also sets the Content-Type as "application/json". -// WARNING: we recommend to use this only for development purposes since printing pretty JSON is +// WARNING: we recommend using this only for development purposes since printing pretty JSON is // more CPU and bandwidth consuming. Use Context.JSON() instead. -func (c *Context) IndentedJSON(code int, obj interface{}) { +func (c *Context) IndentedJSON(code int, obj any) { c.Render(code, render.IndentedJSON{Data: obj}) } // SecureJSON serializes the given struct as Secure JSON into the response body. // Default prepends "while(1)," to response body if the given struct is array values. // It also sets the Content-Type as "application/json". -func (c *Context) SecureJSON(code int, obj interface{}) { +func (c *Context) SecureJSON(code int, obj any) { c.Render(code, render.SecureJSON{Prefix: c.engine.secureJSONPrefix, Data: obj}) } // JSONP serializes the given struct as JSON into the response body. // It adds padding to response body to request data from a server residing in a different domain than the client. // It also sets the Content-Type as "application/javascript". -func (c *Context) JSONP(code int, obj interface{}) { +func (c *Context) JSONP(code int, obj any) { callback := c.DefaultQuery("callback", "") if callback == "" { c.Render(code, render.JSON{Data: obj}) @@ -966,44 +949,49 @@ func (c *Context) JSONP(code int, obj interface{}) { // JSON serializes the given struct as JSON into the response body. // It also sets the Content-Type as "application/json". -func (c *Context) JSON(code int, obj interface{}) { +func (c *Context) JSON(code int, obj any) { c.Render(code, render.JSON{Data: obj}) } // AsciiJSON serializes the given struct as JSON into the response body with unicode to ASCII string. // It also sets the Content-Type as "application/json". -func (c *Context) AsciiJSON(code int, obj interface{}) { +func (c *Context) AsciiJSON(code int, obj any) { c.Render(code, render.AsciiJSON{Data: obj}) } // PureJSON serializes the given struct as JSON into the response body. // PureJSON, unlike JSON, does not replace special html characters with their unicode entities. -func (c *Context) PureJSON(code int, obj interface{}) { +func (c *Context) PureJSON(code int, obj any) { c.Render(code, render.PureJSON{Data: obj}) } // XML serializes the given struct as XML into the response body. // It also sets the Content-Type as "application/xml". -func (c *Context) XML(code int, obj interface{}) { +func (c *Context) XML(code int, obj any) { c.Render(code, render.XML{Data: obj}) } // YAML serializes the given struct as YAML into the response body. -func (c *Context) YAML(code int, obj interface{}) { +func (c *Context) YAML(code int, obj any) { c.Render(code, render.YAML{Data: obj}) } +// TOML serializes the given struct as TOML into the response body. +func (c *Context) TOML(code int, obj interface{}) { + c.Render(code, render.TOML{Data: obj}) +} + // ProtoBuf serializes the given struct as ProtoBuf into the response body. -func (c *Context) ProtoBuf(code int, obj interface{}) { +func (c *Context) ProtoBuf(code int, obj any) { c.Render(code, render.ProtoBuf{Data: obj}) } // String writes the given string into the response body. -func (c *Context) String(code int, format string, values ...interface{}) { +func (c *Context) String(code int, format string, values ...any) { c.Render(code, render.String{Format: format, Data: values}) } -// Redirect returns a HTTP redirect to the specific location. +// Redirect returns an HTTP redirect to the specific location. func (c *Context) Redirect(code int, location string) { c.Render(-1, render.Redirect{ Code: code, @@ -1049,12 +1037,16 @@ func (c *Context) FileFromFS(filepath string, fs http.FileSystem) { // FileAttachment writes the specified file into the body stream in an efficient way // On the client side, the file will typically be downloaded with the given filename func (c *Context) FileAttachment(filepath, filename string) { - c.Writer.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filename)) + if isASCII(filename) { + c.Writer.Header().Set("Content-Disposition", `attachment; filename="`+filename+`"`) + } else { + c.Writer.Header().Set("Content-Disposition", `attachment; filename*=UTF-8''`+url.QueryEscape(filename)) + } http.ServeFile(c.Writer, c.Request, filepath) } // SSEvent writes a Server-Sent Event into the body stream. -func (c *Context) SSEvent(name string, message interface{}) { +func (c *Context) SSEvent(name string, message any) { c.Render(-1, sse.Event{ Event: name, Data: message, @@ -1088,14 +1080,15 @@ func (c *Context) Stream(step func(w io.Writer) bool) bool { type Negotiate struct { Offered []string HTMLName string - HTMLData interface{} - JSONData interface{} - XMLData interface{} - YAMLData interface{} - Data interface{} + HTMLData any + JSONData any + XMLData any + YAMLData any + Data any + TOMLData any } -// Negotiate calls different Render according acceptable Accept format. +// Negotiate calls different Render according to acceptable Accept format. func (c *Context) Negotiate(code int, config Negotiate) { switch c.NegotiateFormat(config.Offered...) { case binding.MIMEJSON: @@ -1114,6 +1107,10 @@ func (c *Context) Negotiate(code int, config Negotiate) { data := chooseData(config.YAMLData, config.Data) c.YAML(code, data) + case binding.MIMETOML: + data := chooseData(config.TOMLData, config.Data) + c.TOML(code, data) + default: c.AbortWithError(http.StatusNotAcceptable, errors.New("the accepted formats are not offered by the server")) // nolint: errcheck } @@ -1159,34 +1156,47 @@ func (c *Context) SetAccepted(formats ...string) { /***** GOLANG.ORG/X/NET/CONTEXT *****/ /************************************/ -// Deadline always returns that there is no deadline (ok==false), -// maybe you want to use Request.Context().Deadline() instead. +// Deadline returns that there is no deadline (ok==false) when c.Request has no Context. func (c *Context) Deadline() (deadline time.Time, ok bool) { - return + if !c.engine.ContextWithFallback || c.Request == nil || c.Request.Context() == nil { + return + } + return c.Request.Context().Deadline() } -// Done always returns nil (chan which will wait forever), -// if you want to abort your work when the connection was closed -// you should use Request.Context().Done() instead. +// Done returns nil (chan which will wait forever) when c.Request has no Context. func (c *Context) Done() <-chan struct{} { - return nil + if !c.engine.ContextWithFallback || c.Request == nil || c.Request.Context() == nil { + return nil + } + return c.Request.Context().Done() } -// Err always returns nil, maybe you want to use Request.Context().Err() instead. +// Err returns nil when c.Request has no Context. func (c *Context) Err() error { - return nil + if !c.engine.ContextWithFallback || c.Request == nil || c.Request.Context() == nil { + return nil + } + return c.Request.Context().Err() } // Value returns the value associated with this context for key, or nil // if no value is associated with key. Successive calls to Value with // the same key returns the same result. -func (c *Context) Value(key interface{}) interface{} { +func (c *Context) Value(key any) any { if key == 0 { return c.Request } + if key == ContextKey { + return c + } if keyAsString, ok := key.(string); ok { - val, _ := c.Get(keyAsString) - return val + if val, exists := c.Get(keyAsString); exists { + return val + } } - return nil + if !c.engine.ContextWithFallback || c.Request == nil || c.Request.Context() == nil { + return nil + } + return c.Request.Context().Value(key) } diff --git a/vendor/github.com/gin-gonic/gin/context_appengine.go b/vendor/github.com/gin-gonic/gin/context_appengine.go index 8bf938961..931313f61 100644 --- a/vendor/github.com/gin-gonic/gin/context_appengine.go +++ b/vendor/github.com/gin-gonic/gin/context_appengine.go @@ -1,4 +1,4 @@ -// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. diff --git a/vendor/github.com/gin-gonic/gin/debug.go b/vendor/github.com/gin-gonic/gin/debug.go index 9bacc6857..25fd7c87f 100644 --- a/vendor/github.com/gin-gonic/gin/debug.go +++ b/vendor/github.com/gin-gonic/gin/debug.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -12,7 +12,7 @@ import ( "strings" ) -const ginSupportMinGoVer = 13 +const ginSupportMinGoVer = 14 // IsDebugging returns true if the framework is running in debug mode. // Use SetMode(gin.ReleaseMode) to disable debug mode. @@ -47,7 +47,7 @@ func debugPrintLoadTemplate(tmpl *template.Template) { } } -func debugPrint(format string, values ...interface{}) { +func debugPrint(format string, values ...any) { if IsDebugging() { if !strings.HasSuffix(format, "\n") { format += "\n" @@ -67,7 +67,7 @@ func getMinVer(v string) (uint64, error) { func debugPrintWARNINGDefault() { if v, e := getMinVer(runtime.Version()); e == nil && v <= ginSupportMinGoVer { - debugPrint(`[WARNING] Now Gin requires Go 1.13+. + debugPrint(`[WARNING] Now Gin requires Go 1.14+. `) } @@ -95,9 +95,7 @@ at initialization. ie. before any route is registered or the router is listening } func debugPrintError(err error) { - if err != nil { - if IsDebugging() { - fmt.Fprintf(DefaultErrorWriter, "[GIN-debug] [ERROR] %v\n", err) - } + if err != nil && IsDebugging() { + fmt.Fprintf(DefaultErrorWriter, "[GIN-debug] [ERROR] %v\n", err) } } diff --git a/vendor/github.com/gin-gonic/gin/deprecated.go b/vendor/github.com/gin-gonic/gin/deprecated.go index ab4474296..fdad85547 100644 --- a/vendor/github.com/gin-gonic/gin/deprecated.go +++ b/vendor/github.com/gin-gonic/gin/deprecated.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -12,7 +12,7 @@ import ( // BindWith binds the passed struct pointer using the specified binding engine. // See the binding package. -func (c *Context) BindWith(obj interface{}, b binding.Binding) error { +func (c *Context) BindWith(obj any, b binding.Binding) error { log.Println(`BindWith(\"interface{}, binding.Binding\") error is going to be deprecated, please check issue #662 and either use MustBindWith() if you want HTTP 400 to be automatically returned if any error occur, or use diff --git a/vendor/github.com/gin-gonic/gin/errors.go b/vendor/github.com/gin-gonic/gin/errors.go index 0f276c13d..2853ce8ed 100644 --- a/vendor/github.com/gin-gonic/gin/errors.go +++ b/vendor/github.com/gin-gonic/gin/errors.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -34,7 +34,7 @@ const ( type Error struct { Err error Type ErrorType - Meta interface{} + Meta any } type errorMsgs []*Error @@ -48,13 +48,13 @@ func (msg *Error) SetType(flags ErrorType) *Error { } // SetMeta sets the error's meta data. -func (msg *Error) SetMeta(data interface{}) *Error { +func (msg *Error) SetMeta(data any) *Error { msg.Meta = data return msg } // JSON creates a properly formatted JSON -func (msg *Error) JSON() interface{} { +func (msg *Error) JSON() any { jsonData := H{} if msg.Meta != nil { value := reflect.ValueOf(msg.Meta) @@ -122,7 +122,7 @@ func (a errorMsgs) Last() *Error { return nil } -// Errors returns an array will all the error messages. +// Errors returns an array with all the error messages. // Example: // c.Error(errors.New("first")) // c.Error(errors.New("second")) @@ -139,14 +139,14 @@ func (a errorMsgs) Errors() []string { return errorStrings } -func (a errorMsgs) JSON() interface{} { +func (a errorMsgs) JSON() any { switch length := len(a); length { case 0: return nil case 1: return a.Last().JSON() default: - jsonData := make([]interface{}, length) + jsonData := make([]any, length) for i, err := range a { jsonData[i] = err.JSON() } diff --git a/vendor/github.com/gin-gonic/gin/fs.go b/vendor/github.com/gin-gonic/gin/fs.go index 007d9b755..64274735e 100644 --- a/vendor/github.com/gin-gonic/gin/fs.go +++ b/vendor/github.com/gin-gonic/gin/fs.go @@ -1,4 +1,4 @@ -// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -17,7 +17,7 @@ type neuteredReaddirFile struct { http.File } -// Dir returns a http.Filesystem that can be used by http.FileServer(). It is used internally +// Dir returns a http.FileSystem that can be used by http.FileServer(). It is used internally // in router.Static(). // if listDirectory == true, then it works the same as http.Dir() otherwise it returns // a filesystem that prevents http.FileServer() to list the directory files. diff --git a/vendor/github.com/gin-gonic/gin/gin.go b/vendor/github.com/gin-gonic/gin/gin.go index 58e76f41f..f9324299b 100644 --- a/vendor/github.com/gin-gonic/gin/gin.go +++ b/vendor/github.com/gin-gonic/gin/gin.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -11,12 +11,13 @@ import ( "net/http" "os" "path" - "reflect" "strings" "sync" "github.com/gin-gonic/gin/internal/bytesconv" "github.com/gin-gonic/gin/render" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" ) const defaultMultipartMemory = 32 << 20 // 32 MB @@ -28,15 +29,24 @@ var ( var defaultPlatform string -var defaultTrustedCIDRs = []*net.IPNet{{IP: net.IP{0x0, 0x0, 0x0, 0x0}, Mask: net.IPMask{0x0, 0x0, 0x0, 0x0}}} // 0.0.0.0/0 +var defaultTrustedCIDRs = []*net.IPNet{ + { // 0.0.0.0/0 (IPv4) + IP: net.IP{0x0, 0x0, 0x0, 0x0}, + Mask: net.IPMask{0x0, 0x0, 0x0, 0x0}, + }, + { // ::/0 (IPv6) + IP: net.IP{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + Mask: net.IPMask{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + }, +} // HandlerFunc defines the handler used by gin middleware as return value. type HandlerFunc func(*Context) -// HandlersChain defines a HandlerFunc array. +// HandlersChain defines a HandlerFunc slice. type HandlersChain []HandlerFunc -// Last returns the last handler in the chain. ie. the last handler is the main one. +// Last returns the last handler in the chain. i.e. the last handler is the main one. func (c HandlersChain) Last() HandlerFunc { if length := len(c); length > 0 { return c[length-1] @@ -52,15 +62,15 @@ type RouteInfo struct { HandlerFunc HandlerFunc } -// RoutesInfo defines a RouteInfo array. +// RoutesInfo defines a RouteInfo slice. type RoutesInfo []RouteInfo // Trusted platforms const ( - // When running on Google App Engine. Trust X-Appengine-Remote-Addr + // PlatformGoogleAppEngine when running on Google App Engine. Trust X-Appengine-Remote-Addr // for determining the client's IP PlatformGoogleAppEngine = "X-Appengine-Remote-Addr" - // When using Cloudflare's CDN. Trust CF-Connecting-IP for determining + // PlatformCloudflare when using Cloudflare's CDN. Trust CF-Connecting-IP for determining // the client's IP PlatformCloudflare = "CF-Connecting-IP" ) @@ -70,14 +80,14 @@ const ( type Engine struct { RouterGroup - // Enables automatic redirection if the current route can't be matched but a + // RedirectTrailingSlash enables automatic redirection if the current route can't be matched but a // handler for the path with (without) the trailing slash exists. // For example if /foo/ is requested but a route only exists for /foo, the // client is redirected to /foo with http status code 301 for GET requests // and 307 for all other request methods. RedirectTrailingSlash bool - // If enabled, the router tries to fix the current request path, if no + // RedirectFixedPath if enabled, the router tries to fix the current request path, if no // handle is registered for it. // First superfluous path elements like ../ or // are removed. // Afterwards the router does a case-insensitive lookup of the cleaned path. @@ -88,7 +98,7 @@ type Engine struct { // RedirectTrailingSlash is independent of this option. RedirectFixedPath bool - // If enabled, the router checks if another method is allowed for the + // HandleMethodNotAllowed if enabled, the router checks if another method is allowed for the // current route, if the current request can not be routed. // If this is the case, the request is answered with 'Method Not Allowed' // and HTTP status code 405. @@ -96,21 +106,22 @@ type Engine struct { // handler. HandleMethodNotAllowed bool - // If enabled, client IP will be parsed from the request's headers that + // ForwardedByClientIP if enabled, client IP will be parsed from the request's headers that // match those stored at `(*gin.Engine).RemoteIPHeaders`. If no IP was // fetched, it falls back to the IP obtained from // `(*gin.Context).Request.RemoteAddr`. ForwardedByClientIP bool - // DEPRECATED: USE `TrustedPlatform` WITH VALUE `gin.GoogleAppEngine` INSTEAD + // AppEngine was deprecated. + // Deprecated: USE `TrustedPlatform` WITH VALUE `gin.PlatformGoogleAppEngine` INSTEAD // #726 #755 If enabled, it will trust some headers starting with // 'X-AppEngine...' for better integration with that PaaS. AppEngine bool - // If enabled, the url.RawPath will be used to find parameters. + // UseRawPath if enabled, the url.RawPath will be used to find parameters. UseRawPath bool - // If true, the path value will be unescaped. + // UnescapePathValues if true, the path value will be unescaped. // If UseRawPath is false (by default), the UnescapePathValues effectively is true, // as url.Path gonna be used, which is already unescaped. UnescapePathValues bool @@ -119,20 +130,26 @@ type Engine struct { // See the PR #1817 and issue #1644 RemoveExtraSlash bool - // List of headers used to obtain the client IP when + // RemoteIPHeaders list of headers used to obtain the client IP when // `(*gin.Engine).ForwardedByClientIP` is `true` and // `(*gin.Context).Request.RemoteAddr` is matched by at least one of the // network origins of list defined by `(*gin.Engine).SetTrustedProxies()`. RemoteIPHeaders []string - // If set to a constant of value gin.Platform*, trusts the headers set by + // TrustedPlatform if set to a constant of value gin.Platform*, trusts the headers set by // that platform, for example to determine the client IP TrustedPlatform string - // Value of 'maxMemory' param that is given to http.Request's ParseMultipartForm + // MaxMultipartMemory value of 'maxMemory' param that is given to http.Request's ParseMultipartForm // method call. MaxMultipartMemory int64 + // UseH2C enable h2c support. + UseH2C bool + + // ContextWithFallback enable fallback Context.Deadline(), Context.Done(), Context.Err() and Context.Value() when Context.Request.Context() is not nil. + ContextWithFallback bool + delims render.Delims secureJSONPrefix string HTMLRender render.HTMLRender @@ -152,7 +169,7 @@ type Engine struct { var _ IRouter = &Engine{} // New returns a new blank Engine instance without any middleware attached. -// By default the configuration is: +// By default, the configuration is: // - RedirectTrailingSlash: true // - RedirectFixedPath: false // - HandleMethodNotAllowed: false @@ -181,11 +198,11 @@ func New() *Engine { trees: make(methodTrees, 0, 9), delims: render.Delims{Left: "{{", Right: "}}"}, secureJSONPrefix: "while(1);", - trustedProxies: []string{"0.0.0.0/0"}, + trustedProxies: []string{"0.0.0.0/0", "::/0"}, trustedCIDRs: defaultTrustedCIDRs, } engine.RouterGroup.engine = engine - engine.pool.New = func() interface{} { + engine.pool.New = func() any { return engine.allocateContext() } return engine @@ -199,13 +216,22 @@ func Default() *Engine { return engine } +func (engine *Engine) Handler() http.Handler { + if !engine.UseH2C { + return engine + } + + h2s := &http2.Server{} + return h2c.NewHandler(engine, h2s) +} + func (engine *Engine) allocateContext() *Context { v := make(Params, 0, engine.maxParams) skippedNodes := make([]skippedNode, 0, engine.maxSections) return &Context{engine: engine, params: &v, skippedNodes: &skippedNodes} } -// Delims sets template left and right delims and returns a Engine instance. +// Delims sets template left and right delims and returns an Engine instance. func (engine *Engine) Delims(left, right string) *Engine { engine.delims = render.Delims{Left: left, Right: right} return engine @@ -259,7 +285,7 @@ func (engine *Engine) SetFuncMap(funcMap template.FuncMap) { engine.FuncMap = funcMap } -// NoRoute adds handlers for NoRoute. It return a 404 code by default. +// NoRoute adds handlers for NoRoute. It returns a 404 code by default. func (engine *Engine) NoRoute(handlers ...HandlerFunc) { engine.noRoute = handlers engine.rebuild404Handlers() @@ -271,7 +297,7 @@ func (engine *Engine) NoMethod(handlers ...HandlerFunc) { engine.rebuild405Handlers() } -// Use attaches a global middleware to the router. ie. the middleware attached though Use() will be +// Use attaches a global middleware to the router. i.e. the middleware attached through Use() will be // included in the handlers chain for every single request. Even 404, 405, static files... // For example, this is the right place for a logger or error management middleware. func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes { @@ -353,7 +379,7 @@ func (engine *Engine) Run(addr ...string) (err error) { address := resolveAddress(addr) debugPrint("Listening and serving HTTP on %s\n", address) - err = http.ListenAndServe(address, engine) + err = http.ListenAndServe(address, engine.Handler()) return } @@ -399,9 +425,9 @@ func (engine *Engine) SetTrustedProxies(trustedProxies []string) error { return engine.parseTrustedProxies() } -// isUnsafeTrustedProxies compares Engine.trustedCIDRs and defaultTrustedCIDRs, it's not safe if equal (returns true) +// isUnsafeTrustedProxies checks if Engine.trustedCIDRs contains all IPs, it's not safe if it has (returns true) func (engine *Engine) isUnsafeTrustedProxies() bool { - return reflect.DeepEqual(engine.trustedCIDRs, defaultTrustedCIDRs) + return engine.isTrustedProxy(net.ParseIP("0.0.0.0")) || engine.isTrustedProxy(net.ParseIP("::")) } // parseTrustedProxies parse Engine.trustedProxies to Engine.trustedCIDRs @@ -411,6 +437,41 @@ func (engine *Engine) parseTrustedProxies() error { return err } +// isTrustedProxy will check whether the IP address is included in the trusted list according to Engine.trustedCIDRs +func (engine *Engine) isTrustedProxy(ip net.IP) bool { + if engine.trustedCIDRs == nil { + return false + } + for _, cidr := range engine.trustedCIDRs { + if cidr.Contains(ip) { + return true + } + } + return false +} + +// validateHeader will parse X-Forwarded-For header and return the trusted client IP address +func (engine *Engine) validateHeader(header string) (clientIP string, valid bool) { + if header == "" { + return "", false + } + items := strings.Split(header, ",") + for i := len(items) - 1; i >= 0; i-- { + ipStr := strings.TrimSpace(items[i]) + ip := net.ParseIP(ipStr) + if ip == nil { + break + } + + // X-Forwarded-For is appended by proxy + // Check IPs in reverse order and stop when find untrusted proxy + if (i == 0) || (!engine.isTrustedProxy(ip)) { + return ipStr, true + } + } + return "", false +} + // parseIP parse a string representation of an IP and returns a net.IP with the // minimum byte representation or nil if input is invalid. func parseIP(ip string) net.IP { @@ -437,12 +498,12 @@ func (engine *Engine) RunTLS(addr, certFile, keyFile string) (err error) { "Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.") } - err = http.ListenAndServeTLS(addr, certFile, keyFile, engine) + err = http.ListenAndServeTLS(addr, certFile, keyFile, engine.Handler()) return } // RunUnix attaches the router to a http.Server and starts listening and serving HTTP requests -// through the specified unix socket (ie. a file). +// through the specified unix socket (i.e. a file). // Note: this method will block the calling goroutine indefinitely unless an error happens. func (engine *Engine) RunUnix(file string) (err error) { debugPrint("Listening and serving HTTP on unix:/%s", file) @@ -460,7 +521,7 @@ func (engine *Engine) RunUnix(file string) (err error) { defer listener.Close() defer os.Remove(file) - err = http.Serve(listener, engine) + err = http.Serve(listener, engine.Handler()) return } @@ -497,7 +558,7 @@ func (engine *Engine) RunListener(listener net.Listener) (err error) { "Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.") } - err = http.Serve(listener, engine) + err = http.Serve(listener, engine.Handler()) return } @@ -513,9 +574,9 @@ func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { engine.pool.Put(c) } -// HandleContext re-enter a context that has been rewritten. +// HandleContext re-enters a context that has been rewritten. // This can be done by setting c.Request.URL.Path to your new target. -// Disclaimer: You can loop yourself to death with this, use wisely. +// Disclaimer: You can loop yourself to deal with this, use wisely. func (engine *Engine) HandleContext(c *Context) { oldIndexValue := c.index c.reset() @@ -556,7 +617,7 @@ func (engine *Engine) handleHTTPRequest(c *Context) { c.writermem.WriteHeaderNow() return } - if httpMethod != "CONNECT" && rPath != "/" { + if httpMethod != http.MethodConnect && rPath != "/" { if value.tsr && engine.RedirectTrailingSlash { redirectTrailingSlash(c) return diff --git a/vendor/github.com/gin-gonic/gin/internal/json/go_json.go b/vendor/github.com/gin-gonic/gin/internal/json/go_json.go new file mode 100644 index 000000000..23f717265 --- /dev/null +++ b/vendor/github.com/gin-gonic/gin/internal/json/go_json.go @@ -0,0 +1,23 @@ +// Copyright 2017 Bo-Yi Wu. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +//go:build go_json +// +build go_json + +package json + +import json "github.com/goccy/go-json" + +var ( + // Marshal is exported by gin/json package. + Marshal = json.Marshal + // Unmarshal is exported by gin/json package. + Unmarshal = json.Unmarshal + // MarshalIndent is exported by gin/json package. + MarshalIndent = json.MarshalIndent + // NewDecoder is exported by gin/json package. + NewDecoder = json.NewDecoder + // NewEncoder is exported by gin/json package. + NewEncoder = json.NewEncoder +) diff --git a/vendor/github.com/gin-gonic/gin/internal/json/json.go b/vendor/github.com/gin-gonic/gin/internal/json/json.go index 172aeb241..a26d7db2e 100644 --- a/vendor/github.com/gin-gonic/gin/internal/json/json.go +++ b/vendor/github.com/gin-gonic/gin/internal/json/json.go @@ -1,9 +1,9 @@ -// Copyright 2017 Bo-Yi Wu. All rights reserved. +// Copyright 2017 Bo-Yi Wu. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. -//go:build !jsoniter -// +build !jsoniter +//go:build !jsoniter && !go_json +// +build !jsoniter,!go_json package json diff --git a/vendor/github.com/gin-gonic/gin/internal/json/jsoniter.go b/vendor/github.com/gin-gonic/gin/internal/json/jsoniter.go index 232f8dcad..853b1a901 100644 --- a/vendor/github.com/gin-gonic/gin/internal/json/jsoniter.go +++ b/vendor/github.com/gin-gonic/gin/internal/json/jsoniter.go @@ -1,4 +1,4 @@ -// Copyright 2017 Bo-Yi Wu. All rights reserved. +// Copyright 2017 Bo-Yi Wu. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. diff --git a/vendor/github.com/gin-gonic/gin/logger.go b/vendor/github.com/gin-gonic/gin/logger.go index d361b74d3..cd1e7fa6e 100644 --- a/vendor/github.com/gin-gonic/gin/logger.go +++ b/vendor/github.com/gin-gonic/gin/logger.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -44,7 +44,7 @@ type LoggerConfig struct { // Optional. Default value is gin.DefaultWriter. Output io.Writer - // SkipPaths is a url path array which logs are not written. + // SkipPaths is an url path array which logs are not written. // Optional. SkipPaths []string } @@ -70,12 +70,12 @@ type LogFormatterParams struct { Path string // ErrorMessage is set if error has occurred in processing the request. ErrorMessage string - // isTerm shows whether does gin's output descriptor refers to a terminal. + // isTerm shows whether gin's output descriptor refers to a terminal. isTerm bool // BodySize is the size of the Response Body BodySize int // Keys are the keys set on the request's context. - Keys map[string]interface{} + Keys map[string]any } // StatusCodeColor is the ANSI color for appropriately logging http status code to a terminal. @@ -138,8 +138,7 @@ var defaultLogFormatter = func(param LogFormatterParams) string { } if param.Latency > time.Minute { - // Truncate in a golang < 1.8 safe way - param.Latency = param.Latency - param.Latency%time.Second + param.Latency = param.Latency.Truncate(time.Second) } return fmt.Sprintf("[GIN] %v |%s %3d %s| %13v | %15s |%s %-7s %s %#v\n%s", param.TimeStamp.Format("2006/01/02 - 15:04:05"), @@ -162,12 +161,12 @@ func ForceConsoleColor() { consoleColorMode = forceColor } -// ErrorLogger returns a handlerfunc for any error type. +// ErrorLogger returns a HandlerFunc for any error type. func ErrorLogger() HandlerFunc { return ErrorLoggerT(ErrorTypeAny) } -// ErrorLoggerT returns a handlerfunc for a given error type. +// ErrorLoggerT returns a HandlerFunc for a given error type. func ErrorLoggerT(typ ErrorType) HandlerFunc { return func(c *Context) { c.Next() @@ -179,7 +178,7 @@ func ErrorLoggerT(typ ErrorType) HandlerFunc { } // Logger instances a Logger middleware that will write the logs to gin.DefaultWriter. -// By default gin.DefaultWriter = os.Stdout. +// By default, gin.DefaultWriter = os.Stdout. func Logger() HandlerFunc { return LoggerWithConfig(LoggerConfig{}) } diff --git a/vendor/github.com/gin-gonic/gin/mode.go b/vendor/github.com/gin-gonic/gin/mode.go index c8813aff2..545fdaaf8 100644 --- a/vendor/github.com/gin-gonic/gin/mode.go +++ b/vendor/github.com/gin-gonic/gin/mode.go @@ -1,10 +1,11 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. package gin import ( + "flag" "io" "os" @@ -41,8 +42,10 @@ var DefaultWriter io.Writer = os.Stdout // DefaultErrorWriter is the default io.Writer used by Gin to debug errors var DefaultErrorWriter io.Writer = os.Stderr -var ginMode = debugCode -var modeName = DebugMode +var ( + ginMode = debugCode + modeName = DebugMode +) func init() { mode := os.Getenv(EnvGinMode) @@ -52,7 +55,11 @@ func init() { // SetMode sets gin mode according to input string. func SetMode(value string) { if value == "" { - value = DebugMode + if flag.Lookup("test.v") != nil { + value = TestMode + } else { + value = DebugMode + } } switch value { @@ -86,7 +93,7 @@ func EnableJsonDecoderDisallowUnknownFields() { binding.EnableDecoderDisallowUnknownFields = true } -// Mode returns currently gin mode. +// Mode returns current gin mode. func Mode() string { return modeName } diff --git a/vendor/github.com/gin-gonic/gin/recovery.go b/vendor/github.com/gin-gonic/gin/recovery.go index 563f5aaa8..abb645105 100644 --- a/vendor/github.com/gin-gonic/gin/recovery.go +++ b/vendor/github.com/gin-gonic/gin/recovery.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -6,6 +6,7 @@ package gin import ( "bytes" + "errors" "fmt" "io" "io/ioutil" @@ -27,14 +28,14 @@ var ( ) // RecoveryFunc defines the function passable to CustomRecovery. -type RecoveryFunc func(c *Context, err interface{}) +type RecoveryFunc func(c *Context, err any) // Recovery returns a middleware that recovers from any panics and writes a 500 if there was one. func Recovery() HandlerFunc { return RecoveryWithWriter(DefaultErrorWriter) } -//CustomRecovery returns a middleware that recovers from any panics and calls the provided handle func to handle it. +// CustomRecovery returns a middleware that recovers from any panics and calls the provided handle func to handle it. func CustomRecovery(handle RecoveryFunc) HandlerFunc { return RecoveryWithWriter(DefaultErrorWriter, handle) } @@ -60,7 +61,8 @@ func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc { // condition that warrants a panic stack trace. var brokenPipe bool if ne, ok := err.(*net.OpError); ok { - if se, ok := ne.Err.(*os.SyscallError); ok { + var se *os.SyscallError + if errors.As(ne, &se) { if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") { brokenPipe = true } @@ -100,7 +102,7 @@ func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc { } } -func defaultHandleRecovery(c *Context, err interface{}) { +func defaultHandleRecovery(c *Context, err any) { c.AbortWithStatus(http.StatusInternalServerError) } @@ -153,7 +155,7 @@ func function(pc uintptr) []byte { // runtime/debug.*T·ptrmethod // and want // *T.ptrmethod - // Also the package path might contains dot (e.g. code.google.com/...), + // Also the package path might contain dot (e.g. code.google.com/...), // so first eliminate the path prefix if lastSlash := bytes.LastIndex(name, slash); lastSlash >= 0 { name = name[lastSlash+1:] @@ -165,7 +167,7 @@ func function(pc uintptr) []byte { return name } +// timeFormat returns a customized time string for logger. func timeFormat(t time.Time) string { - timeString := t.Format("2006/01/02 - 15:04:05") - return timeString + return t.Format("2006/01/02 - 15:04:05") } diff --git a/vendor/github.com/gin-gonic/gin/render/any.go b/vendor/github.com/gin-gonic/gin/render/any.go new file mode 100644 index 000000000..b19ad45d9 --- /dev/null +++ b/vendor/github.com/gin-gonic/gin/render/any.go @@ -0,0 +1,10 @@ +// Copyright 2021 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +//go:build !go1.18 +// +build !go1.18 + +package render + +type any = interface{} diff --git a/vendor/github.com/gin-gonic/gin/render/data.go b/vendor/github.com/gin-gonic/gin/render/data.go index 6ba657ba0..a653ea309 100644 --- a/vendor/github.com/gin-gonic/gin/render/data.go +++ b/vendor/github.com/gin-gonic/gin/render/data.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. diff --git a/vendor/github.com/gin-gonic/gin/render/html.go b/vendor/github.com/gin-gonic/gin/render/html.go index 6696ece99..c308408d2 100644 --- a/vendor/github.com/gin-gonic/gin/render/html.go +++ b/vendor/github.com/gin-gonic/gin/render/html.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -20,7 +20,7 @@ type Delims struct { // HTMLRender interface is to be implemented by HTMLProduction and HTMLDebug. type HTMLRender interface { // Instance returns an HTML instance. - Instance(string, interface{}) Render + Instance(string, any) Render } // HTMLProduction contains template reference and its delims. @@ -41,13 +41,13 @@ type HTMLDebug struct { type HTML struct { Template *template.Template Name string - Data interface{} + Data any } var htmlContentType = []string{"text/html; charset=utf-8"} // Instance (HTMLProduction) returns an HTML instance which it realizes Render interface. -func (r HTMLProduction) Instance(name string, data interface{}) Render { +func (r HTMLProduction) Instance(name string, data any) Render { return HTML{ Template: r.Template, Name: name, @@ -56,7 +56,7 @@ func (r HTMLProduction) Instance(name string, data interface{}) Render { } // Instance (HTMLDebug) returns an HTML instance which it realizes Render interface. -func (r HTMLDebug) Instance(name string, data interface{}) Render { +func (r HTMLDebug) Instance(name string, data any) Render { return HTML{ Template: r.loadTemplate(), Name: name, diff --git a/vendor/github.com/gin-gonic/gin/render/json.go b/vendor/github.com/gin-gonic/gin/render/json.go index 418630939..af678e80d 100644 --- a/vendor/github.com/gin-gonic/gin/render/json.go +++ b/vendor/github.com/gin-gonic/gin/render/json.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -16,39 +16,41 @@ import ( // JSON contains the given interface object. type JSON struct { - Data interface{} + Data any } // IndentedJSON contains the given interface object. type IndentedJSON struct { - Data interface{} + Data any } // SecureJSON contains the given interface object and its prefix. type SecureJSON struct { Prefix string - Data interface{} + Data any } // JsonpJSON contains the given interface object its callback. type JsonpJSON struct { Callback string - Data interface{} + Data any } // AsciiJSON contains the given interface object. type AsciiJSON struct { - Data interface{} + Data any } // PureJSON contains the given interface object. type PureJSON struct { - Data interface{} + Data any } -var jsonContentType = []string{"application/json; charset=utf-8"} -var jsonpContentType = []string{"application/javascript; charset=utf-8"} -var jsonAsciiContentType = []string{"application/json"} +var ( + jsonContentType = []string{"application/json; charset=utf-8"} + jsonpContentType = []string{"application/javascript; charset=utf-8"} + jsonASCIIContentType = []string{"application/json"} +) // Render (JSON) writes data with custom ContentType. func (r JSON) Render(w http.ResponseWriter) (err error) { @@ -64,7 +66,7 @@ func (r JSON) WriteContentType(w http.ResponseWriter) { } // WriteJSON marshals the given interface object and writes it with custom ContentType. -func WriteJSON(w http.ResponseWriter, obj interface{}) error { +func WriteJSON(w http.ResponseWriter, obj any) error { writeContentType(w, jsonContentType) jsonBytes, err := json.Marshal(obj) if err != nil { @@ -100,8 +102,7 @@ func (r SecureJSON) Render(w http.ResponseWriter) error { // if the jsonBytes is array values if bytes.HasPrefix(jsonBytes, bytesconv.StringToBytes("[")) && bytes.HasSuffix(jsonBytes, bytesconv.StringToBytes("]")) { - _, err = w.Write(bytesconv.StringToBytes(r.Prefix)) - if err != nil { + if _, err = w.Write(bytesconv.StringToBytes(r.Prefix)); err != nil { return err } } @@ -128,20 +129,19 @@ func (r JsonpJSON) Render(w http.ResponseWriter) (err error) { } callback := template.JSEscapeString(r.Callback) - _, err = w.Write(bytesconv.StringToBytes(callback)) - if err != nil { + if _, err = w.Write(bytesconv.StringToBytes(callback)); err != nil { return err } - _, err = w.Write(bytesconv.StringToBytes("(")) - if err != nil { + + if _, err = w.Write(bytesconv.StringToBytes("(")); err != nil { return err } - _, err = w.Write(ret) - if err != nil { + + if _, err = w.Write(ret); err != nil { return err } - _, err = w.Write(bytesconv.StringToBytes(");")) - if err != nil { + + if _, err = w.Write(bytesconv.StringToBytes(");")); err != nil { return err } @@ -176,7 +176,7 @@ func (r AsciiJSON) Render(w http.ResponseWriter) (err error) { // WriteContentType (AsciiJSON) writes JSON ContentType. func (r AsciiJSON) WriteContentType(w http.ResponseWriter) { - writeContentType(w, jsonAsciiContentType) + writeContentType(w, jsonASCIIContentType) } // Render (PureJSON) writes custom ContentType and encodes the given interface object. diff --git a/vendor/github.com/gin-gonic/gin/render/msgpack.go b/vendor/github.com/gin-gonic/gin/render/msgpack.go index 6ef5b6e51..e0f30f7a9 100644 --- a/vendor/github.com/gin-gonic/gin/render/msgpack.go +++ b/vendor/github.com/gin-gonic/gin/render/msgpack.go @@ -1,4 +1,4 @@ -// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -13,13 +13,15 @@ import ( "github.com/ugorji/go/codec" ) +// Check interface implemented here to support go build tag nomsgpack. +// See: https://github.com/gin-gonic/gin/pull/1852/ var ( _ Render = MsgPack{} ) // MsgPack contains the given interface object. type MsgPack struct { - Data interface{} + Data any } var msgpackContentType = []string{"application/msgpack; charset=utf-8"} @@ -35,7 +37,7 @@ func (r MsgPack) Render(w http.ResponseWriter) error { } // WriteMsgPack writes MsgPack ContentType and encodes the given interface object. -func WriteMsgPack(w http.ResponseWriter, obj interface{}) error { +func WriteMsgPack(w http.ResponseWriter, obj any) error { writeContentType(w, msgpackContentType) var mh codec.MsgpackHandle return codec.NewEncoder(w, &mh).Encode(obj) diff --git a/vendor/github.com/gin-gonic/gin/render/protobuf.go b/vendor/github.com/gin-gonic/gin/render/protobuf.go index 15aca9959..9331c4058 100644 --- a/vendor/github.com/gin-gonic/gin/render/protobuf.go +++ b/vendor/github.com/gin-gonic/gin/render/protobuf.go @@ -1,4 +1,4 @@ -// Copyright 2018 Gin Core Team. All rights reserved. +// Copyright 2018 Gin Core Team. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -7,12 +7,12 @@ package render import ( "net/http" - "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/proto" ) // ProtoBuf contains the given interface object. type ProtoBuf struct { - Data interface{} + Data any } var protobufContentType = []string{"application/x-protobuf"} diff --git a/vendor/github.com/gin-gonic/gin/render/reader.go b/vendor/github.com/gin-gonic/gin/render/reader.go index d5282e492..5752d8d85 100644 --- a/vendor/github.com/gin-gonic/gin/render/reader.go +++ b/vendor/github.com/gin-gonic/gin/render/reader.go @@ -1,4 +1,4 @@ -// Copyright 2018 Gin Core Team. All rights reserved. +// Copyright 2018 Gin Core Team. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. diff --git a/vendor/github.com/gin-gonic/gin/render/redirect.go b/vendor/github.com/gin-gonic/gin/render/redirect.go index c006691ca..70e3a47e8 100644 --- a/vendor/github.com/gin-gonic/gin/render/redirect.go +++ b/vendor/github.com/gin-gonic/gin/render/redirect.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. diff --git a/vendor/github.com/gin-gonic/gin/render/render.go b/vendor/github.com/gin-gonic/gin/render/render.go index bcd568bfb..7955000c6 100644 --- a/vendor/github.com/gin-gonic/gin/render/render.go +++ b/vendor/github.com/gin-gonic/gin/render/render.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -30,6 +30,7 @@ var ( _ Render = Reader{} _ Render = AsciiJSON{} _ Render = ProtoBuf{} + _ Render = TOML{} ) func writeContentType(w http.ResponseWriter, value []string) { diff --git a/vendor/github.com/gin-gonic/gin/render/text.go b/vendor/github.com/gin-gonic/gin/render/text.go index 461b720af..77eafdfd8 100644 --- a/vendor/github.com/gin-gonic/gin/render/text.go +++ b/vendor/github.com/gin-gonic/gin/render/text.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -14,7 +14,7 @@ import ( // String contains the given interface object slice and its format. type String struct { Format string - Data []interface{} + Data []any } var plainContentType = []string{"text/plain; charset=utf-8"} @@ -30,7 +30,7 @@ func (r String) WriteContentType(w http.ResponseWriter) { } // WriteString writes data according to its format and write custom ContentType. -func WriteString(w http.ResponseWriter, format string, data []interface{}) (err error) { +func WriteString(w http.ResponseWriter, format string, data []any) (err error) { writeContentType(w, plainContentType) if len(data) > 0 { _, err = fmt.Fprintf(w, format, data...) diff --git a/vendor/github.com/gin-gonic/gin/render/toml.go b/vendor/github.com/gin-gonic/gin/render/toml.go new file mode 100644 index 000000000..40f044c88 --- /dev/null +++ b/vendor/github.com/gin-gonic/gin/render/toml.go @@ -0,0 +1,36 @@ +// Copyright 2022 Gin Core Team. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "net/http" + + "github.com/pelletier/go-toml/v2" +) + +// TOML contains the given interface object. +type TOML struct { + Data any +} + +var TOMLContentType = []string{"application/toml; charset=utf-8"} + +// Render (TOML) marshals the given interface object and writes data with custom ContentType. +func (r TOML) Render(w http.ResponseWriter) error { + r.WriteContentType(w) + + bytes, err := toml.Marshal(r.Data) + if err != nil { + return err + } + + _, err = w.Write(bytes) + return err +} + +// WriteContentType (TOML) writes TOML ContentType for response. +func (r TOML) WriteContentType(w http.ResponseWriter) { + writeContentType(w, TOMLContentType) +} diff --git a/vendor/github.com/gin-gonic/gin/render/xml.go b/vendor/github.com/gin-gonic/gin/render/xml.go index cc5390a2d..6af890179 100644 --- a/vendor/github.com/gin-gonic/gin/render/xml.go +++ b/vendor/github.com/gin-gonic/gin/render/xml.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -11,7 +11,7 @@ import ( // XML contains the given interface object. type XML struct { - Data interface{} + Data any } var xmlContentType = []string{"application/xml; charset=utf-8"} diff --git a/vendor/github.com/gin-gonic/gin/render/yaml.go b/vendor/github.com/gin-gonic/gin/render/yaml.go index 0df783608..4f0ac01f6 100644 --- a/vendor/github.com/gin-gonic/gin/render/yaml.go +++ b/vendor/github.com/gin-gonic/gin/render/yaml.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -12,7 +12,7 @@ import ( // YAML contains the given interface object. type YAML struct { - Data interface{} + Data any } var yamlContentType = []string{"application/x-yaml; charset=utf-8"} diff --git a/vendor/github.com/gin-gonic/gin/response_writer.go b/vendor/github.com/gin-gonic/gin/response_writer.go index 26826689a..77c7ed8fd 100644 --- a/vendor/github.com/gin-gonic/gin/response_writer.go +++ b/vendor/github.com/gin-gonic/gin/response_writer.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -23,23 +23,23 @@ type ResponseWriter interface { http.Flusher http.CloseNotifier - // Returns the HTTP response status code of the current request. + // Status returns the HTTP response status code of the current request. Status() int - // Returns the number of bytes already written into the response http body. + // Size returns the number of bytes already written into the response http body. // See Written() Size() int - // Writes the string into the response body. + // WriteString writes the string into the response body. WriteString(string) (int, error) - // Returns true if the response body was already written. + // Written returns true if the response body was already written. Written() bool - // Forces to write the http header (status code + headers). + // WriteHeaderNow forces to write the http header (status code + headers). WriteHeaderNow() - // get the http.Pusher for server push + // Pusher get the http.Pusher for server push Pusher() http.Pusher } @@ -107,12 +107,12 @@ func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { return w.ResponseWriter.(http.Hijacker).Hijack() } -// CloseNotify implements the http.CloseNotify interface. +// CloseNotify implements the http.CloseNotifier interface. func (w *responseWriter) CloseNotify() <-chan bool { return w.ResponseWriter.(http.CloseNotifier).CloseNotify() } -// Flush implements the http.Flush interface. +// Flush implements the http.Flusher interface. func (w *responseWriter) Flush() { w.WriteHeaderNow() w.ResponseWriter.(http.Flusher).Flush() diff --git a/vendor/github.com/gin-gonic/gin/routergroup.go b/vendor/github.com/gin-gonic/gin/routergroup.go index 15d9930d3..3c082d932 100644 --- a/vendor/github.com/gin-gonic/gin/routergroup.go +++ b/vendor/github.com/gin-gonic/gin/routergroup.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -11,6 +11,18 @@ import ( "strings" ) +var ( + // regEnLetter matches english letters for http method name + regEnLetter = regexp.MustCompile("^[A-Z]+$") + + // anyMethods for RouterGroup Any method + anyMethods = []string{ + http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, + http.MethodHead, http.MethodOptions, http.MethodDelete, http.MethodConnect, + http.MethodTrace, + } +) + // IRouter defines all router handle interface includes single and group router. type IRouter interface { IRoutes @@ -32,6 +44,7 @@ type IRoutes interface { HEAD(string, ...HandlerFunc) IRoutes StaticFile(string, string) IRoutes + StaticFileFS(string, string, http.FileSystem) IRoutes Static(string, string) IRoutes StaticFS(string, http.FileSystem) IRoutes } @@ -87,7 +100,7 @@ func (group *RouterGroup) handle(httpMethod, relativePath string, handlers Handl // frequently used, non-standardized or custom methods (e.g. for internal // communication with a proxy). func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes { - if matches, err := regexp.MatchString("^[A-Z]+$", httpMethod); !matches || err != nil { + if matched := regEnLetter.MatchString(httpMethod); !matched { panic("http method " + httpMethod + " is not valid") } return group.handle(httpMethod, relativePath, handlers) @@ -131,27 +144,34 @@ func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRo // Any registers a route that matches all the HTTP methods. // GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE. func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRoutes { - group.handle(http.MethodGet, relativePath, handlers) - group.handle(http.MethodPost, relativePath, handlers) - group.handle(http.MethodPut, relativePath, handlers) - group.handle(http.MethodPatch, relativePath, handlers) - group.handle(http.MethodHead, relativePath, handlers) - group.handle(http.MethodOptions, relativePath, handlers) - group.handle(http.MethodDelete, relativePath, handlers) - group.handle(http.MethodConnect, relativePath, handlers) - group.handle(http.MethodTrace, relativePath, handlers) + for _, method := range anyMethods { + group.handle(method, relativePath, handlers) + } + return group.returnObj() } // StaticFile registers a single route in order to serve a single file of the local filesystem. // router.StaticFile("favicon.ico", "./resources/favicon.ico") func (group *RouterGroup) StaticFile(relativePath, filepath string) IRoutes { + return group.staticFileHandler(relativePath, func(c *Context) { + c.File(filepath) + }) +} + +// StaticFileFS works just like `StaticFile` but a custom `http.FileSystem` can be used instead.. +// router.StaticFileFS("favicon.ico", "./resources/favicon.ico", Dir{".", false}) +// Gin by default user: gin.Dir() +func (group *RouterGroup) StaticFileFS(relativePath, filepath string, fs http.FileSystem) IRoutes { + return group.staticFileHandler(relativePath, func(c *Context) { + c.FileFromFS(filepath, fs) + }) +} + +func (group *RouterGroup) staticFileHandler(relativePath string, handler HandlerFunc) IRoutes { if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") { panic("URL parameters can not be used when serving a static file") } - handler := func(c *Context) { - c.File(filepath) - } group.GET(relativePath, handler) group.HEAD(relativePath, handler) return group.returnObj() @@ -209,9 +229,7 @@ func (group *RouterGroup) createStaticHandler(relativePath string, fs http.FileS func (group *RouterGroup) combineHandlers(handlers HandlersChain) HandlersChain { finalSize := len(group.Handlers) + len(handlers) - if finalSize >= int(abortIndex) { - panic("too many handlers") - } + assert1(finalSize < int(abortIndex), "too many handlers") mergedHandlers := make(HandlersChain, finalSize) copy(mergedHandlers, group.Handlers) copy(mergedHandlers[len(group.Handlers):], handlers) diff --git a/vendor/github.com/gin-gonic/gin/test_helpers.go b/vendor/github.com/gin-gonic/gin/test_helpers.go index 3a7a5ddf6..b3be93b4e 100644 --- a/vendor/github.com/gin-gonic/gin/test_helpers.go +++ b/vendor/github.com/gin-gonic/gin/test_helpers.go @@ -1,4 +1,4 @@ -// Copyright 2017 Manu Martinez-Almeida. All rights reserved. +// Copyright 2017 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. diff --git a/vendor/github.com/gin-gonic/gin/tree.go b/vendor/github.com/gin-gonic/gin/tree.go index 158a33908..88100eec8 100644 --- a/vendor/github.com/gin-gonic/gin/tree.go +++ b/vendor/github.com/gin-gonic/gin/tree.go @@ -31,8 +31,8 @@ type Param struct { // It is therefore safe to read values by the index. type Params []Param -// Get returns the value of the first Param which key matches the given name. -// If no matching Param is found, an empty string is returned. +// Get returns the value of the first Param which key matches the given name and a boolean true. +// If no matching Param is found, an empty string is returned and a boolean false . func (ps Params) Get(name string) (string, bool) { for _, entry := range ps { if entry.Key == name { @@ -81,7 +81,7 @@ func longestCommonPrefix(a, b string) int { return i } -// addChild will add a child node, keeping wildcards at the end +// addChild will add a child node, keeping wildcardChild at the end func (n *node) addChild(child *node) { if n.wildChild && len(n.children) > 0 { wildcardChild := n.children[len(n.children)-1] @@ -107,8 +107,7 @@ func countSections(path string) uint16 { type nodeType uint8 const ( - static nodeType = iota // default - root + root nodeType = iota + 1 param catchAll ) @@ -297,7 +296,7 @@ func (n *node) insertChild(path string, fullPath string, handlers HandlersChain) break } - // The wildcard name must not contain ':' and '*' + // The wildcard name must only contain one ':' or '*' character if !valid { panic("only one wildcard per path segment is allowed, has: '" + wildcard + "' in path '" + fullPath + "'") @@ -326,7 +325,7 @@ func (n *node) insertChild(path string, fullPath string, handlers HandlersChain) n.priority++ // if the path doesn't end with the wildcard, then there - // will be another non-wildcard subpath starting with '/' + // will be another subpath starting with '/' if len(wildcard) < len(path) { path = path[len(wildcard):] @@ -350,7 +349,12 @@ func (n *node) insertChild(path string, fullPath string, handlers HandlersChain) } if len(n.path) > 0 && n.path[len(n.path)-1] == '/' { - panic("catch-all conflicts with existing handle for the path segment root in path '" + fullPath + "'") + pathSeg := strings.SplitN(n.children[0].path, "/", 2)[0] + panic("catch-all wildcard '" + path + + "' in new path '" + fullPath + + "' conflicts with existing path segment '" + pathSeg + + "' in existing prefix '" + n.path + pathSeg + + "'") } // currently fixed width 1 for '/' @@ -531,7 +535,7 @@ walk: // Outer loop for walking the tree // No handle found. Check if a handle for this path + a // trailing slash exists for TSR recommendation n = n.children[0] - value.tsr = n.path == "/" && n.handlers != nil + value.tsr = (n.path == "/" && n.handlers != nil) || (n.path == "" && n.indices == "/") } return diff --git a/vendor/github.com/gin-gonic/gin/utils.go b/vendor/github.com/gin-gonic/gin/utils.go index c32f0eeb0..4021a2ab4 100644 --- a/vendor/github.com/gin-gonic/gin/utils.go +++ b/vendor/github.com/gin-gonic/gin/utils.go @@ -1,4 +1,4 @@ -// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. @@ -12,13 +12,14 @@ import ( "reflect" "runtime" "strings" + "unicode" ) // BindKey indicates a default bind key. const BindKey = "_gin-gonic/gin/bindkey" // Bind is a helper function for given interface object and returns a Gin middleware. -func Bind(val interface{}) HandlerFunc { +func Bind(val any) HandlerFunc { value := reflect.ValueOf(val) if value.Kind() == reflect.Ptr { panic(`Bind struct can not be a pointer. Example: @@ -50,7 +51,7 @@ func WrapH(h http.Handler) HandlerFunc { } // H is a shortcut for map[string]interface{} -type H map[string]interface{} +type H map[string]any // MarshalXML allows type H to be used with xml.Marshal. func (h H) MarshalXML(e *xml.Encoder, start xml.StartElement) error { @@ -89,7 +90,7 @@ func filterFlags(content string) string { return content } -func chooseData(custom, wildcard interface{}) interface{} { +func chooseData(custom, wildcard any) any { if custom != nil { return custom } @@ -120,7 +121,7 @@ func lastChar(str string) uint8 { return str[len(str)-1] } -func nameOfFunction(f interface{}) string { +func nameOfFunction(f any) string { return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name() } @@ -151,3 +152,13 @@ func resolveAddress(addr []string) string { panic("too many parameters") } } + +// https://stackoverflow.com/questions/53069040/checking-a-string-contains-only-ascii-characters +func isASCII(s string) bool { + for i := 0; i < len(s); i++ { + if s[i] > unicode.MaxASCII { + return false + } + } + return true +} diff --git a/vendor/github.com/gin-gonic/gin/version.go b/vendor/github.com/gin-gonic/gin/version.go index 4b69b9b91..632ca7d1d 100644 --- a/vendor/github.com/gin-gonic/gin/version.go +++ b/vendor/github.com/gin-gonic/gin/version.go @@ -1,8 +1,8 @@ -// Copyright 2018 Gin Core Team. All rights reserved. +// Copyright 2018 Gin Core Team. All rights reserved. // Use of this source code is governed by a MIT style // license that can be found in the LICENSE file. package gin // Version is the current gin framework's version. -const Version = "v1.7.7" +const Version = "v1.8.1" |