mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 22:42:24 -05:00 
			
		
		
		
	Grand test fixup (#138)
* start fixing up tests * fix up tests + automate with drone * fiddle with linting * messing about with drone.yml * some more fiddling * hmmm * add cache * add vendor directory * verbose * ci updates * update some little things * update sig
This commit is contained in:
		
					parent
					
						
							
								329a5e8144
							
						
					
				
			
			
				commit
				
					
						98263a7de6
					
				
			
		
					 2677 changed files with 1090869 additions and 219 deletions
				
			
		
							
								
								
									
										7
									
								
								vendor/github.com/gin-gonic/gin/.gitignore
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/gin-gonic/gin/.gitignore
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| vendor/* | ||||
| !vendor/vendor.json | ||||
| coverage.out | ||||
| count.out | ||||
| test | ||||
| profile.out | ||||
| tmp.out | ||||
							
								
								
									
										233
									
								
								vendor/github.com/gin-gonic/gin/AUTHORS.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								vendor/github.com/gin-gonic/gin/AUTHORS.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,233 @@ | |||
| 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 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 | ||||
| 
 | ||||
| 
 | ||||
| **@yuyabee** | ||||
| - Fixed README | ||||
							
								
								
									
										666
									
								
								vendor/github.com/gin-gonic/gin/BENCHMARKS.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										666
									
								
								vendor/github.com/gin-gonic/gin/BENCHMARKS.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,666 @@ | |||
| 
 | ||||
| # Benchmark System | ||||
| 
 | ||||
| **VM HOST:** Travis | ||||
| **Machine:** Ubuntu 16.04.6 LTS x64 | ||||
| **Date:** May 04th, 2020 | ||||
| **Version:** Gin v1.6.3 | ||||
| **Go Version:** 1.14.2 linux/amd64 | ||||
| **Source:** [Go HTTP Router Benchmark](https://github.com/gin-gonic/go-http-routing-benchmark) | ||||
| **Result:** [See the gist](https://gist.github.com/appleboy/b5f2ecfaf50824ae9c64dcfb9165ae5e) or [Travis result](https://travis-ci.org/github/gin-gonic/go-http-routing-benchmark/jobs/682947061) | ||||
| 
 | ||||
| ## Static Routes: 157 | ||||
| 
 | ||||
| ```sh | ||||
| Gin: 34936 Bytes | ||||
| 
 | ||||
| HttpServeMux: 14512 Bytes | ||||
| Ace: 30680 Bytes | ||||
| Aero: 34536 Bytes | ||||
| Bear: 30456 Bytes | ||||
| Beego: 98456 Bytes | ||||
| Bone: 40224 Bytes | ||||
| Chi: 83608 Bytes | ||||
| Denco: 10216 Bytes | ||||
| Echo: 80328 Bytes | ||||
| GocraftWeb: 55288 Bytes | ||||
| Goji: 29744 Bytes | ||||
| Gojiv2: 105840 Bytes | ||||
| GoJsonRest: 137496 Bytes | ||||
| GoRestful: 816936 Bytes | ||||
| GorillaMux: 585632 Bytes | ||||
| GowwwRouter: 24968 Bytes | ||||
| HttpRouter: 21712 Bytes | ||||
| HttpTreeMux: 73448 Bytes | ||||
| Kocha: 115472 Bytes | ||||
| LARS: 30640 Bytes | ||||
| Macaron: 38592 Bytes | ||||
| Martini: 310864 Bytes | ||||
| Pat: 19696 Bytes | ||||
| Possum: 89920 Bytes | ||||
| R2router: 23712 Bytes | ||||
| Rivet: 24608 Bytes | ||||
| Tango: 28264 Bytes | ||||
| TigerTonic: 78768 Bytes | ||||
| Traffic: 538976 Bytes | ||||
| Vulcan: 369960 Bytes | ||||
| ``` | ||||
| 
 | ||||
| ## GithubAPI Routes: 203 | ||||
| 
 | ||||
| ```sh | ||||
| Gin: 58512 Bytes | ||||
| 
 | ||||
| Ace: 48688 Bytes | ||||
| Aero: 318568 Bytes | ||||
| Bear: 84248 Bytes | ||||
| Beego: 150936 Bytes | ||||
| Bone: 100976 Bytes | ||||
| Chi: 95112 Bytes | ||||
| Denco: 36736 Bytes | ||||
| Echo: 100296 Bytes | ||||
| GocraftWeb: 95432 Bytes | ||||
| Goji: 49680 Bytes | ||||
| Gojiv2: 104704 Bytes | ||||
| GoJsonRest: 141976 Bytes | ||||
| GoRestful: 1241656 Bytes | ||||
| GorillaMux: 1322784 Bytes | ||||
| GowwwRouter: 80008 Bytes | ||||
| HttpRouter: 37144 Bytes | ||||
| HttpTreeMux: 78800 Bytes | ||||
| Kocha: 785120 Bytes | ||||
| LARS: 48600 Bytes | ||||
| Macaron: 92784 Bytes | ||||
| Martini: 485264 Bytes | ||||
| Pat: 21200 Bytes | ||||
| Possum: 85312 Bytes | ||||
| R2router: 47104 Bytes | ||||
| Rivet: 42840 Bytes | ||||
| Tango: 54840 Bytes | ||||
| TigerTonic: 95264 Bytes | ||||
| Traffic: 921744 Bytes | ||||
| Vulcan: 425992 Bytes | ||||
| ``` | ||||
| 
 | ||||
| ## GPlusAPI Routes: 13 | ||||
| 
 | ||||
| ```sh | ||||
| Gin: 4384 Bytes | ||||
| 
 | ||||
| Ace: 3712 Bytes | ||||
| Aero: 26056 Bytes | ||||
| Bear: 7112 Bytes | ||||
| Beego: 10272 Bytes | ||||
| Bone: 6688 Bytes | ||||
| Chi: 8024 Bytes | ||||
| Denco: 3264 Bytes | ||||
| Echo: 9688 Bytes | ||||
| GocraftWeb: 7496 Bytes | ||||
| Goji: 3152 Bytes | ||||
| Gojiv2: 7376 Bytes | ||||
| GoJsonRest: 11400 Bytes | ||||
| GoRestful: 74328 Bytes | ||||
| GorillaMux: 66208 Bytes | ||||
| GowwwRouter: 5744 Bytes | ||||
| HttpRouter: 2808 Bytes | ||||
| HttpTreeMux: 7440 Bytes | ||||
| Kocha: 128880 Bytes | ||||
| LARS: 3656 Bytes | ||||
| Macaron: 8656 Bytes | ||||
| Martini: 23920 Bytes | ||||
| Pat: 1856 Bytes | ||||
| Possum: 7248 Bytes | ||||
| R2router: 3928 Bytes | ||||
| Rivet: 3064 Bytes | ||||
| Tango: 5168 Bytes | ||||
| TigerTonic: 9408 Bytes | ||||
| Traffic: 46400 Bytes | ||||
| Vulcan: 25544 Bytes | ||||
| ``` | ||||
| 
 | ||||
| ## ParseAPI Routes: 26 | ||||
| 
 | ||||
| ```sh | ||||
| Gin: 7776 Bytes | ||||
| 
 | ||||
| Ace: 6704 Bytes | ||||
| Aero: 28488 Bytes | ||||
| Bear: 12320 Bytes | ||||
| Beego: 19280 Bytes | ||||
| Bone: 11440 Bytes | ||||
| Chi: 9744 Bytes | ||||
| Denco: 4192 Bytes | ||||
| Echo: 11664 Bytes | ||||
| GocraftWeb: 12800 Bytes | ||||
| Goji: 5680 Bytes | ||||
| Gojiv2: 14464 Bytes | ||||
| GoJsonRest: 14072 Bytes | ||||
| GoRestful: 116264 Bytes | ||||
| GorillaMux: 105880 Bytes | ||||
| GowwwRouter: 9344 Bytes | ||||
| HttpRouter: 5072 Bytes | ||||
| HttpTreeMux: 7848 Bytes | ||||
| Kocha: 181712 Bytes | ||||
| LARS: 6632 Bytes | ||||
| Macaron: 13648 Bytes | ||||
| Martini: 45888 Bytes | ||||
| Pat: 2560 Bytes | ||||
| Possum: 9200 Bytes | ||||
| R2router: 7056 Bytes | ||||
| Rivet: 5680 Bytes | ||||
| Tango: 8920 Bytes | ||||
| TigerTonic: 9840 Bytes | ||||
| Traffic: 79096 Bytes | ||||
| Vulcan: 44504 Bytes | ||||
| ``` | ||||
| 
 | ||||
| ## Static Routes | ||||
| 
 | ||||
| ```sh | ||||
| BenchmarkGin_StaticAll                   62169         19319 ns/op           0 B/op           0 allocs/op | ||||
| 
 | ||||
| BenchmarkAce_StaticAll                   65428         18313 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_StaticAll                 121132          9632 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpServeMux_StaticAll          52626         22758 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBeego_StaticAll                  9962        179058 ns/op       55264 B/op         471 allocs/op | ||||
| BenchmarkBear_StaticAll                  14894         80966 ns/op       20272 B/op         469 allocs/op | ||||
| BenchmarkBone_StaticAll                  18718         64065 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkChi_StaticAll                   10000        149827 ns/op       67824 B/op         471 allocs/op | ||||
| BenchmarkDenco_StaticAll                211393          5680 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkEcho_StaticAll                  49341         24343 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_StaticAll            10000        126209 ns/op       46312 B/op         785 allocs/op | ||||
| BenchmarkGoji_StaticAll                  27956         43174 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGojiv2_StaticAll                 3430        370718 ns/op      205984 B/op        1570 allocs/op | ||||
| BenchmarkGoJsonRest_StaticAll             9134        188888 ns/op       51653 B/op        1727 allocs/op | ||||
| BenchmarkGoRestful_StaticAll               706       1703330 ns/op      613280 B/op        2053 allocs/op | ||||
| BenchmarkGorillaMux_StaticAll             1268        924083 ns/op      153233 B/op        1413 allocs/op | ||||
| BenchmarkGowwwRouter_StaticAll           63374         18935 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpRouter_StaticAll           109938         10902 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_StaticAll          109166         10861 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkKocha_StaticAll                 92258         12992 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkLARS_StaticAll                  65200         18387 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_StaticAll                5671        291501 ns/op      115553 B/op        1256 allocs/op | ||||
| BenchmarkMartini_StaticAll                 807       1460498 ns/op      125444 B/op        1717 allocs/op | ||||
| BenchmarkPat_StaticAll                     513       2342396 ns/op      602832 B/op       12559 allocs/op | ||||
| BenchmarkPossum_StaticAll                10000        128270 ns/op       65312 B/op         471 allocs/op | ||||
| BenchmarkR2router_StaticAll              16726         71760 ns/op       22608 B/op         628 allocs/op | ||||
| BenchmarkRivet_StaticAll                 41722         28723 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkTango_StaticAll                  7606        205082 ns/op       39209 B/op        1256 allocs/op | ||||
| BenchmarkTigerTonic_StaticAll            26247         45806 ns/op        7376 B/op         157 allocs/op | ||||
| BenchmarkTraffic_StaticAll                 550       2284518 ns/op      754864 B/op       14601 allocs/op | ||||
| BenchmarkVulcan_StaticAll                10000        131343 ns/op       15386 B/op         471 allocs/op | ||||
| ``` | ||||
| 
 | ||||
| ## Micro Benchmarks | ||||
| 
 | ||||
| ```sh | ||||
| BenchmarkGin_Param                    18785022          63.9 ns/op           0 B/op           0 allocs/op | ||||
| 
 | ||||
| BenchmarkAce_Param                    14689765          81.5 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_Param                   23094770          51.2 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_Param                    1417045           845 ns/op         456 B/op           5 allocs/op | ||||
| BenchmarkBeego_Param                   1000000          1080 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_Param                    1000000          1463 ns/op         816 B/op           6 allocs/op | ||||
| BenchmarkChi_Param                     1378756           885 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_Param                   8557899           143 ns/op          32 B/op           1 allocs/op | ||||
| BenchmarkEcho_Param                   16433347          75.5 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_Param              1000000          1218 ns/op         648 B/op           8 allocs/op | ||||
| BenchmarkGoji_Param                    1921248           617 ns/op         336 B/op           2 allocs/op | ||||
| BenchmarkGojiv2_Param                   561848          2156 ns/op        1328 B/op          11 allocs/op | ||||
| BenchmarkGoJsonRest_Param              1000000          1358 ns/op         649 B/op          13 allocs/op | ||||
| BenchmarkGoRestful_Param                224857          5307 ns/op        4192 B/op          14 allocs/op | ||||
| BenchmarkGorillaMux_Param               498313          2459 ns/op        1280 B/op          10 allocs/op | ||||
| BenchmarkGowwwRouter_Param             1864354           654 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkHttpRouter_Param             26269074          47.7 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_Param             2109829           557 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkKocha_Param                   5050216           243 ns/op          56 B/op           3 allocs/op | ||||
| BenchmarkLARS_Param                   19811712          59.9 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_Param                  662746          2329 ns/op        1072 B/op          10 allocs/op | ||||
| BenchmarkMartini_Param                  279902          4260 ns/op        1072 B/op          10 allocs/op | ||||
| BenchmarkPat_Param                     1000000          1382 ns/op         536 B/op          11 allocs/op | ||||
| BenchmarkPossum_Param                  1000000          1014 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkR2router_Param                1712559           707 ns/op         432 B/op           5 allocs/op | ||||
| BenchmarkRivet_Param                   6648086           182 ns/op          48 B/op           1 allocs/op | ||||
| BenchmarkTango_Param                   1221504           994 ns/op         248 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_Param               891661          2261 ns/op         776 B/op          16 allocs/op | ||||
| BenchmarkTraffic_Param                  350059          3598 ns/op        1856 B/op          21 allocs/op | ||||
| BenchmarkVulcan_Param                  2517823           472 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_Param5                    9214365           130 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_Param5                  15369013          77.9 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_Param5                   1000000          1113 ns/op         501 B/op           5 allocs/op | ||||
| BenchmarkBeego_Param5                  1000000          1269 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_Param5                    986820          1873 ns/op         864 B/op           6 allocs/op | ||||
| BenchmarkChi_Param5                    1000000          1156 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_Param5                  3036331           400 ns/op         160 B/op           1 allocs/op | ||||
| BenchmarkEcho_Param5                   6447133           186 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGin_Param5                   10786068           110 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_Param5              844820          1944 ns/op         920 B/op          11 allocs/op | ||||
| BenchmarkGoji_Param5                   1474965           827 ns/op         336 B/op           2 allocs/op | ||||
| BenchmarkGojiv2_Param5                  442820          2516 ns/op        1392 B/op          11 allocs/op | ||||
| BenchmarkGoJsonRest_Param5              507555          2711 ns/op        1097 B/op          16 allocs/op | ||||
| BenchmarkGoRestful_Param5               216481          6093 ns/op        4288 B/op          14 allocs/op | ||||
| BenchmarkGorillaMux_Param5              314402          3628 ns/op        1344 B/op          10 allocs/op | ||||
| BenchmarkGowwwRouter_Param5            1624660           733 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkHttpRouter_Param5            13167324          92.0 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_Param5            1000000          1295 ns/op         576 B/op           6 allocs/op | ||||
| BenchmarkKocha_Param5                  1000000          1138 ns/op         440 B/op          10 allocs/op | ||||
| BenchmarkLARS_Param5                  11580613           105 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_Param5                 473596          2755 ns/op        1072 B/op          10 allocs/op | ||||
| BenchmarkMartini_Param5                 230756          5111 ns/op        1232 B/op          11 allocs/op | ||||
| BenchmarkPat_Param5                     469190          3370 ns/op         888 B/op          29 allocs/op | ||||
| BenchmarkPossum_Param5                 1000000          1002 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkR2router_Param5               1422129           844 ns/op         432 B/op           5 allocs/op | ||||
| BenchmarkRivet_Param5                  2263789           539 ns/op         240 B/op           1 allocs/op | ||||
| BenchmarkTango_Param5                  1000000          1256 ns/op         360 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_Param5              175500          7492 ns/op        2279 B/op          39 allocs/op | ||||
| BenchmarkTraffic_Param5                 233631          5816 ns/op        2208 B/op          27 allocs/op | ||||
| BenchmarkVulcan_Param5                 1923416           629 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_Param20                   4321266           281 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_Param20                 31501641          35.2 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_Param20                   335204          3489 ns/op        1665 B/op           5 allocs/op | ||||
| BenchmarkBeego_Param20                  503674          2860 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_Param20                   298922          4741 ns/op        2031 B/op           6 allocs/op | ||||
| BenchmarkChi_Param20                    878181          1957 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_Param20                 1000000          1360 ns/op         640 B/op           1 allocs/op | ||||
| BenchmarkEcho_Param20                  2104946           580 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGin_Param20                   4167204           290 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_Param20             173064          7514 ns/op        3796 B/op          15 allocs/op | ||||
| BenchmarkGoji_Param20                   458778          2651 ns/op        1247 B/op           2 allocs/op | ||||
| BenchmarkGojiv2_Param20                 364862          3178 ns/op        1632 B/op          11 allocs/op | ||||
| BenchmarkGoJsonRest_Param20             125514          9760 ns/op        4485 B/op          20 allocs/op | ||||
| BenchmarkGoRestful_Param20              101217         11964 ns/op        6715 B/op          18 allocs/op | ||||
| BenchmarkGorillaMux_Param20             147654          8132 ns/op        3452 B/op          12 allocs/op | ||||
| BenchmarkGowwwRouter_Param20           1000000          1225 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkHttpRouter_Param20            4920895           247 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_Param20            173202          6605 ns/op        3196 B/op          10 allocs/op | ||||
| BenchmarkKocha_Param20                  345988          3620 ns/op        1808 B/op          27 allocs/op | ||||
| BenchmarkLARS_Param20                  4592326           262 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_Param20                166492          7286 ns/op        2924 B/op          12 allocs/op | ||||
| BenchmarkMartini_Param20                122162         10653 ns/op        3595 B/op          13 allocs/op | ||||
| BenchmarkPat_Param20                     78630         15239 ns/op        4424 B/op          93 allocs/op | ||||
| BenchmarkPossum_Param20                1000000          1008 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkR2router_Param20               294981          4587 ns/op        2284 B/op           7 allocs/op | ||||
| BenchmarkRivet_Param20                  691798          2090 ns/op        1024 B/op           1 allocs/op | ||||
| BenchmarkTango_Param20                  842440          2505 ns/op         856 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_Param20              38614         31509 ns/op        9870 B/op         119 allocs/op | ||||
| BenchmarkTraffic_Param20                 57633         21107 ns/op        7853 B/op          47 allocs/op | ||||
| BenchmarkVulcan_Param20                1000000          1178 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_ParamWrite                7330743           180 ns/op           8 B/op           1 allocs/op | ||||
| BenchmarkAero_ParamWrite              13833598          86.7 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_ParamWrite               1363321           867 ns/op         456 B/op           5 allocs/op | ||||
| BenchmarkBeego_ParamWrite              1000000          1104 ns/op         360 B/op           4 allocs/op | ||||
| BenchmarkBone_ParamWrite               1000000          1475 ns/op         816 B/op           6 allocs/op | ||||
| BenchmarkChi_ParamWrite                1320590           892 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_ParamWrite              7093605           172 ns/op          32 B/op           1 allocs/op | ||||
| BenchmarkEcho_ParamWrite               8434424           161 ns/op           8 B/op           1 allocs/op | ||||
| BenchmarkGin_ParamWrite               10377034           118 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_ParamWrite         1000000          1266 ns/op         656 B/op           9 allocs/op | ||||
| BenchmarkGoji_ParamWrite               1874168           654 ns/op         336 B/op           2 allocs/op | ||||
| BenchmarkGojiv2_ParamWrite              459032          2352 ns/op        1360 B/op          13 allocs/op | ||||
| BenchmarkGoJsonRest_ParamWrite          499434          2145 ns/op        1128 B/op          18 allocs/op | ||||
| BenchmarkGoRestful_ParamWrite           241087          5470 ns/op        4200 B/op          15 allocs/op | ||||
| BenchmarkGorillaMux_ParamWrite          425686          2522 ns/op        1280 B/op          10 allocs/op | ||||
| BenchmarkGowwwRouter_ParamWrite         922172          1778 ns/op         976 B/op           8 allocs/op | ||||
| BenchmarkHttpRouter_ParamWrite        15392049          77.7 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_ParamWrite        1973385           597 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkKocha_ParamWrite              4262500           281 ns/op          56 B/op           3 allocs/op | ||||
| BenchmarkLARS_ParamWrite              10764410           113 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_ParamWrite             486769          2726 ns/op        1176 B/op          14 allocs/op | ||||
| BenchmarkMartini_ParamWrite             264804          4842 ns/op        1176 B/op          14 allocs/op | ||||
| BenchmarkPat_ParamWrite                 735116          2047 ns/op         960 B/op          15 allocs/op | ||||
| BenchmarkPossum_ParamWrite             1000000          1004 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkR2router_ParamWrite           1592136           768 ns/op         432 B/op           5 allocs/op | ||||
| BenchmarkRivet_ParamWrite              3582051           339 ns/op         112 B/op           2 allocs/op | ||||
| BenchmarkTango_ParamWrite              2237337           534 ns/op         136 B/op           4 allocs/op | ||||
| BenchmarkTigerTonic_ParamWrite          439608          3136 ns/op        1216 B/op          21 allocs/op | ||||
| BenchmarkTraffic_ParamWrite             306979          4328 ns/op        2280 B/op          25 allocs/op | ||||
| BenchmarkVulcan_ParamWrite             2529973           472 ns/op          98 B/op           3 allocs/op | ||||
| ``` | ||||
| 
 | ||||
| ## GitHub | ||||
| 
 | ||||
| ```sh | ||||
| BenchmarkGin_GithubStatic             15629472          76.7 ns/op           0 B/op           0 allocs/op | ||||
| 
 | ||||
| BenchmarkAce_GithubStatic             15542612          75.9 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_GithubStatic            24777151          48.5 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_GithubStatic             2788894           435 ns/op         120 B/op           3 allocs/op | ||||
| BenchmarkBeego_GithubStatic            1000000          1064 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_GithubStatic               93507         12838 ns/op        2880 B/op          60 allocs/op | ||||
| BenchmarkChi_GithubStatic              1387743           860 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_GithubStatic           39384996          30.4 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkEcho_GithubStatic            12076382          99.1 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_GithubStatic       1596495           756 ns/op         296 B/op           5 allocs/op | ||||
| BenchmarkGoji_GithubStatic             6364876           189 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGojiv2_GithubStatic            550202          2098 ns/op        1312 B/op          10 allocs/op | ||||
| BenchmarkGoRestful_GithubStatic         102183         12552 ns/op        4256 B/op          13 allocs/op | ||||
| BenchmarkGoJsonRest_GithubStatic       1000000          1029 ns/op         329 B/op          11 allocs/op | ||||
| BenchmarkGorillaMux_GithubStatic        255552          5190 ns/op         976 B/op           9 allocs/op | ||||
| BenchmarkGowwwRouter_GithubStatic     15531916          77.1 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpRouter_GithubStatic      27920724          43.1 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_GithubStatic     21448953          55.8 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkKocha_GithubStatic           21405310          56.0 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkLARS_GithubStatic            13625156          89.0 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_GithubStatic          1000000          1747 ns/op         736 B/op           8 allocs/op | ||||
| BenchmarkMartini_GithubStatic           187186          7326 ns/op         768 B/op           9 allocs/op | ||||
| BenchmarkPat_GithubStatic               109143         11563 ns/op        3648 B/op          76 allocs/op | ||||
| BenchmarkPossum_GithubStatic           1575898           770 ns/op         416 B/op           3 allocs/op | ||||
| BenchmarkR2router_GithubStatic         3046231           404 ns/op         144 B/op           4 allocs/op | ||||
| BenchmarkRivet_GithubStatic           11484826           105 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkTango_GithubStatic            1000000          1153 ns/op         248 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_GithubStatic       4929780           249 ns/op          48 B/op           1 allocs/op | ||||
| BenchmarkTraffic_GithubStatic           106351         11819 ns/op        4664 B/op          90 allocs/op | ||||
| BenchmarkVulcan_GithubStatic           1613271           722 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_GithubParam               8386032           143 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_GithubParam             11816200           102 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_GithubParam              1000000          1012 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkBeego_GithubParam             1000000          1157 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_GithubParam               184653          6912 ns/op        1888 B/op          19 allocs/op | ||||
| BenchmarkChi_GithubParam               1000000          1102 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_GithubParam             3484798           352 ns/op         128 B/op           1 allocs/op | ||||
| BenchmarkEcho_GithubParam              6337380           189 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGin_GithubParam               9132032           131 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_GithubParam        1000000          1446 ns/op         712 B/op           9 allocs/op | ||||
| BenchmarkGoji_GithubParam              1248640           977 ns/op         336 B/op           2 allocs/op | ||||
| BenchmarkGojiv2_GithubParam             383233          2784 ns/op        1408 B/op          13 allocs/op | ||||
| BenchmarkGoJsonRest_GithubParam        1000000          1991 ns/op         713 B/op          14 allocs/op | ||||
| BenchmarkGoRestful_GithubParam           76414         16015 ns/op        4352 B/op          16 allocs/op | ||||
| BenchmarkGorillaMux_GithubParam         150026          7663 ns/op        1296 B/op          10 allocs/op | ||||
| BenchmarkGowwwRouter_GithubParam       1592044           751 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkHttpRouter_GithubParam       10420628           115 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_GithubParam       1403755           835 ns/op         384 B/op           4 allocs/op | ||||
| BenchmarkKocha_GithubParam             2286170           533 ns/op         128 B/op           5 allocs/op | ||||
| BenchmarkLARS_GithubParam              9540374           129 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_GithubParam            533154          2742 ns/op        1072 B/op          10 allocs/op | ||||
| BenchmarkMartini_GithubParam            119397          9638 ns/op        1152 B/op          11 allocs/op | ||||
| BenchmarkPat_GithubParam                150675          8858 ns/op        2408 B/op          48 allocs/op | ||||
| BenchmarkPossum_GithubParam            1000000          1001 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkR2router_GithubParam          1602886           761 ns/op         432 B/op           5 allocs/op | ||||
| BenchmarkRivet_GithubParam             2986579           409 ns/op          96 B/op           1 allocs/op | ||||
| BenchmarkTango_GithubParam             1000000          1356 ns/op         344 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_GithubParam         388899          3429 ns/op        1176 B/op          22 allocs/op | ||||
| BenchmarkTraffic_GithubParam            123160          9734 ns/op        2816 B/op          40 allocs/op | ||||
| BenchmarkVulcan_GithubParam            1000000          1138 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_GithubAll                   40543         29670 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_GithubAll                  57632         20648 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_GithubAll                   9234        216179 ns/op       86448 B/op         943 allocs/op | ||||
| BenchmarkBeego_GithubAll                  7407        243496 ns/op       71456 B/op         609 allocs/op | ||||
| BenchmarkBone_GithubAll                    420       2922835 ns/op      720160 B/op        8620 allocs/op | ||||
| BenchmarkChi_GithubAll                    7620        238331 ns/op       87696 B/op         609 allocs/op | ||||
| BenchmarkDenco_GithubAll                 18355         64494 ns/op       20224 B/op         167 allocs/op | ||||
| BenchmarkEcho_GithubAll                  31251         38479 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGin_GithubAll                   43550         27364 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_GithubAll             4117        300062 ns/op      131656 B/op        1686 allocs/op | ||||
| BenchmarkGoji_GithubAll                   3274        416158 ns/op       56112 B/op         334 allocs/op | ||||
| BenchmarkGojiv2_GithubAll                 1402        870518 ns/op      352720 B/op        4321 allocs/op | ||||
| BenchmarkGoJsonRest_GithubAll             2976        401507 ns/op      134371 B/op        2737 allocs/op | ||||
| BenchmarkGoRestful_GithubAll               410       2913158 ns/op      910144 B/op        2938 allocs/op | ||||
| BenchmarkGorillaMux_GithubAll              346       3384987 ns/op      251650 B/op        1994 allocs/op | ||||
| BenchmarkGowwwRouter_GithubAll           10000        143025 ns/op       72144 B/op         501 allocs/op | ||||
| BenchmarkHttpRouter_GithubAll            55938         21360 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_GithubAll           10000        153944 ns/op       65856 B/op         671 allocs/op | ||||
| BenchmarkKocha_GithubAll                 10000        106315 ns/op       23304 B/op         843 allocs/op | ||||
| BenchmarkLARS_GithubAll                  47779         25084 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_GithubAll                3266        371907 ns/op      149409 B/op        1624 allocs/op | ||||
| BenchmarkMartini_GithubAll                 331       3444706 ns/op      226551 B/op        2325 allocs/op | ||||
| BenchmarkPat_GithubAll                     273       4381818 ns/op     1483152 B/op       26963 allocs/op | ||||
| BenchmarkPossum_GithubAll                10000        164367 ns/op       84448 B/op         609 allocs/op | ||||
| BenchmarkR2router_GithubAll              10000        160220 ns/op       77328 B/op         979 allocs/op | ||||
| BenchmarkRivet_GithubAll                 14625         82453 ns/op       16272 B/op         167 allocs/op | ||||
| BenchmarkTango_GithubAll                  6255        279611 ns/op       63826 B/op        1618 allocs/op | ||||
| BenchmarkTigerTonic_GithubAll             2008        687874 ns/op      193856 B/op        4474 allocs/op | ||||
| BenchmarkTraffic_GithubAll                 355       3478508 ns/op      820744 B/op       14114 allocs/op | ||||
| BenchmarkVulcan_GithubAll                 6885        193333 ns/op       19894 B/op         609 allocs/op | ||||
| ``` | ||||
| 
 | ||||
| ## Google+ | ||||
| 
 | ||||
| ```sh | ||||
| BenchmarkGin_GPlusStatic              19247326          62.2 ns/op           0 B/op           0 allocs/op | ||||
| 
 | ||||
| BenchmarkAce_GPlusStatic              20235060          59.2 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_GPlusStatic             31978935          37.6 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_GPlusStatic              3516523           341 ns/op         104 B/op           3 allocs/op | ||||
| BenchmarkBeego_GPlusStatic             1212036           991 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_GPlusStatic              6736242           183 ns/op          32 B/op           1 allocs/op | ||||
| BenchmarkChi_GPlusStatic               1490640           814 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_GPlusStatic            55006856          21.8 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkEcho_GPlusStatic             17688258          67.9 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_GPlusStatic        1829181           666 ns/op         280 B/op           5 allocs/op | ||||
| BenchmarkGoji_GPlusStatic              9147451           130 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGojiv2_GPlusStatic             594015          2063 ns/op        1312 B/op          10 allocs/op | ||||
| BenchmarkGoJsonRest_GPlusStatic        1264906           950 ns/op         329 B/op          11 allocs/op | ||||
| BenchmarkGoRestful_GPlusStatic          231558          5341 ns/op        3872 B/op          13 allocs/op | ||||
| BenchmarkGorillaMux_GPlusStatic         908418          1809 ns/op         976 B/op           9 allocs/op | ||||
| BenchmarkGowwwRouter_GPlusStatic      40684604          29.5 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpRouter_GPlusStatic       46742804          25.7 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_GPlusStatic      32567161          36.9 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkKocha_GPlusStatic            33800060          35.3 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkLARS_GPlusStatic             20431858          60.0 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_GPlusStatic           1000000          1745 ns/op         736 B/op           8 allocs/op | ||||
| BenchmarkMartini_GPlusStatic            442248          3619 ns/op         768 B/op           9 allocs/op | ||||
| BenchmarkPat_GPlusStatic               4328004           292 ns/op          96 B/op           2 allocs/op | ||||
| BenchmarkPossum_GPlusStatic            1570753           763 ns/op         416 B/op           3 allocs/op | ||||
| BenchmarkR2router_GPlusStatic          3339474           355 ns/op         144 B/op           4 allocs/op | ||||
| BenchmarkRivet_GPlusStatic            18570961          64.7 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkTango_GPlusStatic             1388702           860 ns/op         200 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_GPlusStatic        7803543           159 ns/op          32 B/op           1 allocs/op | ||||
| BenchmarkTraffic_GPlusStatic            878605          2171 ns/op        1112 B/op          16 allocs/op | ||||
| BenchmarkVulcan_GPlusStatic            2742446           437 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_GPlusParam               11626975           105 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_GPlusParam              16914322          71.6 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_GPlusParam               1405173           832 ns/op         480 B/op           5 allocs/op | ||||
| BenchmarkBeego_GPlusParam              1000000          1075 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_GPlusParam               1000000          1557 ns/op         816 B/op           6 allocs/op | ||||
| BenchmarkChi_GPlusParam                1347926           894 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_GPlusParam              5513000           212 ns/op          64 B/op           1 allocs/op | ||||
| BenchmarkEcho_GPlusParam              11884383           101 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGin_GPlusParam               12898952          93.1 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_GPlusParam         1000000          1194 ns/op         648 B/op           8 allocs/op | ||||
| BenchmarkGoji_GPlusParam               1857229           645 ns/op         336 B/op           2 allocs/op | ||||
| BenchmarkGojiv2_GPlusParam              520939          2322 ns/op        1328 B/op          11 allocs/op | ||||
| BenchmarkGoJsonRest_GPlusParam         1000000          1536 ns/op         649 B/op          13 allocs/op | ||||
| BenchmarkGoRestful_GPlusParam           205449          5800 ns/op        4192 B/op          14 allocs/op | ||||
| BenchmarkGorillaMux_GPlusParam          395310          3188 ns/op        1280 B/op          10 allocs/op | ||||
| BenchmarkGowwwRouter_GPlusParam        1851798           667 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkHttpRouter_GPlusParam        18420789          65.2 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_GPlusParam        1878463           629 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkKocha_GPlusParam              4495610           273 ns/op          56 B/op           3 allocs/op | ||||
| BenchmarkLARS_GPlusParam              14615976          83.2 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_GPlusParam             584145          2549 ns/op        1072 B/op          10 allocs/op | ||||
| BenchmarkMartini_GPlusParam             250501          4583 ns/op        1072 B/op          10 allocs/op | ||||
| BenchmarkPat_GPlusParam                1000000          1645 ns/op         576 B/op          11 allocs/op | ||||
| BenchmarkPossum_GPlusParam             1000000          1008 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkR2router_GPlusParam           1708191           688 ns/op         432 B/op           5 allocs/op | ||||
| BenchmarkRivet_GPlusParam              5795014           211 ns/op          48 B/op           1 allocs/op | ||||
| BenchmarkTango_GPlusParam              1000000          1091 ns/op         264 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_GPlusParam          760221          2489 ns/op         856 B/op          16 allocs/op | ||||
| BenchmarkTraffic_GPlusParam             309774          4039 ns/op        1872 B/op          21 allocs/op | ||||
| BenchmarkVulcan_GPlusParam             1935730           623 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_GPlus2Params              9158314           134 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_GPlus2Params            11300517           107 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_GPlus2Params             1239238           961 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkBeego_GPlus2Params            1000000          1202 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_GPlus2Params              335576          3725 ns/op        1168 B/op          10 allocs/op | ||||
| BenchmarkChi_GPlus2Params              1000000          1014 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_GPlus2Params            4394598           280 ns/op          64 B/op           1 allocs/op | ||||
| BenchmarkEcho_GPlus2Params             7851861           154 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGin_GPlus2Params              9958588           120 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_GPlus2Params       1000000          1433 ns/op         712 B/op           9 allocs/op | ||||
| BenchmarkGoji_GPlus2Params             1325134           909 ns/op         336 B/op           2 allocs/op | ||||
| BenchmarkGojiv2_GPlus2Params            405955          2870 ns/op        1408 B/op          14 allocs/op | ||||
| BenchmarkGoJsonRest_GPlus2Params        977038          1987 ns/op         713 B/op          14 allocs/op | ||||
| BenchmarkGoRestful_GPlus2Params         205018          6142 ns/op        4384 B/op          16 allocs/op | ||||
| BenchmarkGorillaMux_GPlus2Params        205641          6015 ns/op        1296 B/op          10 allocs/op | ||||
| BenchmarkGowwwRouter_GPlus2Params      1748542           684 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkHttpRouter_GPlus2Params      14047102          87.7 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_GPlus2Params      1418673           828 ns/op         384 B/op           4 allocs/op | ||||
| BenchmarkKocha_GPlus2Params            2334562           520 ns/op         128 B/op           5 allocs/op | ||||
| BenchmarkLARS_GPlus2Params            11954094           101 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_GPlus2Params           491552          2890 ns/op        1072 B/op          10 allocs/op | ||||
| BenchmarkMartini_GPlus2Params           120532          9545 ns/op        1200 B/op          13 allocs/op | ||||
| BenchmarkPat_GPlus2Params               194739          6766 ns/op        2168 B/op          33 allocs/op | ||||
| BenchmarkPossum_GPlus2Params           1201224          1009 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkR2router_GPlus2Params         1575535           756 ns/op         432 B/op           5 allocs/op | ||||
| BenchmarkRivet_GPlus2Params            3698930           325 ns/op          96 B/op           1 allocs/op | ||||
| BenchmarkTango_GPlus2Params            1000000          1212 ns/op         344 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_GPlus2Params        349350          3660 ns/op        1200 B/op          22 allocs/op | ||||
| BenchmarkTraffic_GPlus2Params           169714          7862 ns/op        2248 B/op          28 allocs/op | ||||
| BenchmarkVulcan_GPlus2Params           1222288           974 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_GPlusAll                   845606          1398 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_GPlusAll                 1000000          1009 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_GPlusAll                  103830         11386 ns/op        5488 B/op          61 allocs/op | ||||
| BenchmarkBeego_GPlusAll                  82653         14784 ns/op        4576 B/op          39 allocs/op | ||||
| BenchmarkBone_GPlusAll                   36601         33123 ns/op       11744 B/op         109 allocs/op | ||||
| BenchmarkChi_GPlusAll                    95264         12831 ns/op        5616 B/op          39 allocs/op | ||||
| BenchmarkDenco_GPlusAll                 567681          2950 ns/op         672 B/op          11 allocs/op | ||||
| BenchmarkEcho_GPlusAll                  720366          1665 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGin_GPlusAll                  1000000          1185 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_GPlusAll             71575         16365 ns/op        8040 B/op         103 allocs/op | ||||
| BenchmarkGoji_GPlusAll                  136352          9191 ns/op        3696 B/op          22 allocs/op | ||||
| BenchmarkGojiv2_GPlusAll                 38006         31802 ns/op       17616 B/op         154 allocs/op | ||||
| BenchmarkGoJsonRest_GPlusAll             57238         21561 ns/op        8117 B/op         170 allocs/op | ||||
| BenchmarkGoRestful_GPlusAll              15147         79276 ns/op       55520 B/op         192 allocs/op | ||||
| BenchmarkGorillaMux_GPlusAll             24446         48410 ns/op       16112 B/op         128 allocs/op | ||||
| BenchmarkGowwwRouter_GPlusAll           150112          7770 ns/op        4752 B/op          33 allocs/op | ||||
| BenchmarkHttpRouter_GPlusAll           1367820           878 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_GPlusAll           166628          8004 ns/op        4032 B/op          38 allocs/op | ||||
| BenchmarkKocha_GPlusAll                 265694          4570 ns/op         976 B/op          43 allocs/op | ||||
| BenchmarkLARS_GPlusAll                 1000000          1068 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_GPlusAll                54564         23305 ns/op        9568 B/op         104 allocs/op | ||||
| BenchmarkMartini_GPlusAll                16274         73845 ns/op       14016 B/op         145 allocs/op | ||||
| BenchmarkPat_GPlusAll                    27181         44478 ns/op       15264 B/op         271 allocs/op | ||||
| BenchmarkPossum_GPlusAll                122587         10277 ns/op        5408 B/op          39 allocs/op | ||||
| BenchmarkR2router_GPlusAll              130137          9297 ns/op        5040 B/op          63 allocs/op | ||||
| BenchmarkRivet_GPlusAll                 532438          3323 ns/op         768 B/op          11 allocs/op | ||||
| BenchmarkTango_GPlusAll                  86054         14531 ns/op        3656 B/op         104 allocs/op | ||||
| BenchmarkTigerTonic_GPlusAll             33936         35356 ns/op       11600 B/op         242 allocs/op | ||||
| BenchmarkTraffic_GPlusAll                17833         68181 ns/op       26248 B/op         341 allocs/op | ||||
| BenchmarkVulcan_GPlusAll                120109          9861 ns/op        1274 B/op          39 allocs/op | ||||
| ``` | ||||
| 
 | ||||
| ## Parse.com | ||||
| 
 | ||||
| ```sh | ||||
| BenchmarkGin_ParseStatic              18877833          63.5 ns/op           0 B/op           0 allocs/op | ||||
| 
 | ||||
| BenchmarkAce_ParseStatic              19663731          60.8 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_ParseStatic             28967341          41.5 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_ParseStatic              3006984           402 ns/op         120 B/op           3 allocs/op | ||||
| BenchmarkBeego_ParseStatic             1000000          1031 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_ParseStatic              1782482           675 ns/op         144 B/op           3 allocs/op | ||||
| BenchmarkChi_ParseStatic               1453261           819 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_ParseStatic            45023595          26.5 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkEcho_ParseStatic             17330470          69.3 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_ParseStatic        1644006           731 ns/op         296 B/op           5 allocs/op | ||||
| BenchmarkGoji_ParseStatic              7026930           170 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGojiv2_ParseStatic             517618          2037 ns/op        1312 B/op          10 allocs/op | ||||
| BenchmarkGoJsonRest_ParseStatic        1227080           975 ns/op         329 B/op          11 allocs/op | ||||
| BenchmarkGoRestful_ParseStatic          192458          6659 ns/op        4256 B/op          13 allocs/op | ||||
| BenchmarkGorillaMux_ParseStatic         744062          2109 ns/op         976 B/op           9 allocs/op | ||||
| BenchmarkGowwwRouter_ParseStatic      37781062          31.8 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpRouter_ParseStatic       45311223          26.5 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_ParseStatic      21383475          56.1 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkKocha_ParseStatic            29953290          40.1 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkLARS_ParseStatic             20036196          62.7 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_ParseStatic           1000000          1740 ns/op         736 B/op           8 allocs/op | ||||
| BenchmarkMartini_ParseStatic            404156          3801 ns/op         768 B/op           9 allocs/op | ||||
| BenchmarkPat_ParseStatic               1547180           772 ns/op         240 B/op           5 allocs/op | ||||
| BenchmarkPossum_ParseStatic            1608991           757 ns/op         416 B/op           3 allocs/op | ||||
| BenchmarkR2router_ParseStatic          3177936           385 ns/op         144 B/op           4 allocs/op | ||||
| BenchmarkRivet_ParseStatic            17783205          67.4 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkTango_ParseStatic             1210777           990 ns/op         248 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_ParseStatic        5316440           231 ns/op          48 B/op           1 allocs/op | ||||
| BenchmarkTraffic_ParseStatic            496050          2539 ns/op        1256 B/op          19 allocs/op | ||||
| BenchmarkVulcan_ParseStatic            2462798           488 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_ParseParam               13393669          89.6 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_ParseParam              19836619          60.4 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_ParseParam               1405954           864 ns/op         467 B/op           5 allocs/op | ||||
| BenchmarkBeego_ParseParam              1000000          1065 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_ParseParam               1000000          1698 ns/op         896 B/op           7 allocs/op | ||||
| BenchmarkChi_ParseParam                1356037           873 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_ParseParam              6241392           204 ns/op          64 B/op           1 allocs/op | ||||
| BenchmarkEcho_ParseParam              14088100          85.1 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGin_ParseParam               17426064          68.9 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_ParseParam         1000000          1254 ns/op         664 B/op           8 allocs/op | ||||
| BenchmarkGoji_ParseParam               1682574           713 ns/op         336 B/op           2 allocs/op | ||||
| BenchmarkGojiv2_ParseParam              502224          2333 ns/op        1360 B/op          12 allocs/op | ||||
| BenchmarkGoJsonRest_ParseParam         1000000          1401 ns/op         649 B/op          13 allocs/op | ||||
| BenchmarkGoRestful_ParseParam           182623          7097 ns/op        4576 B/op          14 allocs/op | ||||
| BenchmarkGorillaMux_ParseParam          482332          2477 ns/op        1280 B/op          10 allocs/op | ||||
| BenchmarkGowwwRouter_ParseParam        1834873           657 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkHttpRouter_ParseParam        23593393          51.0 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_ParseParam        2100160           574 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkKocha_ParseParam              4837220           252 ns/op          56 B/op           3 allocs/op | ||||
| BenchmarkLARS_ParseParam              18411192          66.2 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_ParseParam             571870          2398 ns/op        1072 B/op          10 allocs/op | ||||
| BenchmarkMartini_ParseParam             286262          4268 ns/op        1072 B/op          10 allocs/op | ||||
| BenchmarkPat_ParseParam                 692906          2157 ns/op         992 B/op          15 allocs/op | ||||
| BenchmarkPossum_ParseParam             1000000          1011 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkR2router_ParseParam           1722735           697 ns/op         432 B/op           5 allocs/op | ||||
| BenchmarkRivet_ParseParam              6058054           203 ns/op          48 B/op           1 allocs/op | ||||
| BenchmarkTango_ParseParam              1000000          1061 ns/op         280 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_ParseParam          890275          2277 ns/op         784 B/op          15 allocs/op | ||||
| BenchmarkTraffic_ParseParam             351322          3543 ns/op        1896 B/op          21 allocs/op | ||||
| BenchmarkVulcan_ParseParam             2076544           572 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_Parse2Params             11718074           101 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_Parse2Params            16264988          73.4 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_Parse2Params             1238322           973 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkBeego_Parse2Params            1000000          1120 ns/op         352 B/op           3 allocs/op | ||||
| BenchmarkBone_Parse2Params             1000000          1632 ns/op         848 B/op           6 allocs/op | ||||
| BenchmarkChi_Parse2Params              1239477           955 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkDenco_Parse2Params            4944133           245 ns/op          64 B/op           1 allocs/op | ||||
| BenchmarkEcho_Parse2Params            10518286           114 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGin_Parse2Params             14505195          82.7 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_Parse2Params       1000000          1437 ns/op         712 B/op           9 allocs/op | ||||
| BenchmarkGoji_Parse2Params             1689883           707 ns/op         336 B/op           2 allocs/op | ||||
| BenchmarkGojiv2_Parse2Params            502334          2308 ns/op        1344 B/op          11 allocs/op | ||||
| BenchmarkGoJsonRest_Parse2Params       1000000          1771 ns/op         713 B/op          14 allocs/op | ||||
| BenchmarkGoRestful_Parse2Params         159092          7583 ns/op        4928 B/op          14 allocs/op | ||||
| BenchmarkGorillaMux_Parse2Params        417548          2980 ns/op        1296 B/op          10 allocs/op | ||||
| BenchmarkGowwwRouter_Parse2Params      1751737           686 ns/op         432 B/op           3 allocs/op | ||||
| BenchmarkHttpRouter_Parse2Params      18089204          66.3 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_Parse2Params      1556986           777 ns/op         384 B/op           4 allocs/op | ||||
| BenchmarkKocha_Parse2Params            2493082           485 ns/op         128 B/op           5 allocs/op | ||||
| BenchmarkLARS_Parse2Params            15350108          78.5 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_Parse2Params           530974          2605 ns/op        1072 B/op          10 allocs/op | ||||
| BenchmarkMartini_Parse2Params           247069          4673 ns/op        1152 B/op          11 allocs/op | ||||
| BenchmarkPat_Parse2Params               816295          2126 ns/op         752 B/op          16 allocs/op | ||||
| BenchmarkPossum_Parse2Params           1000000          1002 ns/op         496 B/op           5 allocs/op | ||||
| BenchmarkR2router_Parse2Params         1569771           733 ns/op         432 B/op           5 allocs/op | ||||
| BenchmarkRivet_Parse2Params            4080546           295 ns/op          96 B/op           1 allocs/op | ||||
| BenchmarkTango_Parse2Params            1000000          1121 ns/op         312 B/op           8 allocs/op | ||||
| BenchmarkTigerTonic_Parse2Params        399556          3470 ns/op        1168 B/op          22 allocs/op | ||||
| BenchmarkTraffic_Parse2Params           314194          4159 ns/op        1944 B/op          22 allocs/op | ||||
| BenchmarkVulcan_Parse2Params           1827559           664 ns/op          98 B/op           3 allocs/op | ||||
| BenchmarkAce_ParseAll                   478395          2503 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkAero_ParseAll                  715392          1658 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkBear_ParseAll                   59191         20124 ns/op        8928 B/op         110 allocs/op | ||||
| BenchmarkBeego_ParseAll                  45507         27266 ns/op        9152 B/op          78 allocs/op | ||||
| BenchmarkBone_ParseAll                   29328         41459 ns/op       16208 B/op         147 allocs/op | ||||
| BenchmarkChi_ParseAll                    48531         25053 ns/op       11232 B/op          78 allocs/op | ||||
| BenchmarkDenco_ParseAll                 325532          4284 ns/op         928 B/op          16 allocs/op | ||||
| BenchmarkEcho_ParseAll                  433771          2759 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGin_ParseAll                   576316          2082 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkGocraftWeb_ParseAll             41500         29692 ns/op       13728 B/op         181 allocs/op | ||||
| BenchmarkGoji_ParseAll                   80833         15563 ns/op        5376 B/op          32 allocs/op | ||||
| BenchmarkGojiv2_ParseAll                 19836         60335 ns/op       34448 B/op         277 allocs/op | ||||
| BenchmarkGoJsonRest_ParseAll             32210         38027 ns/op       13866 B/op         321 allocs/op | ||||
| BenchmarkGoRestful_ParseAll               6644        190842 ns/op      117600 B/op         354 allocs/op | ||||
| BenchmarkGorillaMux_ParseAll             12634         95894 ns/op       30288 B/op         250 allocs/op | ||||
| BenchmarkGowwwRouter_ParseAll            98152         12159 ns/op        6912 B/op          48 allocs/op | ||||
| BenchmarkHttpRouter_ParseAll            933208          1273 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkHttpTreeMux_ParseAll           107191         11554 ns/op        5728 B/op          51 allocs/op | ||||
| BenchmarkKocha_ParseAll                 184862          6225 ns/op        1112 B/op          54 allocs/op | ||||
| BenchmarkLARS_ParseAll                  644546          1858 ns/op           0 B/op           0 allocs/op | ||||
| BenchmarkMacaron_ParseAll                26145         46484 ns/op       19136 B/op         208 allocs/op | ||||
| BenchmarkMartini_ParseAll                10000        121838 ns/op       25072 B/op         253 allocs/op | ||||
| BenchmarkPat_ParseAll                    25417         47196 ns/op       15216 B/op         308 allocs/op | ||||
| BenchmarkPossum_ParseAll                 58550         20735 ns/op       10816 B/op          78 allocs/op | ||||
| BenchmarkR2router_ParseAll               72732         16584 ns/op        8352 B/op         120 allocs/op | ||||
| BenchmarkRivet_ParseAll                 281365          4968 ns/op         912 B/op          16 allocs/op | ||||
| BenchmarkTango_ParseAll                  42831         28668 ns/op        7168 B/op         208 allocs/op | ||||
| BenchmarkTigerTonic_ParseAll             23774         49972 ns/op       16048 B/op         332 allocs/op | ||||
| BenchmarkTraffic_ParseAll                10000        104679 ns/op       45520 B/op         605 allocs/op | ||||
| BenchmarkVulcan_ParseAll                 64810         18108 ns/op        2548 B/op          78 allocs/op | ||||
| ``` | ||||
							
								
								
									
										418
									
								
								vendor/github.com/gin-gonic/gin/CHANGELOG.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										418
									
								
								vendor/github.com/gin-gonic/gin/CHANGELOG.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,418 @@ | |||
| # Gin ChangeLog | ||||
| 
 | ||||
| ## Gin v1.7.2 | ||||
| 
 | ||||
| ### BUGFIXES | ||||
| 
 | ||||
| * Fix conflict between param and exact path [#2706](https://github.com/gin-gonic/gin/issues/2706). Close issue [#2682](https://github.com/gin-gonic/gin/issues/2682) [#2696](https://github.com/gin-gonic/gin/issues/2696). | ||||
| 
 | ||||
| ## Gin v1.7.1 | ||||
| 
 | ||||
| ### BUGFIXES | ||||
| 
 | ||||
| * fix: data race with trustedCIDRs from [#2674](https://github.com/gin-gonic/gin/issues/2674)([#2675](https://github.com/gin-gonic/gin/pull/2675)) | ||||
| 
 | ||||
| ## Gin v1.7.0 | ||||
| 
 | ||||
| ### BUGFIXES | ||||
| 
 | ||||
| * fix compile error from [#2572](https://github.com/gin-gonic/gin/pull/2572) ([#2600](https://github.com/gin-gonic/gin/pull/2600)) | ||||
| * fix: print headers without Authorization header on broken pipe ([#2528](https://github.com/gin-gonic/gin/pull/2528)) | ||||
| * fix(tree): reassign fullpath when register new node ([#2366](https://github.com/gin-gonic/gin/pull/2366)) | ||||
| 
 | ||||
| ### ENHANCEMENTS | ||||
| 
 | ||||
| * Support params and exact routes without creating conflicts ([#2663](https://github.com/gin-gonic/gin/pull/2663)) | ||||
| * chore: improve render string performance ([#2365](https://github.com/gin-gonic/gin/pull/2365)) | ||||
| * Sync route tree to httprouter latest code ([#2368](https://github.com/gin-gonic/gin/pull/2368)) | ||||
| * chore: rename getQueryCache/getFormCache to initQueryCache/initFormCa ([#2375](https://github.com/gin-gonic/gin/pull/2375)) | ||||
| * chore(performance): improve countParams ([#2378](https://github.com/gin-gonic/gin/pull/2378)) | ||||
| * Remove some functions that have the same effect as the bytes package ([#2387](https://github.com/gin-gonic/gin/pull/2387)) | ||||
| * update:SetMode function ([#2321](https://github.com/gin-gonic/gin/pull/2321)) | ||||
| * remove a unused type SecureJSONPrefix ([#2391](https://github.com/gin-gonic/gin/pull/2391)) | ||||
| * Add a redirect sample for POST method ([#2389](https://github.com/gin-gonic/gin/pull/2389)) | ||||
| * Add CustomRecovery builtin middleware ([#2322](https://github.com/gin-gonic/gin/pull/2322)) | ||||
| * binding: avoid 2038 problem on 32-bit architectures ([#2450](https://github.com/gin-gonic/gin/pull/2450)) | ||||
| * Prevent panic in Context.GetQuery() when there is no Request ([#2412](https://github.com/gin-gonic/gin/pull/2412)) | ||||
| * Add GetUint and GetUint64 method on gin.context ([#2487](https://github.com/gin-gonic/gin/pull/2487)) | ||||
| * update content-disposition header to MIME-style ([#2512](https://github.com/gin-gonic/gin/pull/2512)) | ||||
| * reduce allocs and improve the render `WriteString` ([#2508](https://github.com/gin-gonic/gin/pull/2508)) | ||||
| * implement ".Unwrap() error" on Error type ([#2525](https://github.com/gin-gonic/gin/pull/2525)) ([#2526](https://github.com/gin-gonic/gin/pull/2526)) | ||||
| * Allow bind with a map[string]string ([#2484](https://github.com/gin-gonic/gin/pull/2484)) | ||||
| * chore: update tree ([#2371](https://github.com/gin-gonic/gin/pull/2371)) | ||||
| * Support binding for slice/array obj [Rewrite] ([#2302](https://github.com/gin-gonic/gin/pull/2302)) | ||||
| * basic auth: fix timing oracle ([#2609](https://github.com/gin-gonic/gin/pull/2609)) | ||||
| * Add mixed param and non-param paths (port of httprouter[#329](https://github.com/gin-gonic/gin/pull/329)) ([#2663](https://github.com/gin-gonic/gin/pull/2663)) | ||||
| * feat(engine): add trustedproxies and remoteIP ([#2632](https://github.com/gin-gonic/gin/pull/2632)) | ||||
| 
 | ||||
| ## Gin v1.6.3 | ||||
| 
 | ||||
| ### ENHANCEMENTS | ||||
| 
 | ||||
|   * Improve performance: Change `*sync.RWMutex` to `sync.RWMutex` in context. [#2351](https://github.com/gin-gonic/gin/pull/2351) | ||||
| 
 | ||||
| ## Gin v1.6.2 | ||||
| 
 | ||||
| ### BUGFIXES | ||||
|   * fix missing initial sync.RWMutex [#2305](https://github.com/gin-gonic/gin/pull/2305) | ||||
| ### ENHANCEMENTS | ||||
|   * Add set samesite in cookie. [#2306](https://github.com/gin-gonic/gin/pull/2306) | ||||
| 
 | ||||
| ## Gin v1.6.1 | ||||
| 
 | ||||
| ### BUGFIXES | ||||
|   * Revert "fix accept incoming network connections" [#2294](https://github.com/gin-gonic/gin/pull/2294) | ||||
| 
 | ||||
| ## Gin v1.6.0 | ||||
| 
 | ||||
| ### BREAKING | ||||
|   * chore(performance): Improve performance for adding RemoveExtraSlash flag [#2159](https://github.com/gin-gonic/gin/pull/2159) | ||||
|   * drop support govendor [#2148](https://github.com/gin-gonic/gin/pull/2148) | ||||
|   * Added support for SameSite cookie flag [#1615](https://github.com/gin-gonic/gin/pull/1615) | ||||
| ### FEATURES | ||||
|   * add yaml negotiation [#2220](https://github.com/gin-gonic/gin/pull/2220) | ||||
|   * FileFromFS [#2112](https://github.com/gin-gonic/gin/pull/2112) | ||||
| ### BUGFIXES | ||||
|   * Unix Socket Handling [#2280](https://github.com/gin-gonic/gin/pull/2280) | ||||
|   * Use json marshall in context json to fix breaking new line issue. Fixes #2209 [#2228](https://github.com/gin-gonic/gin/pull/2228) | ||||
|   * fix accept incoming network connections [#2216](https://github.com/gin-gonic/gin/pull/2216) | ||||
|   * Fixed a bug in the calculation of the maximum number of parameters [#2166](https://github.com/gin-gonic/gin/pull/2166) | ||||
|   * [FIX] allow empty headers on DataFromReader [#2121](https://github.com/gin-gonic/gin/pull/2121) | ||||
|   * Add mutex for protect Context.Keys map [#1391](https://github.com/gin-gonic/gin/pull/1391) | ||||
| ### ENHANCEMENTS | ||||
|   * Add mitigation for log injection [#2277](https://github.com/gin-gonic/gin/pull/2277) | ||||
|   * tree: range over nodes values [#2229](https://github.com/gin-gonic/gin/pull/2229) | ||||
|   * tree: remove duplicate assignment [#2222](https://github.com/gin-gonic/gin/pull/2222) | ||||
|   * chore: upgrade go-isatty and json-iterator/go [#2215](https://github.com/gin-gonic/gin/pull/2215) | ||||
|   * path: sync code with httprouter [#2212](https://github.com/gin-gonic/gin/pull/2212) | ||||
|   * Use zero-copy approach to convert types between string and byte slice [#2206](https://github.com/gin-gonic/gin/pull/2206) | ||||
|   * Reuse bytes when cleaning the URL paths [#2179](https://github.com/gin-gonic/gin/pull/2179) | ||||
|   * tree: remove one else statement [#2177](https://github.com/gin-gonic/gin/pull/2177) | ||||
|   * tree: sync httprouter update (#2173) (#2172) [#2171](https://github.com/gin-gonic/gin/pull/2171) | ||||
|   * tree: sync part httprouter codes and reduce if/else [#2163](https://github.com/gin-gonic/gin/pull/2163) | ||||
|   * use http method constant [#2155](https://github.com/gin-gonic/gin/pull/2155) | ||||
|   * upgrade go-validator to v10 [#2149](https://github.com/gin-gonic/gin/pull/2149) | ||||
|   * Refactor redirect request in gin.go [#1970](https://github.com/gin-gonic/gin/pull/1970) | ||||
|   * Add build tag nomsgpack [#1852](https://github.com/gin-gonic/gin/pull/1852) | ||||
| ### DOCS | ||||
|   * docs(path): improve comments [#2223](https://github.com/gin-gonic/gin/pull/2223) | ||||
|   * Renew README to fit the modification of SetCookie method [#2217](https://github.com/gin-gonic/gin/pull/2217) | ||||
|   * Fix spelling [#2202](https://github.com/gin-gonic/gin/pull/2202) | ||||
|   * Remove broken link from README. [#2198](https://github.com/gin-gonic/gin/pull/2198) | ||||
|   * Update docs on Context.Done(), Context.Deadline() and Context.Err() [#2196](https://github.com/gin-gonic/gin/pull/2196) | ||||
|   * Update validator to v10 [#2190](https://github.com/gin-gonic/gin/pull/2190) | ||||
|   * upgrade go-validator to v10 for README [#2189](https://github.com/gin-gonic/gin/pull/2189) | ||||
|   * Update to currently output [#2188](https://github.com/gin-gonic/gin/pull/2188) | ||||
|   * Fix "Custom Validators" example [#2186](https://github.com/gin-gonic/gin/pull/2186) | ||||
|   * Add project to README [#2165](https://github.com/gin-gonic/gin/pull/2165) | ||||
|   * docs(benchmarks): for gin v1.5 [#2153](https://github.com/gin-gonic/gin/pull/2153) | ||||
|   * Changed wording for clarity in README.md [#2122](https://github.com/gin-gonic/gin/pull/2122) | ||||
| ### MISC | ||||
|   * ci support go1.14 [#2262](https://github.com/gin-gonic/gin/pull/2262) | ||||
|   * chore: upgrade depend version [#2231](https://github.com/gin-gonic/gin/pull/2231) | ||||
|   * Drop support go1.10 [#2147](https://github.com/gin-gonic/gin/pull/2147) | ||||
|   * fix comment in `mode.go` [#2129](https://github.com/gin-gonic/gin/pull/2129) | ||||
| 
 | ||||
| ## Gin v1.5.0 | ||||
| 
 | ||||
| - [FIX] Use DefaultWriter and DefaultErrorWriter for debug messages [#1891](https://github.com/gin-gonic/gin/pull/1891) | ||||
| - [NEW] Now you can parse the inline lowercase start structure [#1893](https://github.com/gin-gonic/gin/pull/1893) | ||||
| - [FIX] Some code improvements [#1909](https://github.com/gin-gonic/gin/pull/1909) | ||||
| - [FIX] Use encode replace json marshal increase json encoder speed [#1546](https://github.com/gin-gonic/gin/pull/1546) | ||||
| - [NEW] Hold matched route full path in the Context [#1826](https://github.com/gin-gonic/gin/pull/1826) | ||||
| - [FIX] Fix context.Params race condition on Copy() [#1841](https://github.com/gin-gonic/gin/pull/1841) | ||||
| - [NEW] Add context param query cache [#1450](https://github.com/gin-gonic/gin/pull/1450) | ||||
| - [FIX] Improve GetQueryMap performance [#1918](https://github.com/gin-gonic/gin/pull/1918) | ||||
| - [FIX] Improve get post data [#1920](https://github.com/gin-gonic/gin/pull/1920) | ||||
| - [FIX] Use context instead of x/net/context [#1922](https://github.com/gin-gonic/gin/pull/1922) | ||||
| - [FIX] Attempt to fix PostForm cache bug [#1931](https://github.com/gin-gonic/gin/pull/1931) | ||||
| - [NEW] Add support of multipart multi files [#1949](https://github.com/gin-gonic/gin/pull/1949) | ||||
| - [NEW] Support bind http header param [#1957](https://github.com/gin-gonic/gin/pull/1957) | ||||
| - [FIX] Drop support for go1.8 and go1.9 [#1933](https://github.com/gin-gonic/gin/pull/1933) | ||||
| - [FIX] Bugfix for the FullPath feature [#1919](https://github.com/gin-gonic/gin/pull/1919) | ||||
| - [FIX] Gin1.5 bytes.Buffer to strings.Builder [#1939](https://github.com/gin-gonic/gin/pull/1939) | ||||
| - [FIX] Upgrade github.com/ugorji/go/codec [#1969](https://github.com/gin-gonic/gin/pull/1969) | ||||
| - [NEW] Support bind unix time [#1980](https://github.com/gin-gonic/gin/pull/1980) | ||||
| - [FIX] Simplify code [#2004](https://github.com/gin-gonic/gin/pull/2004) | ||||
| - [NEW] Support negative Content-Length in DataFromReader [#1981](https://github.com/gin-gonic/gin/pull/1981) | ||||
| - [FIX] Identify terminal on a RISC-V architecture for auto-colored logs [#2019](https://github.com/gin-gonic/gin/pull/2019) | ||||
| - [BREAKING] `Context.JSONP()` now expects a semicolon (`;`) at the end [#2007](https://github.com/gin-gonic/gin/pull/2007) | ||||
| - [BREAKING] Upgrade default `binding.Validator` to v9 (see [its changelog](https://github.com/go-playground/validator/releases/tag/v9.0.0)) [#1015](https://github.com/gin-gonic/gin/pull/1015) | ||||
| - [NEW] Add `DisallowUnknownFields()` in `Context.BindJSON()` [#2028](https://github.com/gin-gonic/gin/pull/2028) | ||||
| - [NEW] Use specific `net.Listener` with `Engine.RunListener()` [#2023](https://github.com/gin-gonic/gin/pull/2023) | ||||
| - [FIX] Fix some typo [#2079](https://github.com/gin-gonic/gin/pull/2079) [#2080](https://github.com/gin-gonic/gin/pull/2080) | ||||
| - [FIX] Relocate binding body tests [#2086](https://github.com/gin-gonic/gin/pull/2086) | ||||
| - [FIX] Use Writer in Context.Status [#1606](https://github.com/gin-gonic/gin/pull/1606) | ||||
| - [FIX] `Engine.RunUnix()` now returns the error if it can't change the file mode [#2093](https://github.com/gin-gonic/gin/pull/2093) | ||||
| - [FIX] `RouterGroup.StaticFS()` leaked files. Now it closes them. [#2118](https://github.com/gin-gonic/gin/pull/2118) | ||||
| - [FIX] `Context.Request.FormFile` leaked file. Now it closes it. [#2114](https://github.com/gin-gonic/gin/pull/2114) | ||||
| - [FIX] Ignore walking on `form:"-"` mapping [#1943](https://github.com/gin-gonic/gin/pull/1943) | ||||
| 
 | ||||
| ### Gin v1.4.0 | ||||
| 
 | ||||
| - [NEW] Support for [Go Modules](https://github.com/golang/go/wiki/Modules)  [#1569](https://github.com/gin-gonic/gin/pull/1569) | ||||
| - [NEW] Refactor of form mapping multipart request [#1829](https://github.com/gin-gonic/gin/pull/1829) | ||||
| - [FIX] Truncate Latency precision in long running request [#1830](https://github.com/gin-gonic/gin/pull/1830) | ||||
| - [FIX] IsTerm flag should not be affected by DisableConsoleColor method. [#1802](https://github.com/gin-gonic/gin/pull/1802) | ||||
| - [NEW] Supporting file binding [#1264](https://github.com/gin-gonic/gin/pull/1264) | ||||
| - [NEW] Add support for mapping arrays [#1797](https://github.com/gin-gonic/gin/pull/1797) | ||||
| - [FIX] Readme updates [#1793](https://github.com/gin-gonic/gin/pull/1793) [#1788](https://github.com/gin-gonic/gin/pull/1788) [1789](https://github.com/gin-gonic/gin/pull/1789) | ||||
| - [FIX] StaticFS: Fixed Logging two log lines on 404.  [#1805](https://github.com/gin-gonic/gin/pull/1805), [#1804](https://github.com/gin-gonic/gin/pull/1804) | ||||
| - [NEW] Make context.Keys available as LogFormatterParams [#1779](https://github.com/gin-gonic/gin/pull/1779) | ||||
| - [NEW] Use internal/json for Marshal/Unmarshal [#1791](https://github.com/gin-gonic/gin/pull/1791) | ||||
| - [NEW] Support mapping time.Duration [#1794](https://github.com/gin-gonic/gin/pull/1794) | ||||
| - [NEW] Refactor form mappings [#1749](https://github.com/gin-gonic/gin/pull/1749) | ||||
| - [NEW] Added flag to context.Stream indicates if client disconnected in middle of stream [#1252](https://github.com/gin-gonic/gin/pull/1252) | ||||
| - [FIX] Moved [examples](https://github.com/gin-gonic/examples) to stand alone Repo [#1775](https://github.com/gin-gonic/gin/pull/1775) | ||||
| - [NEW] Extend context.File to allow for the content-disposition attachments via a new method context.Attachment [#1260](https://github.com/gin-gonic/gin/pull/1260) | ||||
| - [FIX] Support HTTP content negotiation wildcards [#1112](https://github.com/gin-gonic/gin/pull/1112) | ||||
| - [NEW] Add prefix from X-Forwarded-Prefix in redirectTrailingSlash [#1238](https://github.com/gin-gonic/gin/pull/1238) | ||||
| - [FIX] context.Copy() race condition [#1020](https://github.com/gin-gonic/gin/pull/1020) | ||||
| - [NEW] Add context.HandlerNames() [#1729](https://github.com/gin-gonic/gin/pull/1729) | ||||
| - [FIX] Change color methods to public in the defaultLogger. [#1771](https://github.com/gin-gonic/gin/pull/1771) | ||||
| - [FIX] Update writeHeaders method to use http.Header.Set [#1722](https://github.com/gin-gonic/gin/pull/1722) | ||||
| - [NEW] Add response size to LogFormatterParams [#1752](https://github.com/gin-gonic/gin/pull/1752) | ||||
| - [NEW] Allow ignoring field on form mapping [#1733](https://github.com/gin-gonic/gin/pull/1733) | ||||
| - [NEW] Add a function to force color in console output. [#1724](https://github.com/gin-gonic/gin/pull/1724) | ||||
| - [FIX] Context.Next() - recheck len of handlers on every iteration. [#1745](https://github.com/gin-gonic/gin/pull/1745) | ||||
| - [FIX] Fix all errcheck warnings [#1739](https://github.com/gin-gonic/gin/pull/1739) [#1653](https://github.com/gin-gonic/gin/pull/1653) | ||||
| - [NEW] context: inherits context cancellation and deadline from http.Request context for Go>=1.7 [#1690](https://github.com/gin-gonic/gin/pull/1690) | ||||
| - [NEW] Binding for URL Params [#1694](https://github.com/gin-gonic/gin/pull/1694) | ||||
| - [NEW] Add LoggerWithFormatter method [#1677](https://github.com/gin-gonic/gin/pull/1677) | ||||
| - [FIX] CI testing updates [#1671](https://github.com/gin-gonic/gin/pull/1671) [#1670](https://github.com/gin-gonic/gin/pull/1670) [#1682](https://github.com/gin-gonic/gin/pull/1682) [#1669](https://github.com/gin-gonic/gin/pull/1669) | ||||
| - [FIX] StaticFS(): Send 404 when path does not exist [#1663](https://github.com/gin-gonic/gin/pull/1663) | ||||
| - [FIX] Handle nil body for JSON binding [#1638](https://github.com/gin-gonic/gin/pull/1638) | ||||
| - [FIX] Support bind uri param [#1612](https://github.com/gin-gonic/gin/pull/1612) | ||||
| - [FIX] recovery: fix issue with syscall import on google app engine [#1640](https://github.com/gin-gonic/gin/pull/1640) | ||||
| - [FIX] Make sure the debug log contains line breaks [#1650](https://github.com/gin-gonic/gin/pull/1650) | ||||
| - [FIX] Panic stack trace being printed during recovery of broken pipe [#1089](https://github.com/gin-gonic/gin/pull/1089) [#1259](https://github.com/gin-gonic/gin/pull/1259) | ||||
| - [NEW] RunFd method to run http.Server through a file descriptor [#1609](https://github.com/gin-gonic/gin/pull/1609) | ||||
| - [NEW] Yaml binding support [#1618](https://github.com/gin-gonic/gin/pull/1618) | ||||
| - [FIX] Pass MaxMultipartMemory when FormFile is called [#1600](https://github.com/gin-gonic/gin/pull/1600) | ||||
| - [FIX] LoadHTML* tests [#1559](https://github.com/gin-gonic/gin/pull/1559) | ||||
| - [FIX] Removed use of sync.pool from HandleContext [#1565](https://github.com/gin-gonic/gin/pull/1565) | ||||
| - [FIX] Format output log to os.Stderr [#1571](https://github.com/gin-gonic/gin/pull/1571) | ||||
| - [FIX] Make logger use a yellow background and a darkgray text for legibility [#1570](https://github.com/gin-gonic/gin/pull/1570) | ||||
| - [FIX] Remove sensitive request information from panic log. [#1370](https://github.com/gin-gonic/gin/pull/1370) | ||||
| - [FIX] log.Println() does not print timestamp [#829](https://github.com/gin-gonic/gin/pull/829) [#1560](https://github.com/gin-gonic/gin/pull/1560) | ||||
| - [NEW] Add PureJSON renderer [#694](https://github.com/gin-gonic/gin/pull/694) | ||||
| - [FIX] Add missing copyright and update if/else [#1497](https://github.com/gin-gonic/gin/pull/1497) | ||||
| - [FIX] Update msgpack usage [#1498](https://github.com/gin-gonic/gin/pull/1498) | ||||
| - [FIX] Use protobuf on render [#1496](https://github.com/gin-gonic/gin/pull/1496) | ||||
| - [FIX] Add support for Protobuf format response [#1479](https://github.com/gin-gonic/gin/pull/1479) | ||||
| - [NEW] Set default time format in form binding [#1487](https://github.com/gin-gonic/gin/pull/1487) | ||||
| - [FIX] Add BindXML and ShouldBindXML [#1485](https://github.com/gin-gonic/gin/pull/1485) | ||||
| - [NEW] Upgrade dependency libraries [#1491](https://github.com/gin-gonic/gin/pull/1491) | ||||
| 
 | ||||
| 
 | ||||
| ## Gin v1.3.0 | ||||
| 
 | ||||
| - [NEW] Add [`func (*Context) QueryMap`](https://godoc.org/github.com/gin-gonic/gin#Context.QueryMap), [`func (*Context) GetQueryMap`](https://godoc.org/github.com/gin-gonic/gin#Context.GetQueryMap), [`func (*Context) PostFormMap`](https://godoc.org/github.com/gin-gonic/gin#Context.PostFormMap) and [`func (*Context) GetPostFormMap`](https://godoc.org/github.com/gin-gonic/gin#Context.GetPostFormMap) to support `type map[string]string` as query string or form parameters, see [#1383](https://github.com/gin-gonic/gin/pull/1383) | ||||
| - [NEW] Add [`func (*Context) AsciiJSON`](https://godoc.org/github.com/gin-gonic/gin#Context.AsciiJSON), see [#1358](https://github.com/gin-gonic/gin/pull/1358) | ||||
| - [NEW] Add `Pusher()` in [`type ResponseWriter`](https://godoc.org/github.com/gin-gonic/gin#ResponseWriter) for supporting http2 push, see [#1273](https://github.com/gin-gonic/gin/pull/1273) | ||||
| - [NEW] Add [`func (*Context) DataFromReader`](https://godoc.org/github.com/gin-gonic/gin#Context.DataFromReader) for serving dynamic data, see [#1304](https://github.com/gin-gonic/gin/pull/1304) | ||||
| - [NEW] Add [`func (*Context) ShouldBindBodyWith`](https://godoc.org/github.com/gin-gonic/gin#Context.ShouldBindBodyWith) allowing to call binding multiple times, see [#1341](https://github.com/gin-gonic/gin/pull/1341) | ||||
| - [NEW] Support pointers in form binding, see [#1336](https://github.com/gin-gonic/gin/pull/1336) | ||||
| - [NEW] Add [`func (*Context) JSONP`](https://godoc.org/github.com/gin-gonic/gin#Context.JSONP), see [#1333](https://github.com/gin-gonic/gin/pull/1333) | ||||
| - [NEW] Support default value in form binding, see [#1138](https://github.com/gin-gonic/gin/pull/1138) | ||||
| - [NEW] Expose validator engine in [`type StructValidator`](https://godoc.org/github.com/gin-gonic/gin/binding#StructValidator), see [#1277](https://github.com/gin-gonic/gin/pull/1277) | ||||
| - [NEW] Add [`func (*Context) ShouldBind`](https://godoc.org/github.com/gin-gonic/gin#Context.ShouldBind), [`func (*Context) ShouldBindQuery`](https://godoc.org/github.com/gin-gonic/gin#Context.ShouldBindQuery) and [`func (*Context) ShouldBindJSON`](https://godoc.org/github.com/gin-gonic/gin#Context.ShouldBindJSON), see [#1047](https://github.com/gin-gonic/gin/pull/1047) | ||||
| - [NEW] Add support for `time.Time` location in form binding, see [#1117](https://github.com/gin-gonic/gin/pull/1117) | ||||
| - [NEW] Add [`func (*Context) BindQuery`](https://godoc.org/github.com/gin-gonic/gin#Context.BindQuery), see [#1029](https://github.com/gin-gonic/gin/pull/1029) | ||||
| - [NEW] Make [jsonite](https://github.com/json-iterator/go) optional with build tags, see [#1026](https://github.com/gin-gonic/gin/pull/1026) | ||||
| - [NEW] Show query string in logger, see [#999](https://github.com/gin-gonic/gin/pull/999) | ||||
| - [NEW] Add [`func (*Context) SecureJSON`](https://godoc.org/github.com/gin-gonic/gin#Context.SecureJSON), see [#987](https://github.com/gin-gonic/gin/pull/987) and [#993](https://github.com/gin-gonic/gin/pull/993) | ||||
| - [DEPRECATE] `func (*Context) GetCookie` for [`func (*Context) Cookie`](https://godoc.org/github.com/gin-gonic/gin#Context.Cookie) | ||||
| - [FIX] Don't display color tags if [`func DisableConsoleColor`](https://godoc.org/github.com/gin-gonic/gin#DisableConsoleColor) called, see [#1072](https://github.com/gin-gonic/gin/pull/1072) | ||||
| - [FIX] Gin Mode `""` when calling [`func Mode`](https://godoc.org/github.com/gin-gonic/gin#Mode) now returns `const DebugMode`, see [#1250](https://github.com/gin-gonic/gin/pull/1250) | ||||
| - [FIX] `Flush()` now doesn't overwrite `responseWriter` status code, see [#1460](https://github.com/gin-gonic/gin/pull/1460) | ||||
| 
 | ||||
| ## Gin 1.2.0 | ||||
| 
 | ||||
| - [NEW] Switch from godeps to govendor | ||||
| - [NEW] Add support for Let's Encrypt via gin-gonic/autotls | ||||
| - [NEW] Improve README examples and add extra at examples folder | ||||
| - [NEW] Improved support with App Engine | ||||
| - [NEW] Add custom template delimiters, see #860 | ||||
| - [NEW] Add Template Func Maps, see #962 | ||||
| - [NEW] Add \*context.Handler(), see #928 | ||||
| - [NEW] Add \*context.GetRawData() | ||||
| - [NEW] Add \*context.GetHeader() (request) | ||||
| - [NEW] Add \*context.AbortWithStatusJSON() (JSON content type) | ||||
| - [NEW] Add \*context.Keys type cast helpers | ||||
| - [NEW] Add \*context.ShouldBindWith() | ||||
| - [NEW] Add \*context.MustBindWith() | ||||
| - [NEW] Add \*engine.SetFuncMap() | ||||
| - [DEPRECATE] On next release: \*context.BindWith(), see #855 | ||||
| - [FIX] Refactor render | ||||
| - [FIX] Reworked tests | ||||
| - [FIX] logger now supports cygwin | ||||
| - [FIX] Use X-Forwarded-For before X-Real-Ip | ||||
| - [FIX] time.Time binding (#904) | ||||
| 
 | ||||
| ## Gin 1.1.4 | ||||
| 
 | ||||
| - [NEW] Support google appengine for IsTerminal func | ||||
| 
 | ||||
| ## Gin 1.1.3 | ||||
| 
 | ||||
| - [FIX] Reverted Logger: skip ANSI color commands | ||||
| 
 | ||||
| ## Gin 1.1 | ||||
| 
 | ||||
| - [NEW] Implement QueryArray and PostArray methods | ||||
| - [NEW] Refactor GetQuery and GetPostForm | ||||
| - [NEW] Add contribution guide | ||||
| - [FIX] Corrected typos in README | ||||
| - [FIX] Removed additional Iota | ||||
| - [FIX] Changed imports to gopkg instead of github in README (#733) | ||||
| - [FIX] Logger: skip ANSI color commands if output is not a tty | ||||
| 
 | ||||
| ## Gin 1.0rc2 (...) | ||||
| 
 | ||||
| - [PERFORMANCE] Fast path for writing Content-Type. | ||||
| - [PERFORMANCE] Much faster 404 routing | ||||
| - [PERFORMANCE] Allocation optimizations | ||||
| - [PERFORMANCE] Faster root tree lookup | ||||
| - [PERFORMANCE] Zero overhead, String() and JSON() rendering. | ||||
| - [PERFORMANCE] Faster ClientIP parsing | ||||
| - [PERFORMANCE] Much faster SSE implementation | ||||
| - [NEW] Benchmarks suite | ||||
| - [NEW] Bind validation can be disabled and replaced with custom validators. | ||||
| - [NEW] More flexible HTML render | ||||
| - [NEW] Multipart and PostForm bindings | ||||
| - [NEW] Adds method to return all the registered routes | ||||
| - [NEW] Context.HandlerName() returns the main handler's name | ||||
| - [NEW] Adds Error.IsType() helper | ||||
| - [FIX] Binding multipart form | ||||
| - [FIX] Integration tests | ||||
| - [FIX] Crash when binding non struct object in Context. | ||||
| - [FIX] RunTLS() implementation | ||||
| - [FIX] Logger() unit tests | ||||
| - [FIX] Adds SetHTMLTemplate() warning | ||||
| - [FIX] Context.IsAborted() | ||||
| - [FIX] More unit tests | ||||
| - [FIX] JSON, XML, HTML renders accept custom content-types | ||||
| - [FIX] gin.AbortIndex is unexported | ||||
| - [FIX] Better approach to avoid directory listing in StaticFS() | ||||
| - [FIX] Context.ClientIP() always returns the IP with trimmed spaces. | ||||
| - [FIX] Better warning when running in debug mode. | ||||
| - [FIX] Google App Engine integration. debugPrint does not use os.Stdout | ||||
| - [FIX] Fixes integer overflow in error type | ||||
| - [FIX] Error implements the json.Marshaller interface | ||||
| - [FIX] MIT license in every file | ||||
| 
 | ||||
| 
 | ||||
| ## Gin 1.0rc1 (May 22, 2015) | ||||
| 
 | ||||
| - [PERFORMANCE] Zero allocation router | ||||
| - [PERFORMANCE] Faster JSON, XML and text rendering | ||||
| - [PERFORMANCE] Custom hand optimized HttpRouter for Gin | ||||
| - [PERFORMANCE] Misc code optimizations. Inlining, tail call optimizations | ||||
| - [NEW] Built-in support for golang.org/x/net/context | ||||
| - [NEW] Any(path, handler). Create a route that matches any path | ||||
| - [NEW] Refactored rendering pipeline (faster and static typed) | ||||
| - [NEW] Refactored errors API | ||||
| - [NEW] IndentedJSON() prints pretty JSON | ||||
| - [NEW] Added gin.DefaultWriter | ||||
| - [NEW] UNIX socket support | ||||
| - [NEW] RouterGroup.BasePath is exposed | ||||
| - [NEW] JSON validation using go-validate-yourself (very powerful options) | ||||
| - [NEW] Completed suite of unit tests | ||||
| - [NEW] HTTP streaming with c.Stream() | ||||
| - [NEW] StaticFile() creates a router for serving just one file. | ||||
| - [NEW] StaticFS() has an option to disable directory listing. | ||||
| - [NEW] StaticFS() for serving static files through virtual filesystems | ||||
| - [NEW] Server-Sent Events native support | ||||
| - [NEW] WrapF() and WrapH() helpers for wrapping http.HandlerFunc and http.Handler | ||||
| - [NEW] Added LoggerWithWriter() middleware | ||||
| - [NEW] Added RecoveryWithWriter() middleware | ||||
| - [NEW] Added DefaultPostFormValue() | ||||
| - [NEW] Added DefaultFormValue() | ||||
| - [NEW] Added DefaultParamValue() | ||||
| - [FIX] BasicAuth() when using custom realm | ||||
| - [FIX] Bug when serving static files in nested routing group | ||||
| - [FIX] Redirect using built-in http.Redirect() | ||||
| - [FIX] Logger when printing the requested path | ||||
| - [FIX] Documentation typos | ||||
| - [FIX] Context.Engine renamed to Context.engine | ||||
| - [FIX] Better debugging messages | ||||
| - [FIX] ErrorLogger | ||||
| - [FIX] Debug HTTP render | ||||
| - [FIX] Refactored binding and render modules | ||||
| - [FIX] Refactored Context initialization | ||||
| - [FIX] Refactored BasicAuth() | ||||
| - [FIX] NoMethod/NoRoute handlers | ||||
| - [FIX] Hijacking http | ||||
| - [FIX] Better support for Google App Engine (using log instead of fmt) | ||||
| 
 | ||||
| 
 | ||||
| ## Gin 0.6 (Mar 9, 2015) | ||||
| 
 | ||||
| - [NEW] Support multipart/form-data | ||||
| - [NEW] NoMethod handler | ||||
| - [NEW] Validate sub structures | ||||
| - [NEW] Support for HTTP Realm Auth | ||||
| - [FIX] Unsigned integers in binding | ||||
| - [FIX] Improve color logger | ||||
| 
 | ||||
| 
 | ||||
| ## Gin 0.5 (Feb 7, 2015) | ||||
| 
 | ||||
| - [NEW] Content Negotiation | ||||
| - [FIX] Solved security bug that allow a client to spoof ip | ||||
| - [FIX] Fix unexported/ignored fields in binding | ||||
| 
 | ||||
| 
 | ||||
| ## Gin 0.4 (Aug 21, 2014) | ||||
| 
 | ||||
| - [NEW] Development mode | ||||
| - [NEW] Unit tests | ||||
| - [NEW] Add Content.Redirect() | ||||
| - [FIX] Deferring WriteHeader() | ||||
| - [FIX] Improved documentation for model binding | ||||
| 
 | ||||
| 
 | ||||
| ## Gin 0.3 (Jul 18, 2014) | ||||
| 
 | ||||
| - [PERFORMANCE] Normal log and error log are printed in the same call. | ||||
| - [PERFORMANCE] Improve performance of NoRouter() | ||||
| - [PERFORMANCE] Improve context's memory locality, reduce CPU cache faults. | ||||
| - [NEW] Flexible rendering API | ||||
| - [NEW] Add Context.File() | ||||
| - [NEW] Add shortcut RunTLS() for http.ListenAndServeTLS | ||||
| - [FIX] Rename NotFound404() to NoRoute() | ||||
| - [FIX] Errors in context are purged | ||||
| - [FIX] Adds HEAD method in Static file serving | ||||
| - [FIX] Refactors Static() file serving | ||||
| - [FIX] Using keyed initialization to fix app-engine integration | ||||
| - [FIX] Can't unmarshal JSON array, #63 | ||||
| - [FIX] Renaming Context.Req to Context.Request | ||||
| - [FIX] Check application/x-www-form-urlencoded when parsing form | ||||
| 
 | ||||
| 
 | ||||
| ## Gin 0.2b (Jul 08, 2014) | ||||
| - [PERFORMANCE] Using sync.Pool to allocatio/gc overhead | ||||
| - [NEW] Travis CI integration | ||||
| - [NEW] Completely new logger | ||||
| - [NEW] New API for serving static files. gin.Static() | ||||
| - [NEW] gin.H() can be serialized into XML | ||||
| - [NEW] Typed errors. Errors can be typed. Internet/external/custom. | ||||
| - [NEW] Support for Godeps | ||||
| - [NEW] Travis/Godocs badges in README | ||||
| - [NEW] New Bind() and BindWith() methods for parsing request body. | ||||
| - [NEW] Add Content.Copy() | ||||
| - [NEW] Add context.LastError() | ||||
| - [NEW] Add shortcut for OPTIONS HTTP method | ||||
| - [FIX] Tons of README fixes | ||||
| - [FIX] Header is written before body | ||||
| - [FIX] BasicAuth() and changes API a little bit | ||||
| - [FIX] Recovery() middleware only prints panics | ||||
| - [FIX] Context.Get() does not panic anymore. Use MustGet() instead. | ||||
| - [FIX] Multiple http.WriteHeader() in NotFound handlers | ||||
| - [FIX] Engine.Run() panics if http server can't be set up | ||||
| - [FIX] Crash when route path doesn't start with '/' | ||||
| - [FIX] Do not update header when status code is negative | ||||
| - [FIX] Setting response headers before calling WriteHeader in context.String() | ||||
| - [FIX] Add MIT license | ||||
| - [FIX] Changes behaviour of ErrorLogger() and Logger() | ||||
							
								
								
									
										46
									
								
								vendor/github.com/gin-gonic/gin/CODE_OF_CONDUCT.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/gin-gonic/gin/CODE_OF_CONDUCT.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | |||
| # Contributor Covenant Code of Conduct | ||||
| 
 | ||||
| ## Our Pledge | ||||
| 
 | ||||
| In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. | ||||
| 
 | ||||
| ## Our Standards | ||||
| 
 | ||||
| Examples of behavior that contributes to creating a positive environment include: | ||||
| 
 | ||||
| * Using welcoming and inclusive language | ||||
| * Being respectful of differing viewpoints and experiences | ||||
| * Gracefully accepting constructive criticism | ||||
| * Focusing on what is best for the community | ||||
| * Showing empathy towards other community members | ||||
| 
 | ||||
| Examples of unacceptable behavior by participants include: | ||||
| 
 | ||||
| * The use of sexualized language or imagery and unwelcome sexual attention or advances | ||||
| * Trolling, insulting/derogatory comments, and personal or political attacks | ||||
| * Public or private harassment | ||||
| * Publishing others' private information, such as a physical or electronic address, without explicit permission | ||||
| * Other conduct which could reasonably be considered inappropriate in a professional setting | ||||
| 
 | ||||
| ## Our Responsibilities | ||||
| 
 | ||||
| Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. | ||||
| 
 | ||||
| Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. | ||||
| 
 | ||||
| ## Scope | ||||
| 
 | ||||
| This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. | ||||
| 
 | ||||
| ## Enforcement | ||||
| 
 | ||||
| Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at teamgingonic@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. | ||||
| 
 | ||||
| Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. | ||||
| 
 | ||||
| ## Attribution | ||||
| 
 | ||||
| This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] | ||||
| 
 | ||||
| [homepage]: http://contributor-covenant.org | ||||
| [version]: http://contributor-covenant.org/version/1/4/ | ||||
							
								
								
									
										13
									
								
								vendor/github.com/gin-gonic/gin/CONTRIBUTING.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/gin-gonic/gin/CONTRIBUTING.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| ## Contributing | ||||
| 
 | ||||
| - With issues: | ||||
|   - Use the search tool before opening a new issue. | ||||
|   - Please provide source code and commit sha if you found a bug. | ||||
|   - Review existing issues and provide feedback or react to them. | ||||
| 
 | ||||
| - 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 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. | ||||
							
								
								
									
										21
									
								
								vendor/github.com/gin-gonic/gin/LICENSE
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/gin-gonic/gin/LICENSE
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2014 Manuel Martínez-Almeida | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | ||||
							
								
								
									
										77
									
								
								vendor/github.com/gin-gonic/gin/Makefile
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								vendor/github.com/gin-gonic/gin/Makefile
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | |||
| 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") | ||||
| TESTFOLDER := $(shell $(GO) list ./... | grep -E 'gin$$|binding$$|render$$' | grep -v examples) | ||||
| TESTTAGS ?= "" | ||||
| 
 | ||||
| .PHONY: test | ||||
| test: | ||||
| 	echo "mode: count" > coverage.out | ||||
| 	for d in $(TESTFOLDER); do \
 | ||||
| 		$(GO) test -tags $(TESTTAGS) -v -covermode=count -coverprofile=profile.out $$d > tmp.out; \
 | ||||
| 		cat tmp.out; \
 | ||||
| 		if grep -q "^--- FAIL" tmp.out; then \
 | ||||
| 			rm tmp.out; \
 | ||||
| 			exit 1; \
 | ||||
| 		elif grep -q "build failed" tmp.out; then \
 | ||||
| 			rm tmp.out; \
 | ||||
| 			exit 1; \
 | ||||
| 		elif grep -q "setup failed" tmp.out; then \
 | ||||
| 			rm tmp.out; \
 | ||||
| 			exit 1; \
 | ||||
| 		fi; \
 | ||||
| 		if [ -f profile.out ]; then \
 | ||||
| 			cat profile.out | grep -v "mode:" >> coverage.out; \
 | ||||
| 			rm profile.out; \
 | ||||
| 		fi; \
 | ||||
| 	done | ||||
| 
 | ||||
| .PHONY: fmt | ||||
| fmt: | ||||
| 	$(GOFMT) -w $(GOFILES) | ||||
| 
 | ||||
| .PHONY: fmt-check | ||||
| fmt-check: | ||||
| 	@diff=$$($(GOFMT) -d $(GOFILES)); \
 | ||||
| 	if [ -n "$$diff" ]; then \
 | ||||
| 		echo "Please run 'make fmt' and commit the result:"; \
 | ||||
| 		echo "$${diff}"; \
 | ||||
| 		exit 1; \
 | ||||
| 	fi; | ||||
| 
 | ||||
| vet: | ||||
| 	$(GO) vet $(VETPACKAGES) | ||||
| 
 | ||||
| .PHONY: lint | ||||
| lint: | ||||
| 	@hash golint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | ||||
| 		$(GO) get -u golang.org/x/lint/golint; \
 | ||||
| 	fi | ||||
| 	for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done; | ||||
| 
 | ||||
| .PHONY: misspell-check | ||||
| misspell-check: | ||||
| 	@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | ||||
| 		$(GO) get -u github.com/client9/misspell/cmd/misspell; \
 | ||||
| 	fi | ||||
| 	misspell -error $(GOFILES) | ||||
| 
 | ||||
| .PHONY: misspell | ||||
| misspell: | ||||
| 	@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | ||||
| 		$(GO) get -u github.com/client9/misspell/cmd/misspell; \
 | ||||
| 	fi | ||||
| 	misspell -w $(GOFILES) | ||||
| 
 | ||||
| .PHONY: tools | ||||
| tools: | ||||
| 	@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 | ||||
							
								
								
									
										2289
									
								
								vendor/github.com/gin-gonic/gin/README.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2289
									
								
								vendor/github.com/gin-gonic/gin/README.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										91
									
								
								vendor/github.com/gin-gonic/gin/auth.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/github.com/gin-gonic/gin/auth.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | |||
| // 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 ( | ||||
| 	"crypto/subtle" | ||||
| 	"encoding/base64" | ||||
| 	"net/http" | ||||
| 	"strconv" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin/internal/bytesconv" | ||||
| ) | ||||
| 
 | ||||
| // AuthUserKey is the cookie name for user credential in basic auth. | ||||
| const AuthUserKey = "user" | ||||
| 
 | ||||
| // Accounts defines a key/value for user/pass list of authorized logins. | ||||
| type Accounts map[string]string | ||||
| 
 | ||||
| type authPair struct { | ||||
| 	value string | ||||
| 	user  string | ||||
| } | ||||
| 
 | ||||
| type authPairs []authPair | ||||
| 
 | ||||
| func (a authPairs) searchCredential(authValue string) (string, bool) { | ||||
| 	if authValue == "" { | ||||
| 		return "", false | ||||
| 	} | ||||
| 	for _, pair := range a { | ||||
| 		if subtle.ConstantTimeCompare([]byte(pair.value), []byte(authValue)) == 1 { | ||||
| 			return pair.user, true | ||||
| 		} | ||||
| 	} | ||||
| 	return "", false | ||||
| } | ||||
| 
 | ||||
| // BasicAuthForRealm returns a Basic HTTP Authorization middleware. It takes as arguments a map[string]string where | ||||
| // the key is the user name and the value is the password, as well as the name of the Realm. | ||||
| // If the realm is empty, "Authorization Required" will be used by default. | ||||
| // (see http://tools.ietf.org/html/rfc2617#section-1.2) | ||||
| func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc { | ||||
| 	if realm == "" { | ||||
| 		realm = "Authorization Required" | ||||
| 	} | ||||
| 	realm = "Basic realm=" + strconv.Quote(realm) | ||||
| 	pairs := processAccounts(accounts) | ||||
| 	return func(c *Context) { | ||||
| 		// Search user in the slice of allowed credentials | ||||
| 		user, found := pairs.searchCredential(c.requestHeader("Authorization")) | ||||
| 		if !found { | ||||
| 			// Credentials doesn't match, we return 401 and abort handlers chain. | ||||
| 			c.Header("WWW-Authenticate", realm) | ||||
| 			c.AbortWithStatus(http.StatusUnauthorized) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		// The user credentials was found, set user's id to key AuthUserKey in this context, the user's id can be read later using | ||||
| 		// c.MustGet(gin.AuthUserKey). | ||||
| 		c.Set(AuthUserKey, user) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // BasicAuth returns a Basic HTTP Authorization middleware. It takes as argument a map[string]string where | ||||
| // the key is the user name and the value is the password. | ||||
| func BasicAuth(accounts Accounts) HandlerFunc { | ||||
| 	return BasicAuthForRealm(accounts, "") | ||||
| } | ||||
| 
 | ||||
| func processAccounts(accounts Accounts) authPairs { | ||||
| 	length := len(accounts) | ||||
| 	assert1(length > 0, "Empty list of authorized credentials") | ||||
| 	pairs := make(authPairs, 0, length) | ||||
| 	for user, password := range accounts { | ||||
| 		assert1(user != "", "User can not be empty") | ||||
| 		value := authorizationHeader(user, password) | ||||
| 		pairs = append(pairs, authPair{ | ||||
| 			value: value, | ||||
| 			user:  user, | ||||
| 		}) | ||||
| 	} | ||||
| 	return pairs | ||||
| } | ||||
| 
 | ||||
| func authorizationHeader(user, password string) string { | ||||
| 	base := user + ":" + password | ||||
| 	return "Basic " + base64.StdEncoding.EncodeToString(bytesconv.StringToBytes(base)) | ||||
| } | ||||
							
								
								
									
										118
									
								
								vendor/github.com/gin-gonic/gin/binding/binding.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								vendor/github.com/gin-gonic/gin/binding/binding.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,118 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build !nomsgpack | ||||
| // +build !nomsgpack | ||||
| 
 | ||||
| package binding | ||||
| 
 | ||||
| import "net/http" | ||||
| 
 | ||||
| // Content-Type MIME of the most common data formats. | ||||
| const ( | ||||
| 	MIMEJSON              = "application/json" | ||||
| 	MIMEHTML              = "text/html" | ||||
| 	MIMEXML               = "application/xml" | ||||
| 	MIMEXML2              = "text/xml" | ||||
| 	MIMEPlain             = "text/plain" | ||||
| 	MIMEPOSTForm          = "application/x-www-form-urlencoded" | ||||
| 	MIMEMultipartPOSTForm = "multipart/form-data" | ||||
| 	MIMEPROTOBUF          = "application/x-protobuf" | ||||
| 	MIMEMSGPACK           = "application/x-msgpack" | ||||
| 	MIMEMSGPACK2          = "application/msgpack" | ||||
| 	MIMEYAML              = "application/x-yaml" | ||||
| ) | ||||
| 
 | ||||
| // Binding describes the interface which needs to be implemented for binding the | ||||
| // data present in the request such as JSON request body, query parameters or | ||||
| // the form POST. | ||||
| type Binding interface { | ||||
| 	Name() string | ||||
| 	Bind(*http.Request, interface{}) 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 | ||||
| } | ||||
| 
 | ||||
| // BindingUri adds BindUri method to Binding. BindUri is similar with Bind, | ||||
| // but it read the Params. | ||||
| type BindingUri interface { | ||||
| 	Name() string | ||||
| 	BindUri(map[string][]string, interface{}) 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/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. | ||||
| 	// If the received type is not a struct or slice|array, 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 | ||||
| 
 | ||||
| 	// Engine returns the underlying validator engine which powers the | ||||
| 	// StructValidator implementation. | ||||
| 	Engine() interface{} | ||||
| } | ||||
| 
 | ||||
| // Validator is the default validator which implements the StructValidator | ||||
| // interface. It uses https://github.com/go-playground/validator/tree/v10.6.1 | ||||
| // under the hood. | ||||
| var Validator StructValidator = &defaultValidator{} | ||||
| 
 | ||||
| // These implement the Binding interface and can be used to bind the data | ||||
| // present in the request to struct instances. | ||||
| var ( | ||||
| 	JSON          = jsonBinding{} | ||||
| 	XML           = xmlBinding{} | ||||
| 	Form          = formBinding{} | ||||
| 	Query         = queryBinding{} | ||||
| 	FormPost      = formPostBinding{} | ||||
| 	FormMultipart = formMultipartBinding{} | ||||
| 	ProtoBuf      = protobufBinding{} | ||||
| 	MsgPack       = msgpackBinding{} | ||||
| 	YAML          = yamlBinding{} | ||||
| 	Uri           = uriBinding{} | ||||
| 	Header        = headerBinding{} | ||||
| ) | ||||
| 
 | ||||
| // Default returns the appropriate Binding instance based on the HTTP method | ||||
| // and the content type. | ||||
| func Default(method, contentType string) Binding { | ||||
| 	if method == http.MethodGet { | ||||
| 		return Form | ||||
| 	} | ||||
| 
 | ||||
| 	switch contentType { | ||||
| 	case MIMEJSON: | ||||
| 		return JSON | ||||
| 	case MIMEXML, MIMEXML2: | ||||
| 		return XML | ||||
| 	case MIMEPROTOBUF: | ||||
| 		return ProtoBuf | ||||
| 	case MIMEMSGPACK, MIMEMSGPACK2: | ||||
| 		return MsgPack | ||||
| 	case MIMEYAML: | ||||
| 		return YAML | ||||
| 	case MIMEMultipartPOSTForm: | ||||
| 		return FormMultipart | ||||
| 	default: // case MIMEPOSTForm: | ||||
| 		return Form | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func validate(obj interface{}) error { | ||||
| 	if Validator == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return Validator.ValidateStruct(obj) | ||||
| } | ||||
							
								
								
									
										112
									
								
								vendor/github.com/gin-gonic/gin/binding/binding_nomsgpack.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								vendor/github.com/gin-gonic/gin/binding/binding_nomsgpack.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| // Copyright 2020 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 nomsgpack | ||||
| // +build nomsgpack | ||||
| 
 | ||||
| package binding | ||||
| 
 | ||||
| import "net/http" | ||||
| 
 | ||||
| // Content-Type MIME of the most common data formats. | ||||
| const ( | ||||
| 	MIMEJSON              = "application/json" | ||||
| 	MIMEHTML              = "text/html" | ||||
| 	MIMEXML               = "application/xml" | ||||
| 	MIMEXML2              = "text/xml" | ||||
| 	MIMEPlain             = "text/plain" | ||||
| 	MIMEPOSTForm          = "application/x-www-form-urlencoded" | ||||
| 	MIMEMultipartPOSTForm = "multipart/form-data" | ||||
| 	MIMEPROTOBUF          = "application/x-protobuf" | ||||
| 	MIMEYAML              = "application/x-yaml" | ||||
| ) | ||||
| 
 | ||||
| // Binding describes the interface which needs to be implemented for binding the | ||||
| // data present in the request such as JSON request body, query parameters or | ||||
| // the form POST. | ||||
| type Binding interface { | ||||
| 	Name() string | ||||
| 	Bind(*http.Request, interface{}) 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 | ||||
| } | ||||
| 
 | ||||
| // BindingUri adds BindUri method to Binding. BindUri is similar with Bind, | ||||
| // but it read the Params. | ||||
| type BindingUri interface { | ||||
| 	Name() string | ||||
| 	BindUri(map[string][]string, interface{}) 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/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 | ||||
| 
 | ||||
| 	// Engine returns the underlying validator engine which powers the | ||||
| 	// StructValidator implementation. | ||||
| 	Engine() interface{} | ||||
| } | ||||
| 
 | ||||
| // Validator is the default validator which implements the StructValidator | ||||
| // interface. It uses https://github.com/go-playground/validator/tree/v10.6.1 | ||||
| // under the hood. | ||||
| var Validator StructValidator = &defaultValidator{} | ||||
| 
 | ||||
| // These implement the Binding interface and can be used to bind the data | ||||
| // present in the request to struct instances. | ||||
| var ( | ||||
| 	JSON          = jsonBinding{} | ||||
| 	XML           = xmlBinding{} | ||||
| 	Form          = formBinding{} | ||||
| 	Query         = queryBinding{} | ||||
| 	FormPost      = formPostBinding{} | ||||
| 	FormMultipart = formMultipartBinding{} | ||||
| 	ProtoBuf      = protobufBinding{} | ||||
| 	YAML          = yamlBinding{} | ||||
| 	Uri           = uriBinding{} | ||||
| 	Header        = headerBinding{} | ||||
| ) | ||||
| 
 | ||||
| // Default returns the appropriate Binding instance based on the HTTP method | ||||
| // and the content type. | ||||
| func Default(method, contentType string) Binding { | ||||
| 	if method == "GET" { | ||||
| 		return Form | ||||
| 	} | ||||
| 
 | ||||
| 	switch contentType { | ||||
| 	case MIMEJSON: | ||||
| 		return JSON | ||||
| 	case MIMEXML, MIMEXML2: | ||||
| 		return XML | ||||
| 	case MIMEPROTOBUF: | ||||
| 		return ProtoBuf | ||||
| 	case MIMEYAML: | ||||
| 		return YAML | ||||
| 	case MIMEMultipartPOSTForm: | ||||
| 		return FormMultipart | ||||
| 	default: // case MIMEPOSTForm: | ||||
| 		return Form | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func validate(obj interface{}) error { | ||||
| 	if Validator == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return Validator.ValidateStruct(obj) | ||||
| } | ||||
							
								
								
									
										97
									
								
								vendor/github.com/gin-gonic/gin/binding/default_validator.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								vendor/github.com/gin-gonic/gin/binding/default_validator.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,97 @@ | |||
| // 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. | ||||
| 
 | ||||
| package binding | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 
 | ||||
| 	"github.com/go-playground/validator/v10" | ||||
| ) | ||||
| 
 | ||||
| type defaultValidator struct { | ||||
| 	once     sync.Once | ||||
| 	validate *validator.Validate | ||||
| } | ||||
| 
 | ||||
| type sliceValidateError []error | ||||
| 
 | ||||
| // Error concatenates all error elements in sliceValidateError into a single string separated by \n. | ||||
| func (err sliceValidateError) 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()) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return b.String() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
| 	if obj == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	value := reflect.ValueOf(obj) | ||||
| 	switch value.Kind() { | ||||
| 	case reflect.Ptr: | ||||
| 		return v.ValidateStruct(value.Elem().Interface()) | ||||
| 	case reflect.Struct: | ||||
| 		return v.validateStruct(obj) | ||||
| 	case reflect.Slice, reflect.Array: | ||||
| 		count := value.Len() | ||||
| 		validateRet := make(sliceValidateError, 0) | ||||
| 		for i := 0; i < count; i++ { | ||||
| 			if err := v.ValidateStruct(value.Index(i).Interface()); err != nil { | ||||
| 				validateRet = append(validateRet, err) | ||||
| 			} | ||||
| 		} | ||||
| 		if len(validateRet) == 0 { | ||||
| 			return nil | ||||
| 		} | ||||
| 		return validateRet | ||||
| 	default: | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // validateStruct receives struct type | ||||
| func (v *defaultValidator) validateStruct(obj interface{}) error { | ||||
| 	v.lazyinit() | ||||
| 	return v.validate.Struct(obj) | ||||
| } | ||||
| 
 | ||||
| // 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://pkg.go.dev/github.com/go-playground/validator/v10 | ||||
| func (v *defaultValidator) Engine() interface{} { | ||||
| 	v.lazyinit() | ||||
| 	return v.validate | ||||
| } | ||||
| 
 | ||||
| func (v *defaultValidator) lazyinit() { | ||||
| 	v.once.Do(func() { | ||||
| 		v.validate = validator.New() | ||||
| 		v.validate.SetTagName("binding") | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										61
									
								
								vendor/github.com/gin-gonic/gin/binding/form.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								vendor/github.com/gin-gonic/gin/binding/form.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| // 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 ( | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| const defaultMemory = 32 << 20 | ||||
| 
 | ||||
| type formBinding struct{} | ||||
| type formPostBinding struct{} | ||||
| type formMultipartBinding struct{} | ||||
| 
 | ||||
| func (formBinding) Name() string { | ||||
| 	return "form" | ||||
| } | ||||
| 
 | ||||
| func (formBinding) Bind(req *http.Request, obj interface{}) error { | ||||
| 	if err := req.ParseForm(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := req.ParseMultipartForm(defaultMemory); err != nil && err != http.ErrNotMultipart { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := mapForm(obj, req.Form); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return validate(obj) | ||||
| } | ||||
| 
 | ||||
| func (formPostBinding) Name() string { | ||||
| 	return "form-urlencoded" | ||||
| } | ||||
| 
 | ||||
| func (formPostBinding) Bind(req *http.Request, obj interface{}) error { | ||||
| 	if err := req.ParseForm(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := mapForm(obj, req.PostForm); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return validate(obj) | ||||
| } | ||||
| 
 | ||||
| func (formMultipartBinding) Name() string { | ||||
| 	return "multipart/form-data" | ||||
| } | ||||
| 
 | ||||
| func (formMultipartBinding) Bind(req *http.Request, obj interface{}) error { | ||||
| 	if err := req.ParseMultipartForm(defaultMemory); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := mappingByPtr(obj, (*multipartRequest)(req), "form"); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return validate(obj) | ||||
| } | ||||
							
								
								
									
										404
									
								
								vendor/github.com/gin-gonic/gin/binding/form_mapping.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										404
									
								
								vendor/github.com/gin-gonic/gin/binding/form_mapping.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,404 @@ | |||
| // 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" | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin/internal/bytesconv" | ||||
| 	"github.com/gin-gonic/gin/internal/json" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	errUnknownType = errors.New("unknown type") | ||||
| 
 | ||||
| 	// 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 interface{}, m map[string][]string) error { | ||||
| 	return mapFormByTag(ptr, m, "uri") | ||||
| } | ||||
| 
 | ||||
| func mapForm(ptr interface{}, form map[string][]string) error { | ||||
| 	return mapFormByTag(ptr, form, "form") | ||||
| } | ||||
| 
 | ||||
| func MapFormWithTag(ptr interface{}, 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 { | ||||
| 	// Check if ptr is a map | ||||
| 	ptrVal := reflect.ValueOf(ptr) | ||||
| 	var pointed interface{} | ||||
| 	if ptrVal.Kind() == reflect.Ptr { | ||||
| 		ptrVal = ptrVal.Elem() | ||||
| 		pointed = ptrVal.Interface() | ||||
| 	} | ||||
| 	if ptrVal.Kind() == reflect.Map && | ||||
| 		ptrVal.Type().Key().Kind() == reflect.String { | ||||
| 		if pointed != nil { | ||||
| 			ptr = pointed | ||||
| 		} | ||||
| 		return setFormMap(ptr, form) | ||||
| 	} | ||||
| 
 | ||||
| 	return mappingByPtr(ptr, formSource(form), tag) | ||||
| } | ||||
| 
 | ||||
| // 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) | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
| 	return setByForm(value, field, form, tagValue, opt) | ||||
| } | ||||
| 
 | ||||
| func mappingByPtr(ptr interface{}, setter setter, tag string) error { | ||||
| 	_, err := mapping(reflect.ValueOf(ptr), emptyField, setter, tag) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func mapping(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) { | ||||
| 	if field.Tag.Get(tag) == "-" { // just ignoring this field | ||||
| 		return false, nil | ||||
| 	} | ||||
| 
 | ||||
| 	var vKind = value.Kind() | ||||
| 
 | ||||
| 	if vKind == reflect.Ptr { | ||||
| 		var isNew bool | ||||
| 		vPtr := value | ||||
| 		if value.IsNil() { | ||||
| 			isNew = true | ||||
| 			vPtr = reflect.New(value.Type().Elem()) | ||||
| 		} | ||||
| 		isSetted, err := mapping(vPtr.Elem(), field, setter, tag) | ||||
| 		if err != nil { | ||||
| 			return false, err | ||||
| 		} | ||||
| 		if isNew && isSetted { | ||||
| 			value.Set(vPtr) | ||||
| 		} | ||||
| 		return isSetted, nil | ||||
| 	} | ||||
| 
 | ||||
| 	if vKind != reflect.Struct || !field.Anonymous { | ||||
| 		ok, err := tryToSetValue(value, field, setter, tag) | ||||
| 		if err != nil { | ||||
| 			return false, err | ||||
| 		} | ||||
| 		if ok { | ||||
| 			return true, nil | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if vKind == reflect.Struct { | ||||
| 		tValue := value.Type() | ||||
| 
 | ||||
| 		var isSetted 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), sf, setter, tag) | ||||
| 			if err != nil { | ||||
| 				return false, err | ||||
| 			} | ||||
| 			isSetted = isSetted || ok | ||||
| 		} | ||||
| 		return isSetted, nil | ||||
| 	} | ||||
| 	return false, nil | ||||
| } | ||||
| 
 | ||||
| type setOptions struct { | ||||
| 	isDefaultExists bool | ||||
| 	defaultValue    string | ||||
| } | ||||
| 
 | ||||
| func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter, tag string) (bool, error) { | ||||
| 	var tagValue string | ||||
| 	var setOpt setOptions | ||||
| 
 | ||||
| 	tagValue = field.Tag.Get(tag) | ||||
| 	tagValue, opts := head(tagValue, ",") | ||||
| 
 | ||||
| 	if tagValue == "" { // default value is FieldName | ||||
| 		tagValue = field.Name | ||||
| 	} | ||||
| 	if tagValue == "" { // when field is "emptyField" variable | ||||
| 		return false, nil | ||||
| 	} | ||||
| 
 | ||||
| 	var opt string | ||||
| 	for len(opts) > 0 { | ||||
| 		opt, opts = head(opts, ",") | ||||
| 
 | ||||
| 		if k, v := head(opt, "="); k == "default" { | ||||
| 			setOpt.isDefaultExists = true | ||||
| 			setOpt.defaultValue = v | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	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) { | ||||
| 	vs, ok := form[tagValue] | ||||
| 	if !ok && !opt.isDefaultExists { | ||||
| 		return false, nil | ||||
| 	} | ||||
| 
 | ||||
| 	switch value.Kind() { | ||||
| 	case reflect.Slice: | ||||
| 		if !ok { | ||||
| 			vs = []string{opt.defaultValue} | ||||
| 		} | ||||
| 		return true, setSlice(vs, value, field) | ||||
| 	case reflect.Array: | ||||
| 		if !ok { | ||||
| 			vs = []string{opt.defaultValue} | ||||
| 		} | ||||
| 		if len(vs) != value.Len() { | ||||
| 			return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String()) | ||||
| 		} | ||||
| 		return true, setArray(vs, value, field) | ||||
| 	default: | ||||
| 		var val string | ||||
| 		if !ok { | ||||
| 			val = opt.defaultValue | ||||
| 		} | ||||
| 
 | ||||
| 		if len(vs) > 0 { | ||||
| 			val = vs[0] | ||||
| 		} | ||||
| 		return true, setWithProperType(val, value, field) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func setWithProperType(val string, value reflect.Value, field reflect.StructField) error { | ||||
| 	switch value.Kind() { | ||||
| 	case reflect.Int: | ||||
| 		return setIntField(val, 0, value) | ||||
| 	case reflect.Int8: | ||||
| 		return setIntField(val, 8, value) | ||||
| 	case reflect.Int16: | ||||
| 		return setIntField(val, 16, value) | ||||
| 	case reflect.Int32: | ||||
| 		return setIntField(val, 32, value) | ||||
| 	case reflect.Int64: | ||||
| 		switch value.Interface().(type) { | ||||
| 		case time.Duration: | ||||
| 			return setTimeDuration(val, value, field) | ||||
| 		} | ||||
| 		return setIntField(val, 64, value) | ||||
| 	case reflect.Uint: | ||||
| 		return setUintField(val, 0, value) | ||||
| 	case reflect.Uint8: | ||||
| 		return setUintField(val, 8, value) | ||||
| 	case reflect.Uint16: | ||||
| 		return setUintField(val, 16, value) | ||||
| 	case reflect.Uint32: | ||||
| 		return setUintField(val, 32, value) | ||||
| 	case reflect.Uint64: | ||||
| 		return setUintField(val, 64, value) | ||||
| 	case reflect.Bool: | ||||
| 		return setBoolField(val, value) | ||||
| 	case reflect.Float32: | ||||
| 		return setFloatField(val, 32, value) | ||||
| 	case reflect.Float64: | ||||
| 		return setFloatField(val, 64, value) | ||||
| 	case reflect.String: | ||||
| 		value.SetString(val) | ||||
| 	case reflect.Struct: | ||||
| 		switch value.Interface().(type) { | ||||
| 		case time.Time: | ||||
| 			return setTimeField(val, field, value) | ||||
| 		} | ||||
| 		return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface()) | ||||
| 	case reflect.Map: | ||||
| 		return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface()) | ||||
| 	default: | ||||
| 		return errUnknownType | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func setIntField(val string, bitSize int, field reflect.Value) error { | ||||
| 	if val == "" { | ||||
| 		val = "0" | ||||
| 	} | ||||
| 	intVal, err := strconv.ParseInt(val, 10, bitSize) | ||||
| 	if err == nil { | ||||
| 		field.SetInt(intVal) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func setUintField(val string, bitSize int, field reflect.Value) error { | ||||
| 	if val == "" { | ||||
| 		val = "0" | ||||
| 	} | ||||
| 	uintVal, err := strconv.ParseUint(val, 10, bitSize) | ||||
| 	if err == nil { | ||||
| 		field.SetUint(uintVal) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func setBoolField(val string, field reflect.Value) error { | ||||
| 	if val == "" { | ||||
| 		val = "false" | ||||
| 	} | ||||
| 	boolVal, err := strconv.ParseBool(val) | ||||
| 	if err == nil { | ||||
| 		field.SetBool(boolVal) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func setFloatField(val string, bitSize int, field reflect.Value) error { | ||||
| 	if val == "" { | ||||
| 		val = "0.0" | ||||
| 	} | ||||
| 	floatVal, err := strconv.ParseFloat(val, bitSize) | ||||
| 	if err == nil { | ||||
| 		field.SetFloat(floatVal) | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func setTimeField(val string, structField reflect.StructField, value reflect.Value) error { | ||||
| 	timeFormat := structField.Tag.Get("time_format") | ||||
| 	if timeFormat == "" { | ||||
| 		timeFormat = time.RFC3339 | ||||
| 	} | ||||
| 
 | ||||
| 	switch tf := strings.ToLower(timeFormat); tf { | ||||
| 	case "unix", "unixnano": | ||||
| 		tv, err := strconv.ParseInt(val, 10, 64) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		d := time.Duration(1) | ||||
| 		if tf == "unixnano" { | ||||
| 			d = time.Second | ||||
| 		} | ||||
| 
 | ||||
| 		t := time.Unix(tv/int64(d), tv%int64(d)) | ||||
| 		value.Set(reflect.ValueOf(t)) | ||||
| 		return nil | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	if val == "" { | ||||
| 		value.Set(reflect.ValueOf(time.Time{})) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	l := time.Local | ||||
| 	if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC { | ||||
| 		l = time.UTC | ||||
| 	} | ||||
| 
 | ||||
| 	if locTag := structField.Tag.Get("time_location"); locTag != "" { | ||||
| 		loc, err := time.LoadLocation(locTag) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		l = loc | ||||
| 	} | ||||
| 
 | ||||
| 	t, err := time.ParseInLocation(timeFormat, val, l) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	value.Set(reflect.ValueOf(t)) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func setArray(vals []string, value reflect.Value, field reflect.StructField) error { | ||||
| 	for i, s := range vals { | ||||
| 		err := setWithProperType(s, value.Index(i), field) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func setSlice(vals []string, value reflect.Value, field reflect.StructField) error { | ||||
| 	slice := reflect.MakeSlice(value.Type(), len(vals), len(vals)) | ||||
| 	err := setArray(vals, slice, field) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	value.Set(slice) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func setTimeDuration(val string, value reflect.Value, field reflect.StructField) error { | ||||
| 	d, err := time.ParseDuration(val) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	value.Set(reflect.ValueOf(d)) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func head(str, sep string) (head string, tail string) { | ||||
| 	idx := strings.Index(str, sep) | ||||
| 	if idx < 0 { | ||||
| 		return str, "" | ||||
| 	} | ||||
| 	return str[:idx], str[idx+len(sep):] | ||||
| } | ||||
| 
 | ||||
| func setFormMap(ptr interface{}, form map[string][]string) error { | ||||
| 	el := reflect.TypeOf(ptr).Elem() | ||||
| 
 | ||||
| 	if el.Kind() == reflect.Slice { | ||||
| 		ptrMap, ok := ptr.(map[string][]string) | ||||
| 		if !ok { | ||||
| 			return ErrConvertMapStringSlice | ||||
| 		} | ||||
| 		for k, v := range form { | ||||
| 			ptrMap[k] = v | ||||
| 		} | ||||
| 
 | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	ptrMap, ok := ptr.(map[string]string) | ||||
| 	if !ok { | ||||
| 		return ErrConvertToMapString | ||||
| 	} | ||||
| 	for k, v := range form { | ||||
| 		ptrMap[k] = v[len(v)-1] // pick last | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										34
									
								
								vendor/github.com/gin-gonic/gin/binding/header.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/gin-gonic/gin/binding/header.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| package binding | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"net/textproto" | ||||
| 	"reflect" | ||||
| ) | ||||
| 
 | ||||
| type headerBinding struct{} | ||||
| 
 | ||||
| func (headerBinding) Name() string { | ||||
| 	return "header" | ||||
| } | ||||
| 
 | ||||
| func (headerBinding) Bind(req *http.Request, obj interface{}) error { | ||||
| 
 | ||||
| 	if err := mapHeader(obj, req.Header); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return validate(obj) | ||||
| } | ||||
| 
 | ||||
| func mapHeader(ptr interface{}, h map[string][]string) error { | ||||
| 	return mappingByPtr(ptr, headerSource(h), "header") | ||||
| } | ||||
| 
 | ||||
| type headerSource map[string][]string | ||||
| 
 | ||||
| var _ setter = headerSource(nil) | ||||
| 
 | ||||
| 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) | ||||
| } | ||||
							
								
								
									
										56
									
								
								vendor/github.com/gin-gonic/gin/binding/json.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								vendor/github.com/gin-gonic/gin/binding/json.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | |||
| // 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 ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin/internal/json" | ||||
| ) | ||||
| 
 | ||||
| // EnableDecoderUseNumber is used to call the UseNumber method on the JSON | ||||
| // Decoder instance. UseNumber causes the Decoder to unmarshal a number into an | ||||
| // interface{} as a Number instead of as a float64. | ||||
| var EnableDecoderUseNumber = false | ||||
| 
 | ||||
| // EnableDecoderDisallowUnknownFields is used to call the DisallowUnknownFields method | ||||
| // on the JSON Decoder instance. DisallowUnknownFields causes the Decoder to | ||||
| // return an error when the destination is a struct and the input contains object | ||||
| // keys which do not match any non-ignored, exported fields in the destination. | ||||
| var EnableDecoderDisallowUnknownFields = false | ||||
| 
 | ||||
| type jsonBinding struct{} | ||||
| 
 | ||||
| func (jsonBinding) Name() string { | ||||
| 	return "json" | ||||
| } | ||||
| 
 | ||||
| func (jsonBinding) Bind(req *http.Request, obj interface{}) error { | ||||
| 	if req == nil || req.Body == nil { | ||||
| 		return errors.New("invalid request") | ||||
| 	} | ||||
| 	return decodeJSON(req.Body, obj) | ||||
| } | ||||
| 
 | ||||
| func (jsonBinding) BindBody(body []byte, obj interface{}) error { | ||||
| 	return decodeJSON(bytes.NewReader(body), obj) | ||||
| } | ||||
| 
 | ||||
| func decodeJSON(r io.Reader, obj interface{}) error { | ||||
| 	decoder := json.NewDecoder(r) | ||||
| 	if EnableDecoderUseNumber { | ||||
| 		decoder.UseNumber() | ||||
| 	} | ||||
| 	if EnableDecoderDisallowUnknownFields { | ||||
| 		decoder.DisallowUnknownFields() | ||||
| 	} | ||||
| 	if err := decoder.Decode(obj); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return validate(obj) | ||||
| } | ||||
							
								
								
									
										38
									
								
								vendor/github.com/gin-gonic/gin/binding/msgpack.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								vendor/github.com/gin-gonic/gin/binding/msgpack.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build !nomsgpack | ||||
| // +build !nomsgpack | ||||
| 
 | ||||
| package binding | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/ugorji/go/codec" | ||||
| ) | ||||
| 
 | ||||
| type msgpackBinding struct{} | ||||
| 
 | ||||
| func (msgpackBinding) Name() string { | ||||
| 	return "msgpack" | ||||
| } | ||||
| 
 | ||||
| func (msgpackBinding) Bind(req *http.Request, obj interface{}) error { | ||||
| 	return decodeMsgPack(req.Body, obj) | ||||
| } | ||||
| 
 | ||||
| func (msgpackBinding) BindBody(body []byte, obj interface{}) error { | ||||
| 	return decodeMsgPack(bytes.NewReader(body), obj) | ||||
| } | ||||
| 
 | ||||
| func decodeMsgPack(r io.Reader, obj interface{}) error { | ||||
| 	cdc := new(codec.MsgpackHandle) | ||||
| 	if err := codec.NewDecoder(r, cdc).Decode(&obj); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return validate(obj) | ||||
| } | ||||
							
								
								
									
										74
									
								
								vendor/github.com/gin-gonic/gin/binding/multipart_form_mapping.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/gin-gonic/gin/binding/multipart_form_mapping.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | |||
| // 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. | ||||
| 
 | ||||
| package binding | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"mime/multipart" | ||||
| 	"net/http" | ||||
| 	"reflect" | ||||
| ) | ||||
| 
 | ||||
| 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) (bool, error) { | ||||
| 	if files := r.MultipartForm.File[key]; len(files) != 0 { | ||||
| 		return setByMultipartFormFile(value, field, files) | ||||
| 	} | ||||
| 
 | ||||
| 	return setByForm(value, field, r.MultipartForm.Value, key, opt) | ||||
| } | ||||
| 
 | ||||
| func setByMultipartFormFile(value reflect.Value, field reflect.StructField, files []*multipart.FileHeader) (isSetted bool, err error) { | ||||
| 	switch value.Kind() { | ||||
| 	case reflect.Ptr: | ||||
| 		switch value.Interface().(type) { | ||||
| 		case *multipart.FileHeader: | ||||
| 			value.Set(reflect.ValueOf(files[0])) | ||||
| 			return true, nil | ||||
| 		} | ||||
| 	case reflect.Struct: | ||||
| 		switch value.Interface().(type) { | ||||
| 		case multipart.FileHeader: | ||||
| 			value.Set(reflect.ValueOf(*files[0])) | ||||
| 			return true, nil | ||||
| 		} | ||||
| 	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 | ||||
| 		} | ||||
| 		value.Set(slice) | ||||
| 		return true, nil | ||||
| 	case reflect.Array: | ||||
| 		return setArrayOfMultipartFormFiles(value, field, files) | ||||
| 	} | ||||
| 	return false, ErrMultiFileHeader | ||||
| } | ||||
| 
 | ||||
| func setArrayOfMultipartFormFiles(value reflect.Value, field reflect.StructField, files []*multipart.FileHeader) (isSetted bool, err error) { | ||||
| 	if value.Len() != len(files) { | ||||
| 		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 | ||||
| 		} | ||||
| 	} | ||||
| 	return true, nil | ||||
| } | ||||
							
								
								
									
										36
									
								
								vendor/github.com/gin-gonic/gin/binding/protobuf.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/gin-gonic/gin/binding/protobuf.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| // 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 ( | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| ) | ||||
| 
 | ||||
| type protobufBinding struct{} | ||||
| 
 | ||||
| func (protobufBinding) Name() string { | ||||
| 	return "protobuf" | ||||
| } | ||||
| 
 | ||||
| func (b protobufBinding) Bind(req *http.Request, obj interface{}) error { | ||||
| 	buf, err := ioutil.ReadAll(req.Body) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return b.BindBody(buf, obj) | ||||
| } | ||||
| 
 | ||||
| func (protobufBinding) BindBody(body []byte, obj interface{}) error { | ||||
| 	if err := proto.Unmarshal(body, obj.(proto.Message)); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// Here it's same to return validate(obj), but util now we can't add | ||||
| 	// `binding:""` to the struct which automatically generate by gen-proto | ||||
| 	return nil | ||||
| 	// return validate(obj) | ||||
| } | ||||
							
								
								
									
										21
									
								
								vendor/github.com/gin-gonic/gin/binding/query.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/gin-gonic/gin/binding/query.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| // 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. | ||||
| 
 | ||||
| package binding | ||||
| 
 | ||||
| import "net/http" | ||||
| 
 | ||||
| type queryBinding struct{} | ||||
| 
 | ||||
| func (queryBinding) Name() string { | ||||
| 	return "query" | ||||
| } | ||||
| 
 | ||||
| func (queryBinding) Bind(req *http.Request, obj interface{}) error { | ||||
| 	values := req.URL.Query() | ||||
| 	if err := mapForm(obj, values); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return validate(obj) | ||||
| } | ||||
							
								
								
									
										18
									
								
								vendor/github.com/gin-gonic/gin/binding/uri.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/gin-gonic/gin/binding/uri.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| // 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 binding | ||||
| 
 | ||||
| type uriBinding struct{} | ||||
| 
 | ||||
| func (uriBinding) Name() string { | ||||
| 	return "uri" | ||||
| } | ||||
| 
 | ||||
| func (uriBinding) BindUri(m map[string][]string, obj interface{}) error { | ||||
| 	if err := mapUri(obj, m); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return validate(obj) | ||||
| } | ||||
							
								
								
									
										33
									
								
								vendor/github.com/gin-gonic/gin/binding/xml.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/gin-gonic/gin/binding/xml.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| // 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 ( | ||||
| 	"bytes" | ||||
| 	"encoding/xml" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| type xmlBinding struct{} | ||||
| 
 | ||||
| func (xmlBinding) Name() string { | ||||
| 	return "xml" | ||||
| } | ||||
| 
 | ||||
| func (xmlBinding) Bind(req *http.Request, obj interface{}) error { | ||||
| 	return decodeXML(req.Body, obj) | ||||
| } | ||||
| 
 | ||||
| func (xmlBinding) BindBody(body []byte, obj interface{}) error { | ||||
| 	return decodeXML(bytes.NewReader(body), obj) | ||||
| } | ||||
| func decodeXML(r io.Reader, obj interface{}) error { | ||||
| 	decoder := xml.NewDecoder(r) | ||||
| 	if err := decoder.Decode(obj); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return validate(obj) | ||||
| } | ||||
							
								
								
									
										35
									
								
								vendor/github.com/gin-gonic/gin/binding/yaml.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								vendor/github.com/gin-gonic/gin/binding/yaml.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| // 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 binding | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"gopkg.in/yaml.v2" | ||||
| ) | ||||
| 
 | ||||
| type yamlBinding struct{} | ||||
| 
 | ||||
| func (yamlBinding) Name() string { | ||||
| 	return "yaml" | ||||
| } | ||||
| 
 | ||||
| func (yamlBinding) Bind(req *http.Request, obj interface{}) error { | ||||
| 	return decodeYAML(req.Body, obj) | ||||
| } | ||||
| 
 | ||||
| func (yamlBinding) BindBody(body []byte, obj interface{}) error { | ||||
| 	return decodeYAML(bytes.NewReader(body), obj) | ||||
| } | ||||
| 
 | ||||
| func decodeYAML(r io.Reader, obj interface{}) error { | ||||
| 	decoder := yaml.NewDecoder(r) | ||||
| 	if err := decoder.Decode(obj); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return validate(obj) | ||||
| } | ||||
							
								
								
									
										5
									
								
								vendor/github.com/gin-gonic/gin/codecov.yml
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/gin-gonic/gin/codecov.yml
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| coverage: | ||||
|   notify: | ||||
|     gitter: | ||||
|       default: | ||||
|         url: https://webhooks.gitter.im/e/d90dcdeeab2f1e357165 | ||||
							
								
								
									
										1198
									
								
								vendor/github.com/gin-gonic/gin/context.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1198
									
								
								vendor/github.com/gin-gonic/gin/context.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										12
									
								
								vendor/github.com/gin-gonic/gin/context_appengine.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/gin-gonic/gin/context_appengine.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build appengine | ||||
| // +build appengine | ||||
| 
 | ||||
| package gin | ||||
| 
 | ||||
| func init() { | ||||
| 	defaultPlatform = PlatformGoogleAppEngine | ||||
| } | ||||
							
								
								
									
										101
									
								
								vendor/github.com/gin-gonic/gin/debug.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								vendor/github.com/gin-gonic/gin/debug.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,101 @@ | |||
| // 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 ( | ||||
| 	"fmt" | ||||
| 	"html/template" | ||||
| 	"runtime" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| const ginSupportMinGoVer = 13 | ||||
| 
 | ||||
| // IsDebugging returns true if the framework is running in debug mode. | ||||
| // Use SetMode(gin.ReleaseMode) to disable debug mode. | ||||
| func IsDebugging() bool { | ||||
| 	return ginMode == debugCode | ||||
| } | ||||
| 
 | ||||
| // DebugPrintRouteFunc indicates debug log output format. | ||||
| var DebugPrintRouteFunc func(httpMethod, absolutePath, handlerName string, nuHandlers int) | ||||
| 
 | ||||
| func debugPrintRoute(httpMethod, absolutePath string, handlers HandlersChain) { | ||||
| 	if IsDebugging() { | ||||
| 		nuHandlers := len(handlers) | ||||
| 		handlerName := nameOfFunction(handlers.Last()) | ||||
| 		if DebugPrintRouteFunc == nil { | ||||
| 			debugPrint("%-6s %-25s --> %s (%d handlers)\n", httpMethod, absolutePath, handlerName, nuHandlers) | ||||
| 		} else { | ||||
| 			DebugPrintRouteFunc(httpMethod, absolutePath, handlerName, nuHandlers) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func debugPrintLoadTemplate(tmpl *template.Template) { | ||||
| 	if IsDebugging() { | ||||
| 		var buf strings.Builder | ||||
| 		for _, tmpl := range tmpl.Templates() { | ||||
| 			buf.WriteString("\t- ") | ||||
| 			buf.WriteString(tmpl.Name()) | ||||
| 			buf.WriteString("\n") | ||||
| 		} | ||||
| 		debugPrint("Loaded HTML Templates (%d): \n%s\n", len(tmpl.Templates()), buf.String()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func debugPrint(format string, values ...interface{}) { | ||||
| 	if IsDebugging() { | ||||
| 		if !strings.HasSuffix(format, "\n") { | ||||
| 			format += "\n" | ||||
| 		} | ||||
| 		fmt.Fprintf(DefaultWriter, "[GIN-debug] "+format, values...) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func getMinVer(v string) (uint64, error) { | ||||
| 	first := strings.IndexByte(v, '.') | ||||
| 	last := strings.LastIndexByte(v, '.') | ||||
| 	if first == last { | ||||
| 		return strconv.ParseUint(v[first+1:], 10, 64) | ||||
| 	} | ||||
| 	return strconv.ParseUint(v[first+1:last], 10, 64) | ||||
| } | ||||
| 
 | ||||
| func debugPrintWARNINGDefault() { | ||||
| 	if v, e := getMinVer(runtime.Version()); e == nil && v <= ginSupportMinGoVer { | ||||
| 		debugPrint(`[WARNING] Now Gin requires Go 1.13+. | ||||
| 
 | ||||
| `) | ||||
| 	} | ||||
| 	debugPrint(`[WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached. | ||||
| 
 | ||||
| `) | ||||
| } | ||||
| 
 | ||||
| func debugPrintWARNINGNew() { | ||||
| 	debugPrint(`[WARNING] Running in "debug" mode. Switch to "release" mode in production. | ||||
|  - using env:	export GIN_MODE=release | ||||
|  - using code:	gin.SetMode(gin.ReleaseMode) | ||||
| 
 | ||||
| `) | ||||
| } | ||||
| 
 | ||||
| func debugPrintWARNINGSetHTMLTemplate() { | ||||
| 	debugPrint(`[WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called | ||||
| at initialization. ie. before any route is registered or the router is listening in a socket: | ||||
| 
 | ||||
| 	router := gin.Default() | ||||
| 	router.SetHTMLTemplate(template) // << good place | ||||
| 
 | ||||
| `) | ||||
| } | ||||
| 
 | ||||
| func debugPrintError(err error) { | ||||
| 	if err != nil && IsDebugging() { | ||||
| 		fmt.Fprintf(DefaultErrorWriter, "[GIN-debug] [ERROR] %v\n", err) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										21
									
								
								vendor/github.com/gin-gonic/gin/deprecated.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/gin-gonic/gin/deprecated.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| // 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 ( | ||||
| 	"log" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin/binding" | ||||
| ) | ||||
| 
 | ||||
| // 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 { | ||||
| 	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 | ||||
| 	ShouldBindWith() if you need to manage the error.`) | ||||
| 	return c.MustBindWith(obj, b) | ||||
| } | ||||
							
								
								
									
										6
									
								
								vendor/github.com/gin-gonic/gin/doc.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/gin-gonic/gin/doc.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| /* | ||||
| Package gin implements a HTTP web framework called gin. | ||||
| 
 | ||||
| See https://gin-gonic.com/ for more information about gin. | ||||
| */ | ||||
| package gin // import "github.com/gin-gonic/gin" | ||||
							
								
								
									
										174
									
								
								vendor/github.com/gin-gonic/gin/errors.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								vendor/github.com/gin-gonic/gin/errors.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,174 @@ | |||
| // 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 ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin/internal/json" | ||||
| ) | ||||
| 
 | ||||
| // ErrorType is an unsigned 64-bit error code as defined in the gin spec. | ||||
| type ErrorType uint64 | ||||
| 
 | ||||
| const ( | ||||
| 	// ErrorTypeBind is used when Context.Bind() fails. | ||||
| 	ErrorTypeBind ErrorType = 1 << 63 | ||||
| 	// ErrorTypeRender is used when Context.Render() fails. | ||||
| 	ErrorTypeRender ErrorType = 1 << 62 | ||||
| 	// ErrorTypePrivate indicates a private error. | ||||
| 	ErrorTypePrivate ErrorType = 1 << 0 | ||||
| 	// ErrorTypePublic indicates a public error. | ||||
| 	ErrorTypePublic ErrorType = 1 << 1 | ||||
| 	// ErrorTypeAny indicates any other error. | ||||
| 	ErrorTypeAny ErrorType = 1<<64 - 1 | ||||
| 	// ErrorTypeNu indicates any other error. | ||||
| 	ErrorTypeNu = 2 | ||||
| ) | ||||
| 
 | ||||
| // Error represents a error's specification. | ||||
| type Error struct { | ||||
| 	Err  error | ||||
| 	Type ErrorType | ||||
| 	Meta interface{} | ||||
| } | ||||
| 
 | ||||
| type errorMsgs []*Error | ||||
| 
 | ||||
| var _ error = &Error{} | ||||
| 
 | ||||
| // SetType sets the error's type. | ||||
| func (msg *Error) SetType(flags ErrorType) *Error { | ||||
| 	msg.Type = flags | ||||
| 	return msg | ||||
| } | ||||
| 
 | ||||
| // SetMeta sets the error's meta data. | ||||
| func (msg *Error) SetMeta(data interface{}) *Error { | ||||
| 	msg.Meta = data | ||||
| 	return msg | ||||
| } | ||||
| 
 | ||||
| // JSON creates a properly formatted JSON | ||||
| func (msg *Error) JSON() interface{} { | ||||
| 	jsonData := H{} | ||||
| 	if msg.Meta != nil { | ||||
| 		value := reflect.ValueOf(msg.Meta) | ||||
| 		switch value.Kind() { | ||||
| 		case reflect.Struct: | ||||
| 			return msg.Meta | ||||
| 		case reflect.Map: | ||||
| 			for _, key := range value.MapKeys() { | ||||
| 				jsonData[key.String()] = value.MapIndex(key).Interface() | ||||
| 			} | ||||
| 		default: | ||||
| 			jsonData["meta"] = msg.Meta | ||||
| 		} | ||||
| 	} | ||||
| 	if _, ok := jsonData["error"]; !ok { | ||||
| 		jsonData["error"] = msg.Error() | ||||
| 	} | ||||
| 	return jsonData | ||||
| } | ||||
| 
 | ||||
| // MarshalJSON implements the json.Marshaller interface. | ||||
| func (msg *Error) MarshalJSON() ([]byte, error) { | ||||
| 	return json.Marshal(msg.JSON()) | ||||
| } | ||||
| 
 | ||||
| // Error implements the error interface. | ||||
| func (msg Error) Error() string { | ||||
| 	return msg.Err.Error() | ||||
| } | ||||
| 
 | ||||
| // IsType judges one error. | ||||
| func (msg *Error) IsType(flags ErrorType) bool { | ||||
| 	return (msg.Type & flags) > 0 | ||||
| } | ||||
| 
 | ||||
| // Unwrap returns the wrapped error, to allow interoperability with errors.Is(), errors.As() and errors.Unwrap() | ||||
| func (msg *Error) Unwrap() error { | ||||
| 	return msg.Err | ||||
| } | ||||
| 
 | ||||
| // ByType returns a readonly copy filtered the byte. | ||||
| // ie ByType(gin.ErrorTypePublic) returns a slice of errors with type=ErrorTypePublic. | ||||
| func (a errorMsgs) ByType(typ ErrorType) errorMsgs { | ||||
| 	if len(a) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if typ == ErrorTypeAny { | ||||
| 		return a | ||||
| 	} | ||||
| 	var result errorMsgs | ||||
| 	for _, msg := range a { | ||||
| 		if msg.IsType(typ) { | ||||
| 			result = append(result, msg) | ||||
| 		} | ||||
| 	} | ||||
| 	return result | ||||
| } | ||||
| 
 | ||||
| // Last returns the last error in the slice. It returns nil if the array is empty. | ||||
| // Shortcut for errors[len(errors)-1]. | ||||
| func (a errorMsgs) Last() *Error { | ||||
| 	if length := len(a); length > 0 { | ||||
| 		return a[length-1] | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Errors returns an array will all the error messages. | ||||
| // Example: | ||||
| // 		c.Error(errors.New("first")) | ||||
| // 		c.Error(errors.New("second")) | ||||
| // 		c.Error(errors.New("third")) | ||||
| // 		c.Errors.Errors() // == []string{"first", "second", "third"} | ||||
| func (a errorMsgs) Errors() []string { | ||||
| 	if len(a) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	errorStrings := make([]string, len(a)) | ||||
| 	for i, err := range a { | ||||
| 		errorStrings[i] = err.Error() | ||||
| 	} | ||||
| 	return errorStrings | ||||
| } | ||||
| 
 | ||||
| func (a errorMsgs) JSON() interface{} { | ||||
| 	switch length := len(a); length { | ||||
| 	case 0: | ||||
| 		return nil | ||||
| 	case 1: | ||||
| 		return a.Last().JSON() | ||||
| 	default: | ||||
| 		jsonData := make([]interface{}, length) | ||||
| 		for i, err := range a { | ||||
| 			jsonData[i] = err.JSON() | ||||
| 		} | ||||
| 		return jsonData | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // MarshalJSON implements the json.Marshaller interface. | ||||
| func (a errorMsgs) MarshalJSON() ([]byte, error) { | ||||
| 	return json.Marshal(a.JSON()) | ||||
| } | ||||
| 
 | ||||
| func (a errorMsgs) String() string { | ||||
| 	if len(a) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	var buffer strings.Builder | ||||
| 	for i, msg := range a { | ||||
| 		fmt.Fprintf(&buffer, "Error #%02d: %s\n", i+1, msg.Err) | ||||
| 		if msg.Meta != nil { | ||||
| 			fmt.Fprintf(&buffer, "     Meta: %v\n", msg.Meta) | ||||
| 		} | ||||
| 	} | ||||
| 	return buffer.String() | ||||
| } | ||||
							
								
								
									
										45
									
								
								vendor/github.com/gin-gonic/gin/fs.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								vendor/github.com/gin-gonic/gin/fs.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| // 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. | ||||
| 
 | ||||
| package gin | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| ) | ||||
| 
 | ||||
| type onlyFilesFS struct { | ||||
| 	fs http.FileSystem | ||||
| } | ||||
| 
 | ||||
| type neuteredReaddirFile struct { | ||||
| 	http.File | ||||
| } | ||||
| 
 | ||||
| // 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. | ||||
| func Dir(root string, listDirectory bool) http.FileSystem { | ||||
| 	fs := http.Dir(root) | ||||
| 	if listDirectory { | ||||
| 		return fs | ||||
| 	} | ||||
| 	return &onlyFilesFS{fs} | ||||
| } | ||||
| 
 | ||||
| // Open conforms to http.Filesystem. | ||||
| func (fs onlyFilesFS) Open(name string) (http.File, error) { | ||||
| 	f, err := fs.fs.Open(name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return neuteredReaddirFile{f}, nil | ||||
| } | ||||
| 
 | ||||
| // Readdir overrides the http.File default implementation. | ||||
| func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) { | ||||
| 	// this disables directory listing | ||||
| 	return nil, nil | ||||
| } | ||||
							
								
								
									
										626
									
								
								vendor/github.com/gin-gonic/gin/gin.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										626
									
								
								vendor/github.com/gin-gonic/gin/gin.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,626 @@ | |||
| // 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 ( | ||||
| 	"fmt" | ||||
| 	"html/template" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin/internal/bytesconv" | ||||
| 	"github.com/gin-gonic/gin/render" | ||||
| ) | ||||
| 
 | ||||
| const defaultMultipartMemory = 32 << 20 // 32 MB | ||||
| 
 | ||||
| var ( | ||||
| 	default404Body = []byte("404 page not found") | ||||
| 	default405Body = []byte("405 method not allowed") | ||||
| ) | ||||
| 
 | ||||
| var defaultPlatform string | ||||
| 
 | ||||
| // HandlerFunc defines the handler used by gin middleware as return value. | ||||
| type HandlerFunc func(*Context) | ||||
| 
 | ||||
| // HandlersChain defines a HandlerFunc array. | ||||
| type HandlersChain []HandlerFunc | ||||
| 
 | ||||
| // Last returns the last handler in the chain. ie. the last handler is the main one. | ||||
| func (c HandlersChain) Last() HandlerFunc { | ||||
| 	if length := len(c); length > 0 { | ||||
| 		return c[length-1] | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // RouteInfo represents a request route's specification which contains method and path and its handler. | ||||
| type RouteInfo struct { | ||||
| 	Method      string | ||||
| 	Path        string | ||||
| 	Handler     string | ||||
| 	HandlerFunc HandlerFunc | ||||
| } | ||||
| 
 | ||||
| // RoutesInfo defines a RouteInfo array. | ||||
| type RoutesInfo []RouteInfo | ||||
| 
 | ||||
| // Trusted platforms | ||||
| const ( | ||||
| 	// When running on Google App Engine. Trust X-Appengine-Remote-Addr | ||||
| 	// for determining the client's IP | ||||
| 	PlatformGoogleAppEngine = "google-app-engine" | ||||
| 	// When using Cloudflare's CDN. Trust CF-Connecting-IP for determining | ||||
| 	// the client's IP | ||||
| 	PlatformCloudflare = "cloudflare" | ||||
| ) | ||||
| 
 | ||||
| // Engine is the framework's instance, it contains the muxer, middleware and configuration settings. | ||||
| // Create an instance of Engine, by using New() or Default() | ||||
| type Engine struct { | ||||
| 	RouterGroup | ||||
| 
 | ||||
| 	// 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 | ||||
| 	// 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. | ||||
| 	// If a handle can be found for this route, the router makes a redirection | ||||
| 	// to the corrected path with status code 301 for GET requests and 307 for | ||||
| 	// all other request methods. | ||||
| 	// For example /FOO and /..//Foo could be redirected to /foo. | ||||
| 	// RedirectTrailingSlash is independent of this option. | ||||
| 	RedirectFixedPath bool | ||||
| 
 | ||||
| 	// 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. | ||||
| 	// If no other Method is allowed, the request is delegated to the NotFound | ||||
| 	// handler. | ||||
| 	HandleMethodNotAllowed bool | ||||
| 
 | ||||
| 	// 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 | ||||
| 	// #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 bool | ||||
| 
 | ||||
| 	// 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 | ||||
| 
 | ||||
| 	// RemoveExtraSlash a parameter can be parsed from the URL even with extra slashes. | ||||
| 	// See the PR #1817 and issue #1644 | ||||
| 	RemoveExtraSlash bool | ||||
| 
 | ||||
| 	// 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 `(*gin.Engine).TrustedProxies`. | ||||
| 	RemoteIPHeaders []string | ||||
| 
 | ||||
| 	// List of network origins (IPv4 addresses, IPv4 CIDRs, IPv6 addresses or | ||||
| 	// IPv6 CIDRs) from which to trust request's headers that contain | ||||
| 	// alternative client IP when `(*gin.Engine).ForwardedByClientIP` is | ||||
| 	// `true`. | ||||
| 	TrustedProxies []string | ||||
| 
 | ||||
| 	// 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 | ||||
| 	// method call. | ||||
| 	MaxMultipartMemory int64 | ||||
| 
 | ||||
| 	delims           render.Delims | ||||
| 	secureJSONPrefix string | ||||
| 	HTMLRender       render.HTMLRender | ||||
| 	FuncMap          template.FuncMap | ||||
| 	allNoRoute       HandlersChain | ||||
| 	allNoMethod      HandlersChain | ||||
| 	noRoute          HandlersChain | ||||
| 	noMethod         HandlersChain | ||||
| 	pool             sync.Pool | ||||
| 	trees            methodTrees | ||||
| 	maxParams        uint16 | ||||
| 	trustedCIDRs     []*net.IPNet | ||||
| } | ||||
| 
 | ||||
| var _ IRouter = &Engine{} | ||||
| 
 | ||||
| // New returns a new blank Engine instance without any middleware attached. | ||||
| // By default the configuration is: | ||||
| // - RedirectTrailingSlash:  true | ||||
| // - RedirectFixedPath:      false | ||||
| // - HandleMethodNotAllowed: false | ||||
| // - ForwardedByClientIP:    true | ||||
| // - UseRawPath:             false | ||||
| // - UnescapePathValues:     true | ||||
| func New() *Engine { | ||||
| 	debugPrintWARNINGNew() | ||||
| 	engine := &Engine{ | ||||
| 		RouterGroup: RouterGroup{ | ||||
| 			Handlers: nil, | ||||
| 			basePath: "/", | ||||
| 			root:     true, | ||||
| 		}, | ||||
| 		FuncMap:                template.FuncMap{}, | ||||
| 		RedirectTrailingSlash:  true, | ||||
| 		RedirectFixedPath:      false, | ||||
| 		HandleMethodNotAllowed: false, | ||||
| 		ForwardedByClientIP:    true, | ||||
| 		RemoteIPHeaders:        []string{"X-Forwarded-For", "X-Real-IP"}, | ||||
| 		TrustedProxies:         []string{"0.0.0.0/0"}, | ||||
| 		TrustedPlatform:        defaultPlatform, | ||||
| 		UseRawPath:             false, | ||||
| 		RemoveExtraSlash:       false, | ||||
| 		UnescapePathValues:     true, | ||||
| 		MaxMultipartMemory:     defaultMultipartMemory, | ||||
| 		trees:                  make(methodTrees, 0, 9), | ||||
| 		delims:                 render.Delims{Left: "{{", Right: "}}"}, | ||||
| 		secureJSONPrefix:       "while(1);", | ||||
| 	} | ||||
| 	engine.RouterGroup.engine = engine | ||||
| 	engine.pool.New = func() interface{} { | ||||
| 		return engine.allocateContext() | ||||
| 	} | ||||
| 	return engine | ||||
| } | ||||
| 
 | ||||
| // Default returns an Engine instance with the Logger and Recovery middleware already attached. | ||||
| func Default() *Engine { | ||||
| 	debugPrintWARNINGDefault() | ||||
| 	engine := New() | ||||
| 	engine.Use(Logger(), Recovery()) | ||||
| 	return engine | ||||
| } | ||||
| 
 | ||||
| func (engine *Engine) allocateContext() *Context { | ||||
| 	v := make(Params, 0, engine.maxParams) | ||||
| 	return &Context{engine: engine, params: &v} | ||||
| } | ||||
| 
 | ||||
| // Delims sets template left and right delims and returns a Engine instance. | ||||
| func (engine *Engine) Delims(left, right string) *Engine { | ||||
| 	engine.delims = render.Delims{Left: left, Right: right} | ||||
| 	return engine | ||||
| } | ||||
| 
 | ||||
| // SecureJsonPrefix sets the secureJSONPrefix used in Context.SecureJSON. | ||||
| func (engine *Engine) SecureJsonPrefix(prefix string) *Engine { | ||||
| 	engine.secureJSONPrefix = prefix | ||||
| 	return engine | ||||
| } | ||||
| 
 | ||||
| // LoadHTMLGlob loads HTML files identified by glob pattern | ||||
| // and associates the result with HTML renderer. | ||||
| func (engine *Engine) LoadHTMLGlob(pattern string) { | ||||
| 	left := engine.delims.Left | ||||
| 	right := engine.delims.Right | ||||
| 	templ := template.Must(template.New("").Delims(left, right).Funcs(engine.FuncMap).ParseGlob(pattern)) | ||||
| 
 | ||||
| 	if IsDebugging() { | ||||
| 		debugPrintLoadTemplate(templ) | ||||
| 		engine.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: engine.FuncMap, Delims: engine.delims} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	engine.SetHTMLTemplate(templ) | ||||
| } | ||||
| 
 | ||||
| // LoadHTMLFiles loads a slice of HTML files | ||||
| // and associates the result with HTML renderer. | ||||
| func (engine *Engine) LoadHTMLFiles(files ...string) { | ||||
| 	if IsDebugging() { | ||||
| 		engine.HTMLRender = render.HTMLDebug{Files: files, FuncMap: engine.FuncMap, Delims: engine.delims} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).Funcs(engine.FuncMap).ParseFiles(files...)) | ||||
| 	engine.SetHTMLTemplate(templ) | ||||
| } | ||||
| 
 | ||||
| // SetHTMLTemplate associate a template with HTML renderer. | ||||
| func (engine *Engine) SetHTMLTemplate(templ *template.Template) { | ||||
| 	if len(engine.trees) > 0 { | ||||
| 		debugPrintWARNINGSetHTMLTemplate() | ||||
| 	} | ||||
| 
 | ||||
| 	engine.HTMLRender = render.HTMLProduction{Template: templ.Funcs(engine.FuncMap)} | ||||
| } | ||||
| 
 | ||||
| // SetFuncMap sets the FuncMap used for template.FuncMap. | ||||
| func (engine *Engine) SetFuncMap(funcMap template.FuncMap) { | ||||
| 	engine.FuncMap = funcMap | ||||
| } | ||||
| 
 | ||||
| // NoRoute adds handlers for NoRoute. It return a 404 code by default. | ||||
| func (engine *Engine) NoRoute(handlers ...HandlerFunc) { | ||||
| 	engine.noRoute = handlers | ||||
| 	engine.rebuild404Handlers() | ||||
| } | ||||
| 
 | ||||
| // NoMethod sets the handlers called when... TODO. | ||||
| func (engine *Engine) NoMethod(handlers ...HandlerFunc) { | ||||
| 	engine.noMethod = handlers | ||||
| 	engine.rebuild405Handlers() | ||||
| } | ||||
| 
 | ||||
| // Use attaches a global middleware to the router. ie. the middleware attached though 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 { | ||||
| 	engine.RouterGroup.Use(middleware...) | ||||
| 	engine.rebuild404Handlers() | ||||
| 	engine.rebuild405Handlers() | ||||
| 	return engine | ||||
| } | ||||
| 
 | ||||
| func (engine *Engine) rebuild404Handlers() { | ||||
| 	engine.allNoRoute = engine.combineHandlers(engine.noRoute) | ||||
| } | ||||
| 
 | ||||
| func (engine *Engine) rebuild405Handlers() { | ||||
| 	engine.allNoMethod = engine.combineHandlers(engine.noMethod) | ||||
| } | ||||
| 
 | ||||
| func (engine *Engine) addRoute(method, path string, handlers HandlersChain) { | ||||
| 	assert1(path[0] == '/', "path must begin with '/'") | ||||
| 	assert1(method != "", "HTTP method can not be empty") | ||||
| 	assert1(len(handlers) > 0, "there must be at least one handler") | ||||
| 
 | ||||
| 	debugPrintRoute(method, path, handlers) | ||||
| 
 | ||||
| 	root := engine.trees.get(method) | ||||
| 	if root == nil { | ||||
| 		root = new(node) | ||||
| 		root.fullPath = "/" | ||||
| 		engine.trees = append(engine.trees, methodTree{method: method, root: root}) | ||||
| 	} | ||||
| 	root.addRoute(path, handlers) | ||||
| 
 | ||||
| 	// Update maxParams | ||||
| 	if paramsCount := countParams(path); paramsCount > engine.maxParams { | ||||
| 		engine.maxParams = paramsCount | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Routes returns a slice of registered routes, including some useful information, such as: | ||||
| // the http method, path and the handler name. | ||||
| func (engine *Engine) Routes() (routes RoutesInfo) { | ||||
| 	for _, tree := range engine.trees { | ||||
| 		routes = iterate("", tree.method, routes, tree.root) | ||||
| 	} | ||||
| 	return routes | ||||
| } | ||||
| 
 | ||||
| func iterate(path, method string, routes RoutesInfo, root *node) RoutesInfo { | ||||
| 	path += root.path | ||||
| 	if len(root.handlers) > 0 { | ||||
| 		handlerFunc := root.handlers.Last() | ||||
| 		routes = append(routes, RouteInfo{ | ||||
| 			Method:      method, | ||||
| 			Path:        path, | ||||
| 			Handler:     nameOfFunction(handlerFunc), | ||||
| 			HandlerFunc: handlerFunc, | ||||
| 		}) | ||||
| 	} | ||||
| 	for _, child := range root.children { | ||||
| 		routes = iterate(path, method, routes, child) | ||||
| 	} | ||||
| 	return routes | ||||
| } | ||||
| 
 | ||||
| // Run attaches the router to a http.Server and starts listening and serving HTTP requests. | ||||
| // It is a shortcut for http.ListenAndServe(addr, router) | ||||
| // Note: this method will block the calling goroutine indefinitely unless an error happens. | ||||
| func (engine *Engine) Run(addr ...string) (err error) { | ||||
| 	defer func() { debugPrintError(err) }() | ||||
| 
 | ||||
| 	err = engine.parseTrustedProxies() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	address := resolveAddress(addr) | ||||
| 	debugPrint("Listening and serving HTTP on %s\n", address) | ||||
| 	err = http.ListenAndServe(address, engine) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (engine *Engine) prepareTrustedCIDRs() ([]*net.IPNet, error) { | ||||
| 	if engine.TrustedProxies == nil { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	cidr := make([]*net.IPNet, 0, len(engine.TrustedProxies)) | ||||
| 	for _, trustedProxy := range engine.TrustedProxies { | ||||
| 		if !strings.Contains(trustedProxy, "/") { | ||||
| 			ip := parseIP(trustedProxy) | ||||
| 			if ip == nil { | ||||
| 				return cidr, &net.ParseError{Type: "IP address", Text: trustedProxy} | ||||
| 			} | ||||
| 
 | ||||
| 			switch len(ip) { | ||||
| 			case net.IPv4len: | ||||
| 				trustedProxy += "/32" | ||||
| 			case net.IPv6len: | ||||
| 				trustedProxy += "/128" | ||||
| 			} | ||||
| 		} | ||||
| 		_, cidrNet, err := net.ParseCIDR(trustedProxy) | ||||
| 		if err != nil { | ||||
| 			return cidr, err | ||||
| 		} | ||||
| 		cidr = append(cidr, cidrNet) | ||||
| 	} | ||||
| 	return cidr, nil | ||||
| } | ||||
| 
 | ||||
| // SetTrustedProxies  set Engine.TrustedProxies | ||||
| func (engine *Engine) SetTrustedProxies(trustedProxies []string) error { | ||||
| 	engine.TrustedProxies = trustedProxies | ||||
| 	return engine.parseTrustedProxies() | ||||
| } | ||||
| 
 | ||||
| // parseTrustedProxies parse Engine.TrustedProxies to Engine.trustedCIDRs | ||||
| func (engine *Engine) parseTrustedProxies() error { | ||||
| 	trustedCIDRs, err := engine.prepareTrustedCIDRs() | ||||
| 	engine.trustedCIDRs = trustedCIDRs | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // 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 { | ||||
| 	parsedIP := net.ParseIP(ip) | ||||
| 
 | ||||
| 	if ipv4 := parsedIP.To4(); ipv4 != nil { | ||||
| 		// return ip in a 4-byte representation | ||||
| 		return ipv4 | ||||
| 	} | ||||
| 
 | ||||
| 	// return ip in a 16-byte representation or nil | ||||
| 	return parsedIP | ||||
| } | ||||
| 
 | ||||
| // RunTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests. | ||||
| // It is a shortcut for http.ListenAndServeTLS(addr, certFile, keyFile, router) | ||||
| // Note: this method will block the calling goroutine indefinitely unless an error happens. | ||||
| func (engine *Engine) RunTLS(addr, certFile, keyFile string) (err error) { | ||||
| 	debugPrint("Listening and serving HTTPS on %s\n", addr) | ||||
| 	defer func() { debugPrintError(err) }() | ||||
| 
 | ||||
| 	err = engine.parseTrustedProxies() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	err = http.ListenAndServeTLS(addr, certFile, keyFile, engine) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // RunUnix attaches the router to a http.Server and starts listening and serving HTTP requests | ||||
| // through the specified unix socket (ie. 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) | ||||
| 	defer func() { debugPrintError(err) }() | ||||
| 
 | ||||
| 	err = engine.parseTrustedProxies() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	listener, err := net.Listen("unix", file) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	defer listener.Close() | ||||
| 	defer os.Remove(file) | ||||
| 
 | ||||
| 	err = http.Serve(listener, engine) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // RunFd attaches the router to a http.Server and starts listening and serving HTTP requests | ||||
| // through the specified file descriptor. | ||||
| // Note: this method will block the calling goroutine indefinitely unless an error happens. | ||||
| func (engine *Engine) RunFd(fd int) (err error) { | ||||
| 	debugPrint("Listening and serving HTTP on fd@%d", fd) | ||||
| 	defer func() { debugPrintError(err) }() | ||||
| 
 | ||||
| 	err = engine.parseTrustedProxies() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	f := os.NewFile(uintptr(fd), fmt.Sprintf("fd@%d", fd)) | ||||
| 	listener, err := net.FileListener(f) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	defer listener.Close() | ||||
| 	err = engine.RunListener(listener) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // RunListener attaches the router to a http.Server and starts listening and serving HTTP requests | ||||
| // through the specified net.Listener | ||||
| func (engine *Engine) RunListener(listener net.Listener) (err error) { | ||||
| 	debugPrint("Listening and serving HTTP on listener what's bind with address@%s", listener.Addr()) | ||||
| 	defer func() { debugPrintError(err) }() | ||||
| 
 | ||||
| 	err = engine.parseTrustedProxies() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	err = http.Serve(listener, engine) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // ServeHTTP conforms to the http.Handler interface. | ||||
| func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||||
| 	c := engine.pool.Get().(*Context) | ||||
| 	c.writermem.reset(w) | ||||
| 	c.Request = req | ||||
| 	c.reset() | ||||
| 
 | ||||
| 	engine.handleHTTPRequest(c) | ||||
| 
 | ||||
| 	engine.pool.Put(c) | ||||
| } | ||||
| 
 | ||||
| // HandleContext re-enter 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. | ||||
| func (engine *Engine) HandleContext(c *Context) { | ||||
| 	oldIndexValue := c.index | ||||
| 	c.reset() | ||||
| 	engine.handleHTTPRequest(c) | ||||
| 
 | ||||
| 	c.index = oldIndexValue | ||||
| } | ||||
| 
 | ||||
| func (engine *Engine) handleHTTPRequest(c *Context) { | ||||
| 	httpMethod := c.Request.Method | ||||
| 	rPath := c.Request.URL.Path | ||||
| 	unescape := false | ||||
| 	if engine.UseRawPath && len(c.Request.URL.RawPath) > 0 { | ||||
| 		rPath = c.Request.URL.RawPath | ||||
| 		unescape = engine.UnescapePathValues | ||||
| 	} | ||||
| 
 | ||||
| 	if engine.RemoveExtraSlash { | ||||
| 		rPath = cleanPath(rPath) | ||||
| 	} | ||||
| 
 | ||||
| 	// Find root of the tree for the given HTTP method | ||||
| 	t := engine.trees | ||||
| 	for i, tl := 0, len(t); i < tl; i++ { | ||||
| 		if t[i].method != httpMethod { | ||||
| 			continue | ||||
| 		} | ||||
| 		root := t[i].root | ||||
| 		// Find route in tree | ||||
| 		value := root.getValue(rPath, c.params, unescape) | ||||
| 		if value.params != nil { | ||||
| 			c.Params = *value.params | ||||
| 		} | ||||
| 		if value.handlers != nil { | ||||
| 			c.handlers = value.handlers | ||||
| 			c.fullPath = value.fullPath | ||||
| 			c.Next() | ||||
| 			c.writermem.WriteHeaderNow() | ||||
| 			return | ||||
| 		} | ||||
| 		if httpMethod != http.MethodConnect && rPath != "/" { | ||||
| 			if value.tsr && engine.RedirectTrailingSlash { | ||||
| 				redirectTrailingSlash(c) | ||||
| 				return | ||||
| 			} | ||||
| 			if engine.RedirectFixedPath && redirectFixedPath(c, root, engine.RedirectFixedPath) { | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 		break | ||||
| 	} | ||||
| 
 | ||||
| 	if engine.HandleMethodNotAllowed { | ||||
| 		for _, tree := range engine.trees { | ||||
| 			if tree.method == httpMethod { | ||||
| 				continue | ||||
| 			} | ||||
| 			if value := tree.root.getValue(rPath, nil, unescape); value.handlers != nil { | ||||
| 				c.handlers = engine.allNoMethod | ||||
| 				serveError(c, http.StatusMethodNotAllowed, default405Body) | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	c.handlers = engine.allNoRoute | ||||
| 	serveError(c, http.StatusNotFound, default404Body) | ||||
| } | ||||
| 
 | ||||
| var mimePlain = []string{MIMEPlain} | ||||
| 
 | ||||
| func serveError(c *Context, code int, defaultMessage []byte) { | ||||
| 	c.writermem.status = code | ||||
| 	c.Next() | ||||
| 	if c.writermem.Written() { | ||||
| 		return | ||||
| 	} | ||||
| 	if c.writermem.Status() == code { | ||||
| 		c.writermem.Header()["Content-Type"] = mimePlain | ||||
| 		_, err := c.Writer.Write(defaultMessage) | ||||
| 		if err != nil { | ||||
| 			debugPrint("cannot write message to writer during serve error: %v", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	c.writermem.WriteHeaderNow() | ||||
| } | ||||
| 
 | ||||
| func redirectTrailingSlash(c *Context) { | ||||
| 	req := c.Request | ||||
| 	p := req.URL.Path | ||||
| 	if prefix := path.Clean(c.Request.Header.Get("X-Forwarded-Prefix")); prefix != "." { | ||||
| 		p = prefix + "/" + req.URL.Path | ||||
| 	} | ||||
| 	req.URL.Path = p + "/" | ||||
| 	if length := len(p); length > 1 && p[length-1] == '/' { | ||||
| 		req.URL.Path = p[:length-1] | ||||
| 	} | ||||
| 	redirectRequest(c) | ||||
| } | ||||
| 
 | ||||
| func redirectFixedPath(c *Context, root *node, trailingSlash bool) bool { | ||||
| 	req := c.Request | ||||
| 	rPath := req.URL.Path | ||||
| 
 | ||||
| 	if fixedPath, ok := root.findCaseInsensitivePath(cleanPath(rPath), trailingSlash); ok { | ||||
| 		req.URL.Path = bytesconv.BytesToString(fixedPath) | ||||
| 		redirectRequest(c) | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func redirectRequest(c *Context) { | ||||
| 	req := c.Request | ||||
| 	rPath := req.URL.Path | ||||
| 	rURL := req.URL.String() | ||||
| 
 | ||||
| 	code := http.StatusMovedPermanently // Permanent redirect, request with GET method | ||||
| 	if req.Method != http.MethodGet { | ||||
| 		code = http.StatusTemporaryRedirect | ||||
| 	} | ||||
| 	debugPrint("redirecting request %d: %s --> %s", code, rPath, rURL) | ||||
| 	http.Redirect(c.Writer, req, rURL, code) | ||||
| 	c.writermem.WriteHeaderNow() | ||||
| } | ||||
							
								
								
									
										15
									
								
								vendor/github.com/gin-gonic/gin/go.mod
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/gin-gonic/gin/go.mod
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| module github.com/gin-gonic/gin | ||||
| 
 | ||||
| go 1.13 | ||||
| 
 | ||||
| require ( | ||||
| 	github.com/gin-contrib/sse v0.1.0 | ||||
| 	github.com/go-playground/validator/v10 v10.6.1 | ||||
| 	github.com/goccy/go-json v0.5.1 | ||||
| 	github.com/golang/protobuf v1.3.3 | ||||
| 	github.com/json-iterator/go v1.1.9 | ||||
| 	github.com/mattn/go-isatty v0.0.12 | ||||
| 	github.com/stretchr/testify v1.4.0 | ||||
| 	github.com/ugorji/go/codec v1.2.6 | ||||
| 	gopkg.in/yaml.v2 v2.2.8 | ||||
| ) | ||||
							
								
								
									
										55
									
								
								vendor/github.com/gin-gonic/gin/go.sum
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								vendor/github.com/gin-gonic/gin/go.sum
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= | ||||
| github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= | ||||
| github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= | ||||
| github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= | ||||
| github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= | ||||
| github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= | ||||
| github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= | ||||
| github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= | ||||
| github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I= | ||||
| github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk= | ||||
| github.com/goccy/go-json v0.5.1 h1:R9UYTOUvo7eIY9aeDMZ4L6OVtHaSr1k2No9W6MKjXrA= | ||||
| github.com/goccy/go-json v0.5.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= | ||||
| github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= | ||||
| github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= | ||||
| github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | ||||
| github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= | ||||
| github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= | ||||
| github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= | ||||
| github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= | ||||
| github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= | ||||
| github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= | ||||
| github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= | ||||
| github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||
| github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= | ||||
| github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||
| github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | ||||
| github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | ||||
| github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= | ||||
| github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= | ||||
| github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= | ||||
| github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= | ||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||
| golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= | ||||
| golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
| golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= | ||||
| golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= | ||||
| golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | ||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= | ||||
| gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
							
								
								
									
										24
									
								
								vendor/github.com/gin-gonic/gin/internal/bytesconv/bytesconv.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/gin-gonic/gin/internal/bytesconv/bytesconv.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| // Copyright 2020 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 bytesconv | ||||
| 
 | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| // StringToBytes converts string to byte slice without a memory allocation. | ||||
| func StringToBytes(s string) []byte { | ||||
| 	return *(*[]byte)(unsafe.Pointer( | ||||
| 		&struct { | ||||
| 			string | ||||
| 			Cap int | ||||
| 		}{s, len(s)}, | ||||
| 	)) | ||||
| } | ||||
| 
 | ||||
| // BytesToString converts byte slice to string without a memory allocation. | ||||
| func BytesToString(b []byte) string { | ||||
| 	return *(*string)(unsafe.Pointer(&b)) | ||||
| } | ||||
							
								
								
									
										23
									
								
								vendor/github.com/gin-gonic/gin/internal/json/go_json.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/gin-gonic/gin/internal/json/go_json.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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 | ||||
| ) | ||||
							
								
								
									
										23
									
								
								vendor/github.com/gin-gonic/gin/internal/json/json.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/gin-gonic/gin/internal/json/json.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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 !jsoniter && !go_json | ||||
| // +build !jsoniter,!go_json | ||||
| 
 | ||||
| package json | ||||
| 
 | ||||
| import "encoding/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 | ||||
| ) | ||||
							
								
								
									
										24
									
								
								vendor/github.com/gin-gonic/gin/internal/json/jsoniter.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/gin-gonic/gin/internal/json/jsoniter.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| // 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 | ||||
| 
 | ||||
| package json | ||||
| 
 | ||||
| import jsoniter "github.com/json-iterator/go" | ||||
| 
 | ||||
| var ( | ||||
| 	json = jsoniter.ConfigCompatibleWithStandardLibrary | ||||
| 	// 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 | ||||
| ) | ||||
							
								
								
									
										270
									
								
								vendor/github.com/gin-gonic/gin/logger.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								vendor/github.com/gin-gonic/gin/logger.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,270 @@ | |||
| // 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 ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/mattn/go-isatty" | ||||
| ) | ||||
| 
 | ||||
| type consoleColorModeValue int | ||||
| 
 | ||||
| const ( | ||||
| 	autoColor consoleColorModeValue = iota | ||||
| 	disableColor | ||||
| 	forceColor | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	green   = "\033[97;42m" | ||||
| 	white   = "\033[90;47m" | ||||
| 	yellow  = "\033[90;43m" | ||||
| 	red     = "\033[97;41m" | ||||
| 	blue    = "\033[97;44m" | ||||
| 	magenta = "\033[97;45m" | ||||
| 	cyan    = "\033[97;46m" | ||||
| 	reset   = "\033[0m" | ||||
| ) | ||||
| 
 | ||||
| var consoleColorMode = autoColor | ||||
| 
 | ||||
| // LoggerConfig defines the config for Logger middleware. | ||||
| type LoggerConfig struct { | ||||
| 	// Optional. Default value is gin.defaultLogFormatter | ||||
| 	Formatter LogFormatter | ||||
| 
 | ||||
| 	// Output is a writer where logs are written. | ||||
| 	// Optional. Default value is gin.DefaultWriter. | ||||
| 	Output io.Writer | ||||
| 
 | ||||
| 	// SkipPaths is a url path array which logs are not written. | ||||
| 	// Optional. | ||||
| 	SkipPaths []string | ||||
| } | ||||
| 
 | ||||
| // LogFormatter gives the signature of the formatter function passed to LoggerWithFormatter | ||||
| type LogFormatter func(params LogFormatterParams) string | ||||
| 
 | ||||
| // LogFormatterParams is the structure any formatter will be handed when time to log comes | ||||
| type LogFormatterParams struct { | ||||
| 	Request *http.Request | ||||
| 
 | ||||
| 	// TimeStamp shows the time after the server returns a response. | ||||
| 	TimeStamp time.Time | ||||
| 	// StatusCode is HTTP response code. | ||||
| 	StatusCode int | ||||
| 	// Latency is how much time the server cost to process a certain request. | ||||
| 	Latency time.Duration | ||||
| 	// ClientIP equals Context's ClientIP method. | ||||
| 	ClientIP string | ||||
| 	// Method is the HTTP method given to the request. | ||||
| 	Method string | ||||
| 	// Path is a path the client requests. | ||||
| 	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 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{} | ||||
| } | ||||
| 
 | ||||
| // StatusCodeColor is the ANSI color for appropriately logging http status code to a terminal. | ||||
| func (p *LogFormatterParams) StatusCodeColor() string { | ||||
| 	code := p.StatusCode | ||||
| 
 | ||||
| 	switch { | ||||
| 	case code >= http.StatusOK && code < http.StatusMultipleChoices: | ||||
| 		return green | ||||
| 	case code >= http.StatusMultipleChoices && code < http.StatusBadRequest: | ||||
| 		return white | ||||
| 	case code >= http.StatusBadRequest && code < http.StatusInternalServerError: | ||||
| 		return yellow | ||||
| 	default: | ||||
| 		return red | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // MethodColor is the ANSI color for appropriately logging http method to a terminal. | ||||
| func (p *LogFormatterParams) MethodColor() string { | ||||
| 	method := p.Method | ||||
| 
 | ||||
| 	switch method { | ||||
| 	case http.MethodGet: | ||||
| 		return blue | ||||
| 	case http.MethodPost: | ||||
| 		return cyan | ||||
| 	case http.MethodPut: | ||||
| 		return yellow | ||||
| 	case http.MethodDelete: | ||||
| 		return red | ||||
| 	case http.MethodPatch: | ||||
| 		return green | ||||
| 	case http.MethodHead: | ||||
| 		return magenta | ||||
| 	case http.MethodOptions: | ||||
| 		return white | ||||
| 	default: | ||||
| 		return reset | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // ResetColor resets all escape attributes. | ||||
| func (p *LogFormatterParams) ResetColor() string { | ||||
| 	return reset | ||||
| } | ||||
| 
 | ||||
| // IsOutputColor indicates whether can colors be outputted to the log. | ||||
| func (p *LogFormatterParams) IsOutputColor() bool { | ||||
| 	return consoleColorMode == forceColor || (consoleColorMode == autoColor && p.isTerm) | ||||
| } | ||||
| 
 | ||||
| // defaultLogFormatter is the default log format function Logger middleware uses. | ||||
| var defaultLogFormatter = func(param LogFormatterParams) string { | ||||
| 	var statusColor, methodColor, resetColor string | ||||
| 	if param.IsOutputColor() { | ||||
| 		statusColor = param.StatusCodeColor() | ||||
| 		methodColor = param.MethodColor() | ||||
| 		resetColor = param.ResetColor() | ||||
| 	} | ||||
| 
 | ||||
| 	if param.Latency > time.Minute { | ||||
| 		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"), | ||||
| 		statusColor, param.StatusCode, resetColor, | ||||
| 		param.Latency, | ||||
| 		param.ClientIP, | ||||
| 		methodColor, param.Method, resetColor, | ||||
| 		param.Path, | ||||
| 		param.ErrorMessage, | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| // DisableConsoleColor disables color output in the console. | ||||
| func DisableConsoleColor() { | ||||
| 	consoleColorMode = disableColor | ||||
| } | ||||
| 
 | ||||
| // ForceConsoleColor force color output in the console. | ||||
| func ForceConsoleColor() { | ||||
| 	consoleColorMode = forceColor | ||||
| } | ||||
| 
 | ||||
| // ErrorLogger returns a handlerfunc for any error type. | ||||
| func ErrorLogger() HandlerFunc { | ||||
| 	return ErrorLoggerT(ErrorTypeAny) | ||||
| } | ||||
| 
 | ||||
| // ErrorLoggerT returns a handlerfunc for a given error type. | ||||
| func ErrorLoggerT(typ ErrorType) HandlerFunc { | ||||
| 	return func(c *Context) { | ||||
| 		c.Next() | ||||
| 		errors := c.Errors.ByType(typ) | ||||
| 		if len(errors) > 0 { | ||||
| 			c.JSON(-1, errors) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Logger instances a Logger middleware that will write the logs to gin.DefaultWriter. | ||||
| // By default gin.DefaultWriter = os.Stdout. | ||||
| func Logger() HandlerFunc { | ||||
| 	return LoggerWithConfig(LoggerConfig{}) | ||||
| } | ||||
| 
 | ||||
| // LoggerWithFormatter instance a Logger middleware with the specified log format function. | ||||
| func LoggerWithFormatter(f LogFormatter) HandlerFunc { | ||||
| 	return LoggerWithConfig(LoggerConfig{ | ||||
| 		Formatter: f, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // LoggerWithWriter instance a Logger middleware with the specified writer buffer. | ||||
| // Example: os.Stdout, a file opened in write mode, a socket... | ||||
| func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc { | ||||
| 	return LoggerWithConfig(LoggerConfig{ | ||||
| 		Output:    out, | ||||
| 		SkipPaths: notlogged, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| // LoggerWithConfig instance a Logger middleware with config. | ||||
| func LoggerWithConfig(conf LoggerConfig) HandlerFunc { | ||||
| 	formatter := conf.Formatter | ||||
| 	if formatter == nil { | ||||
| 		formatter = defaultLogFormatter | ||||
| 	} | ||||
| 
 | ||||
| 	out := conf.Output | ||||
| 	if out == nil { | ||||
| 		out = DefaultWriter | ||||
| 	} | ||||
| 
 | ||||
| 	notlogged := conf.SkipPaths | ||||
| 
 | ||||
| 	isTerm := true | ||||
| 
 | ||||
| 	if w, ok := out.(*os.File); !ok || os.Getenv("TERM") == "dumb" || | ||||
| 		(!isatty.IsTerminal(w.Fd()) && !isatty.IsCygwinTerminal(w.Fd())) { | ||||
| 		isTerm = false | ||||
| 	} | ||||
| 
 | ||||
| 	var skip map[string]struct{} | ||||
| 
 | ||||
| 	if length := len(notlogged); length > 0 { | ||||
| 		skip = make(map[string]struct{}, length) | ||||
| 
 | ||||
| 		for _, path := range notlogged { | ||||
| 			skip[path] = struct{}{} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return func(c *Context) { | ||||
| 		// Start timer | ||||
| 		start := time.Now() | ||||
| 		path := c.Request.URL.Path | ||||
| 		raw := c.Request.URL.RawQuery | ||||
| 
 | ||||
| 		// Process request | ||||
| 		c.Next() | ||||
| 
 | ||||
| 		// Log only when path is not being skipped | ||||
| 		if _, ok := skip[path]; !ok { | ||||
| 			param := LogFormatterParams{ | ||||
| 				Request: c.Request, | ||||
| 				isTerm:  isTerm, | ||||
| 				Keys:    c.Keys, | ||||
| 			} | ||||
| 
 | ||||
| 			// Stop timer | ||||
| 			param.TimeStamp = time.Now() | ||||
| 			param.Latency = param.TimeStamp.Sub(start) | ||||
| 
 | ||||
| 			param.ClientIP = c.ClientIP() | ||||
| 			param.Method = c.Request.Method | ||||
| 			param.StatusCode = c.Writer.Status() | ||||
| 			param.ErrorMessage = c.Errors.ByType(ErrorTypePrivate).String() | ||||
| 
 | ||||
| 			param.BodySize = c.Writer.Size() | ||||
| 
 | ||||
| 			if raw != "" { | ||||
| 				path = path + "?" + raw | ||||
| 			} | ||||
| 
 | ||||
| 			param.Path = path | ||||
| 
 | ||||
| 			fmt.Fprint(out, formatter(param)) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										92
									
								
								vendor/github.com/gin-gonic/gin/mode.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								vendor/github.com/gin-gonic/gin/mode.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | |||
| // 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 ( | ||||
| 	"io" | ||||
| 	"os" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin/binding" | ||||
| ) | ||||
| 
 | ||||
| // EnvGinMode indicates environment name for gin mode. | ||||
| const EnvGinMode = "GIN_MODE" | ||||
| 
 | ||||
| const ( | ||||
| 	// DebugMode indicates gin mode is debug. | ||||
| 	DebugMode = "debug" | ||||
| 	// ReleaseMode indicates gin mode is release. | ||||
| 	ReleaseMode = "release" | ||||
| 	// TestMode indicates gin mode is test. | ||||
| 	TestMode = "test" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	debugCode = iota | ||||
| 	releaseCode | ||||
| 	testCode | ||||
| ) | ||||
| 
 | ||||
| // DefaultWriter is the default io.Writer used by Gin for debug output and | ||||
| // middleware output like Logger() or Recovery(). | ||||
| // Note that both Logger and Recovery provides custom ways to configure their | ||||
| // output io.Writer. | ||||
| // To support coloring in Windows use: | ||||
| // 		import "github.com/mattn/go-colorable" | ||||
| // 		gin.DefaultWriter = colorable.NewColorableStdout() | ||||
| 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 | ||||
| 
 | ||||
| func init() { | ||||
| 	mode := os.Getenv(EnvGinMode) | ||||
| 	SetMode(mode) | ||||
| } | ||||
| 
 | ||||
| // SetMode sets gin mode according to input string. | ||||
| func SetMode(value string) { | ||||
| 	if value == "" { | ||||
| 		value = DebugMode | ||||
| 	} | ||||
| 
 | ||||
| 	switch value { | ||||
| 	case DebugMode: | ||||
| 		ginMode = debugCode | ||||
| 	case ReleaseMode: | ||||
| 		ginMode = releaseCode | ||||
| 	case TestMode: | ||||
| 		ginMode = testCode | ||||
| 	default: | ||||
| 		panic("gin mode unknown: " + value + " (available mode: debug release test)") | ||||
| 	} | ||||
| 
 | ||||
| 	modeName = value | ||||
| } | ||||
| 
 | ||||
| // DisableBindValidation closes the default validator. | ||||
| func DisableBindValidation() { | ||||
| 	binding.Validator = nil | ||||
| } | ||||
| 
 | ||||
| // EnableJsonDecoderUseNumber sets true for binding.EnableDecoderUseNumber to | ||||
| // call the UseNumber method on the JSON Decoder instance. | ||||
| func EnableJsonDecoderUseNumber() { | ||||
| 	binding.EnableDecoderUseNumber = true | ||||
| } | ||||
| 
 | ||||
| // EnableJsonDecoderDisallowUnknownFields sets true for binding.EnableDecoderDisallowUnknownFields to | ||||
| // call the DisallowUnknownFields method on the JSON Decoder instance. | ||||
| func EnableJsonDecoderDisallowUnknownFields() { | ||||
| 	binding.EnableDecoderDisallowUnknownFields = true | ||||
| } | ||||
| 
 | ||||
| // Mode returns currently gin mode. | ||||
| func Mode() string { | ||||
| 	return modeName | ||||
| } | ||||
							
								
								
									
										150
									
								
								vendor/github.com/gin-gonic/gin/path.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								vendor/github.com/gin-gonic/gin/path.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,150 @@ | |||
| // Copyright 2013 Julien Schmidt. All rights reserved. | ||||
| // Based on the path package, Copyright 2009 The Go Authors. | ||||
| // Use of this source code is governed by a BSD-style license that can be found | ||||
| // at https://github.com/julienschmidt/httprouter/blob/master/LICENSE. | ||||
| 
 | ||||
| package gin | ||||
| 
 | ||||
| // cleanPath is the URL version of path.Clean, it returns a canonical URL path | ||||
| // for p, eliminating . and .. elements. | ||||
| // | ||||
| // The following rules are applied iteratively until no further processing can | ||||
| // be done: | ||||
| //	1. Replace multiple slashes with a single slash. | ||||
| //	2. Eliminate each . path name element (the current directory). | ||||
| //	3. Eliminate each inner .. path name element (the parent directory) | ||||
| //	   along with the non-.. element that precedes it. | ||||
| //	4. Eliminate .. elements that begin a rooted path: | ||||
| //	   that is, replace "/.." by "/" at the beginning of a path. | ||||
| // | ||||
| // If the result of this process is an empty string, "/" is returned. | ||||
| func cleanPath(p string) string { | ||||
| 	const stackBufSize = 128 | ||||
| 	// Turn empty string into "/" | ||||
| 	if p == "" { | ||||
| 		return "/" | ||||
| 	} | ||||
| 
 | ||||
| 	// Reasonably sized buffer on stack to avoid allocations in the common case. | ||||
| 	// If a larger buffer is required, it gets allocated dynamically. | ||||
| 	buf := make([]byte, 0, stackBufSize) | ||||
| 
 | ||||
| 	n := len(p) | ||||
| 
 | ||||
| 	// Invariants: | ||||
| 	//      reading from path; r is index of next byte to process. | ||||
| 	//      writing to buf; w is index of next byte to write. | ||||
| 
 | ||||
| 	// path must start with '/' | ||||
| 	r := 1 | ||||
| 	w := 1 | ||||
| 
 | ||||
| 	if p[0] != '/' { | ||||
| 		r = 0 | ||||
| 
 | ||||
| 		if n+1 > stackBufSize { | ||||
| 			buf = make([]byte, n+1) | ||||
| 		} else { | ||||
| 			buf = buf[:n+1] | ||||
| 		} | ||||
| 		buf[0] = '/' | ||||
| 	} | ||||
| 
 | ||||
| 	trailing := n > 1 && p[n-1] == '/' | ||||
| 
 | ||||
| 	// A bit more clunky without a 'lazybuf' like the path package, but the loop | ||||
| 	// gets completely inlined (bufApp calls). | ||||
| 	// loop has no expensive function calls (except 1x make)		// So in contrast to the path package this loop has no expensive function | ||||
| 	// calls (except make, if needed). | ||||
| 
 | ||||
| 	for r < n { | ||||
| 		switch { | ||||
| 		case p[r] == '/': | ||||
| 			// empty path element, trailing slash is added after the end | ||||
| 			r++ | ||||
| 
 | ||||
| 		case p[r] == '.' && r+1 == n: | ||||
| 			trailing = true | ||||
| 			r++ | ||||
| 
 | ||||
| 		case p[r] == '.' && p[r+1] == '/': | ||||
| 			// . element | ||||
| 			r += 2 | ||||
| 
 | ||||
| 		case p[r] == '.' && p[r+1] == '.' && (r+2 == n || p[r+2] == '/'): | ||||
| 			// .. element: remove to last / | ||||
| 			r += 3 | ||||
| 
 | ||||
| 			if w > 1 { | ||||
| 				// can backtrack | ||||
| 				w-- | ||||
| 
 | ||||
| 				if len(buf) == 0 { | ||||
| 					for w > 1 && p[w] != '/' { | ||||
| 						w-- | ||||
| 					} | ||||
| 				} else { | ||||
| 					for w > 1 && buf[w] != '/' { | ||||
| 						w-- | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 		default: | ||||
| 			// Real path element. | ||||
| 			// Add slash if needed | ||||
| 			if w > 1 { | ||||
| 				bufApp(&buf, p, w, '/') | ||||
| 				w++ | ||||
| 			} | ||||
| 
 | ||||
| 			// Copy element | ||||
| 			for r < n && p[r] != '/' { | ||||
| 				bufApp(&buf, p, w, p[r]) | ||||
| 				w++ | ||||
| 				r++ | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Re-append trailing slash | ||||
| 	if trailing && w > 1 { | ||||
| 		bufApp(&buf, p, w, '/') | ||||
| 		w++ | ||||
| 	} | ||||
| 
 | ||||
| 	// If the original string was not modified (or only shortened at the end), | ||||
| 	// return the respective substring of the original string. | ||||
| 	// Otherwise return a new string from the buffer. | ||||
| 	if len(buf) == 0 { | ||||
| 		return p[:w] | ||||
| 	} | ||||
| 	return string(buf[:w]) | ||||
| } | ||||
| 
 | ||||
| // Internal helper to lazily create a buffer if necessary. | ||||
| // Calls to this function get inlined. | ||||
| func bufApp(buf *[]byte, s string, w int, c byte) { | ||||
| 	b := *buf | ||||
| 	if len(b) == 0 { | ||||
| 		// No modification of the original string so far. | ||||
| 		// If the next character is the same as in the original string, we do | ||||
| 		// not yet have to allocate a buffer. | ||||
| 		if s[w] == c { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		// Otherwise use either the stack buffer, if it is large enough, or | ||||
| 		// allocate a new buffer on the heap, and copy all previous characters. | ||||
| 		length := len(s) | ||||
| 		if length > cap(b) { | ||||
| 			*buf = make([]byte, length) | ||||
| 		} else { | ||||
| 			*buf = (*buf)[:length] | ||||
| 		} | ||||
| 		b = *buf | ||||
| 
 | ||||
| 		copy(b, s[:w]) | ||||
| 	} | ||||
| 	b[w] = c | ||||
| } | ||||
							
								
								
									
										171
									
								
								vendor/github.com/gin-gonic/gin/recovery.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								vendor/github.com/gin-gonic/gin/recovery.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,171 @@ | |||
| // 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 ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"net/http/httputil" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	dunno     = []byte("???") | ||||
| 	centerDot = []byte("·") | ||||
| 	dot       = []byte(".") | ||||
| 	slash     = []byte("/") | ||||
| ) | ||||
| 
 | ||||
| // RecoveryFunc defines the function passable to CustomRecovery. | ||||
| type RecoveryFunc func(c *Context, err interface{}) | ||||
| 
 | ||||
| // 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. | ||||
| func CustomRecovery(handle RecoveryFunc) HandlerFunc { | ||||
| 	return RecoveryWithWriter(DefaultErrorWriter, handle) | ||||
| } | ||||
| 
 | ||||
| // RecoveryWithWriter returns a middleware for a given writer that recovers from any panics and writes a 500 if there was one. | ||||
| func RecoveryWithWriter(out io.Writer, recovery ...RecoveryFunc) HandlerFunc { | ||||
| 	if len(recovery) > 0 { | ||||
| 		return CustomRecoveryWithWriter(out, recovery[0]) | ||||
| 	} | ||||
| 	return CustomRecoveryWithWriter(out, defaultHandleRecovery) | ||||
| } | ||||
| 
 | ||||
| // CustomRecoveryWithWriter returns a middleware for a given writer that recovers from any panics and calls the provided handle func to handle it. | ||||
| func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc { | ||||
| 	var logger *log.Logger | ||||
| 	if out != nil { | ||||
| 		logger = log.New(out, "\n\n\x1b[31m", log.LstdFlags) | ||||
| 	} | ||||
| 	return func(c *Context) { | ||||
| 		defer func() { | ||||
| 			if err := recover(); err != nil { | ||||
| 				// Check for a broken connection, as it is not really a | ||||
| 				// 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 { | ||||
| 						if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") { | ||||
| 							brokenPipe = true | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				if logger != nil { | ||||
| 					stack := stack(3) | ||||
| 					httpRequest, _ := httputil.DumpRequest(c.Request, false) | ||||
| 					headers := strings.Split(string(httpRequest), "\r\n") | ||||
| 					for idx, header := range headers { | ||||
| 						current := strings.Split(header, ":") | ||||
| 						if current[0] == "Authorization" { | ||||
| 							headers[idx] = current[0] + ": *" | ||||
| 						} | ||||
| 					} | ||||
| 					headersToStr := strings.Join(headers, "\r\n") | ||||
| 					if brokenPipe { | ||||
| 						logger.Printf("%s\n%s%s", err, headersToStr, reset) | ||||
| 					} else if IsDebugging() { | ||||
| 						logger.Printf("[Recovery] %s panic recovered:\n%s\n%s\n%s%s", | ||||
| 							timeFormat(time.Now()), headersToStr, err, stack, reset) | ||||
| 					} else { | ||||
| 						logger.Printf("[Recovery] %s panic recovered:\n%s\n%s%s", | ||||
| 							timeFormat(time.Now()), err, stack, reset) | ||||
| 					} | ||||
| 				} | ||||
| 				if brokenPipe { | ||||
| 					// If the connection is dead, we can't write a status to it. | ||||
| 					c.Error(err.(error)) // nolint: errcheck | ||||
| 					c.Abort() | ||||
| 				} else { | ||||
| 					handle(c, err) | ||||
| 				} | ||||
| 			} | ||||
| 		}() | ||||
| 		c.Next() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func defaultHandleRecovery(c *Context, err interface{}) { | ||||
| 	c.AbortWithStatus(http.StatusInternalServerError) | ||||
| } | ||||
| 
 | ||||
| // stack returns a nicely formatted stack frame, skipping skip frames. | ||||
| func stack(skip int) []byte { | ||||
| 	buf := new(bytes.Buffer) // the returned data | ||||
| 	// As we loop, we open files and read them. These variables record the currently | ||||
| 	// loaded file. | ||||
| 	var lines [][]byte | ||||
| 	var lastFile string | ||||
| 	for i := skip; ; i++ { // Skip the expected number of frames | ||||
| 		pc, file, line, ok := runtime.Caller(i) | ||||
| 		if !ok { | ||||
| 			break | ||||
| 		} | ||||
| 		// Print this much at least.  If we can't find the source, it won't show. | ||||
| 		fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc) | ||||
| 		if file != lastFile { | ||||
| 			data, err := ioutil.ReadFile(file) | ||||
| 			if err != nil { | ||||
| 				continue | ||||
| 			} | ||||
| 			lines = bytes.Split(data, []byte{'\n'}) | ||||
| 			lastFile = file | ||||
| 		} | ||||
| 		fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line)) | ||||
| 	} | ||||
| 	return buf.Bytes() | ||||
| } | ||||
| 
 | ||||
| // source returns a space-trimmed slice of the n'th line. | ||||
| func source(lines [][]byte, n int) []byte { | ||||
| 	n-- // in stack trace, lines are 1-indexed but our array is 0-indexed | ||||
| 	if n < 0 || n >= len(lines) { | ||||
| 		return dunno | ||||
| 	} | ||||
| 	return bytes.TrimSpace(lines[n]) | ||||
| } | ||||
| 
 | ||||
| // function returns, if possible, the name of the function containing the PC. | ||||
| func function(pc uintptr) []byte { | ||||
| 	fn := runtime.FuncForPC(pc) | ||||
| 	if fn == nil { | ||||
| 		return dunno | ||||
| 	} | ||||
| 	name := []byte(fn.Name()) | ||||
| 	// The name includes the path name to the package, which is unnecessary | ||||
| 	// since the file name is already included.  Plus, it has center dots. | ||||
| 	// That is, we see | ||||
| 	//	runtime/debug.*T·ptrmethod | ||||
| 	// and want | ||||
| 	//	*T.ptrmethod | ||||
| 	// Also the package path might contains dot (e.g. code.google.com/...), | ||||
| 	// so first eliminate the path prefix | ||||
| 	if lastSlash := bytes.LastIndex(name, slash); lastSlash >= 0 { | ||||
| 		name = name[lastSlash+1:] | ||||
| 	} | ||||
| 	if period := bytes.Index(name, dot); period >= 0 { | ||||
| 		name = name[period+1:] | ||||
| 	} | ||||
| 	name = bytes.Replace(name, centerDot, dot, -1) | ||||
| 	return name | ||||
| } | ||||
| 
 | ||||
| // timeFormat returns a customized time string for logger. | ||||
| func timeFormat(t time.Time) string { | ||||
| 	return t.Format("2006/01/02 - 15:04:05") | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/github.com/gin-gonic/gin/render/data.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/gin-gonic/gin/render/data.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| // 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 render | ||||
| 
 | ||||
| import "net/http" | ||||
| 
 | ||||
| // Data contains ContentType and bytes data. | ||||
| type Data struct { | ||||
| 	ContentType string | ||||
| 	Data        []byte | ||||
| } | ||||
| 
 | ||||
| // Render (Data) writes data with custom ContentType. | ||||
| func (r Data) Render(w http.ResponseWriter) (err error) { | ||||
| 	r.WriteContentType(w) | ||||
| 	_, err = w.Write(r.Data) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (Data) writes custom ContentType. | ||||
| func (r Data) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, []string{r.ContentType}) | ||||
| } | ||||
							
								
								
									
										92
									
								
								vendor/github.com/gin-gonic/gin/render/html.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								vendor/github.com/gin-gonic/gin/render/html.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | |||
| // 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 render | ||||
| 
 | ||||
| import ( | ||||
| 	"html/template" | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| // Delims represents a set of Left and Right delimiters for HTML template rendering. | ||||
| type Delims struct { | ||||
| 	// Left delimiter, defaults to {{. | ||||
| 	Left string | ||||
| 	// Right delimiter, defaults to }}. | ||||
| 	Right string | ||||
| } | ||||
| 
 | ||||
| // HTMLRender interface is to be implemented by HTMLProduction and HTMLDebug. | ||||
| type HTMLRender interface { | ||||
| 	// Instance returns an HTML instance. | ||||
| 	Instance(string, interface{}) Render | ||||
| } | ||||
| 
 | ||||
| // HTMLProduction contains template reference and its delims. | ||||
| type HTMLProduction struct { | ||||
| 	Template *template.Template | ||||
| 	Delims   Delims | ||||
| } | ||||
| 
 | ||||
| // HTMLDebug contains template delims and pattern and function with file list. | ||||
| type HTMLDebug struct { | ||||
| 	Files   []string | ||||
| 	Glob    string | ||||
| 	Delims  Delims | ||||
| 	FuncMap template.FuncMap | ||||
| } | ||||
| 
 | ||||
| // HTML contains template reference and its name with given interface object. | ||||
| type HTML struct { | ||||
| 	Template *template.Template | ||||
| 	Name     string | ||||
| 	Data     interface{} | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
| 	return HTML{ | ||||
| 		Template: r.Template, | ||||
| 		Name:     name, | ||||
| 		Data:     data, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Instance (HTMLDebug) returns an HTML instance which it realizes Render interface. | ||||
| func (r HTMLDebug) Instance(name string, data interface{}) Render { | ||||
| 	return HTML{ | ||||
| 		Template: r.loadTemplate(), | ||||
| 		Name:     name, | ||||
| 		Data:     data, | ||||
| 	} | ||||
| } | ||||
| func (r HTMLDebug) loadTemplate() *template.Template { | ||||
| 	if r.FuncMap == nil { | ||||
| 		r.FuncMap = template.FuncMap{} | ||||
| 	} | ||||
| 	if len(r.Files) > 0 { | ||||
| 		return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseFiles(r.Files...)) | ||||
| 	} | ||||
| 	if r.Glob != "" { | ||||
| 		return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseGlob(r.Glob)) | ||||
| 	} | ||||
| 	panic("the HTML debug render was created without files or glob pattern") | ||||
| } | ||||
| 
 | ||||
| // Render (HTML) executes template and writes its result with custom ContentType for response. | ||||
| func (r HTML) Render(w http.ResponseWriter) error { | ||||
| 	r.WriteContentType(w) | ||||
| 
 | ||||
| 	if r.Name == "" { | ||||
| 		return r.Template.Execute(w, r.Data) | ||||
| 	} | ||||
| 	return r.Template.ExecuteTemplate(w, r.Name, r.Data) | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (HTML) writes HTML ContentType. | ||||
| func (r HTML) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, htmlContentType) | ||||
| } | ||||
							
								
								
									
										195
									
								
								vendor/github.com/gin-gonic/gin/render/json.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								vendor/github.com/gin-gonic/gin/render/json.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,195 @@ | |||
| // 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 render | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"html/template" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin/internal/bytesconv" | ||||
| 	"github.com/gin-gonic/gin/internal/json" | ||||
| ) | ||||
| 
 | ||||
| // JSON contains the given interface object. | ||||
| type JSON struct { | ||||
| 	Data interface{} | ||||
| } | ||||
| 
 | ||||
| // IndentedJSON contains the given interface object. | ||||
| type IndentedJSON struct { | ||||
| 	Data interface{} | ||||
| } | ||||
| 
 | ||||
| // SecureJSON contains the given interface object and its prefix. | ||||
| type SecureJSON struct { | ||||
| 	Prefix string | ||||
| 	Data   interface{} | ||||
| } | ||||
| 
 | ||||
| // JsonpJSON contains the given interface object its callback. | ||||
| type JsonpJSON struct { | ||||
| 	Callback string | ||||
| 	Data     interface{} | ||||
| } | ||||
| 
 | ||||
| // AsciiJSON contains the given interface object. | ||||
| type AsciiJSON struct { | ||||
| 	Data interface{} | ||||
| } | ||||
| 
 | ||||
| // PureJSON contains the given interface object. | ||||
| type PureJSON struct { | ||||
| 	Data interface{} | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
| 	if err = WriteJSON(w, r.Data); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (JSON) writes JSON ContentType. | ||||
| func (r JSON) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, jsonContentType) | ||||
| } | ||||
| 
 | ||||
| // WriteJSON marshals the given interface object and writes it with custom ContentType. | ||||
| func WriteJSON(w http.ResponseWriter, obj interface{}) error { | ||||
| 	writeContentType(w, jsonContentType) | ||||
| 	jsonBytes, err := json.Marshal(obj) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = w.Write(jsonBytes) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // Render (IndentedJSON) marshals the given interface object and writes it with custom ContentType. | ||||
| func (r IndentedJSON) Render(w http.ResponseWriter) error { | ||||
| 	r.WriteContentType(w) | ||||
| 	jsonBytes, err := json.MarshalIndent(r.Data, "", "    ") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = w.Write(jsonBytes) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (IndentedJSON) writes JSON ContentType. | ||||
| func (r IndentedJSON) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, jsonContentType) | ||||
| } | ||||
| 
 | ||||
| // Render (SecureJSON) marshals the given interface object and writes it with custom ContentType. | ||||
| func (r SecureJSON) Render(w http.ResponseWriter) error { | ||||
| 	r.WriteContentType(w) | ||||
| 	jsonBytes, err := json.Marshal(r.Data) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// 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 { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	_, err = w.Write(jsonBytes) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (SecureJSON) writes JSON ContentType. | ||||
| func (r SecureJSON) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, jsonContentType) | ||||
| } | ||||
| 
 | ||||
| // Render (JsonpJSON) marshals the given interface object and writes it and its callback with custom ContentType. | ||||
| func (r JsonpJSON) Render(w http.ResponseWriter) (err error) { | ||||
| 	r.WriteContentType(w) | ||||
| 	ret, err := json.Marshal(r.Data) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if r.Callback == "" { | ||||
| 		_, err = w.Write(ret) | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	callback := template.JSEscapeString(r.Callback) | ||||
| 	_, err = w.Write(bytesconv.StringToBytes(callback)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = w.Write(bytesconv.StringToBytes("(")) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = w.Write(ret) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = w.Write(bytesconv.StringToBytes(");")) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (JsonpJSON) writes Javascript ContentType. | ||||
| func (r JsonpJSON) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, jsonpContentType) | ||||
| } | ||||
| 
 | ||||
| // Render (AsciiJSON) marshals the given interface object and writes it with custom ContentType. | ||||
| func (r AsciiJSON) Render(w http.ResponseWriter) (err error) { | ||||
| 	r.WriteContentType(w) | ||||
| 	ret, err := json.Marshal(r.Data) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	var buffer bytes.Buffer | ||||
| 	for _, r := range bytesconv.BytesToString(ret) { | ||||
| 		cvt := string(r) | ||||
| 		if r >= 128 { | ||||
| 			cvt = fmt.Sprintf("\\u%04x", int64(r)) | ||||
| 		} | ||||
| 		buffer.WriteString(cvt) | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = w.Write(buffer.Bytes()) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (AsciiJSON) writes JSON ContentType. | ||||
| func (r AsciiJSON) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, jsonAsciiContentType) | ||||
| } | ||||
| 
 | ||||
| // Render (PureJSON) writes custom ContentType and encodes the given interface object. | ||||
| func (r PureJSON) Render(w http.ResponseWriter) error { | ||||
| 	r.WriteContentType(w) | ||||
| 	encoder := json.NewEncoder(w) | ||||
| 	encoder.SetEscapeHTML(false) | ||||
| 	return encoder.Encode(r.Data) | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (PureJSON) writes custom ContentType. | ||||
| func (r PureJSON) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, jsonContentType) | ||||
| } | ||||
							
								
								
									
										44
									
								
								vendor/github.com/gin-gonic/gin/render/msgpack.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/gin-gonic/gin/render/msgpack.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build !nomsgpack | ||||
| // +build !nomsgpack | ||||
| 
 | ||||
| package render | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"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{} | ||||
| } | ||||
| 
 | ||||
| var msgpackContentType = []string{"application/msgpack; charset=utf-8"} | ||||
| 
 | ||||
| // WriteContentType (MsgPack) writes MsgPack ContentType. | ||||
| func (r MsgPack) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, msgpackContentType) | ||||
| } | ||||
| 
 | ||||
| // Render (MsgPack) encodes the given interface object and writes data with custom ContentType. | ||||
| func (r MsgPack) Render(w http.ResponseWriter) error { | ||||
| 	return WriteMsgPack(w, r.Data) | ||||
| } | ||||
| 
 | ||||
| // WriteMsgPack writes MsgPack ContentType and encodes the given interface object. | ||||
| func WriteMsgPack(w http.ResponseWriter, obj interface{}) error { | ||||
| 	writeContentType(w, msgpackContentType) | ||||
| 	var mh codec.MsgpackHandle | ||||
| 	return codec.NewEncoder(w, &mh).Encode(obj) | ||||
| } | ||||
							
								
								
									
										36
									
								
								vendor/github.com/gin-gonic/gin/render/protobuf.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/gin-gonic/gin/render/protobuf.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| // 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 render | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| ) | ||||
| 
 | ||||
| // ProtoBuf contains the given interface object. | ||||
| type ProtoBuf struct { | ||||
| 	Data interface{} | ||||
| } | ||||
| 
 | ||||
| var protobufContentType = []string{"application/x-protobuf"} | ||||
| 
 | ||||
| // Render (ProtoBuf) marshals the given interface object and writes data with custom ContentType. | ||||
| func (r ProtoBuf) Render(w http.ResponseWriter) error { | ||||
| 	r.WriteContentType(w) | ||||
| 
 | ||||
| 	bytes, err := proto.Marshal(r.Data.(proto.Message)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = w.Write(bytes) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (ProtoBuf) writes ProtoBuf ContentType. | ||||
| func (r ProtoBuf) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, protobufContentType) | ||||
| } | ||||
							
								
								
									
										48
									
								
								vendor/github.com/gin-gonic/gin/render/reader.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/gin-gonic/gin/render/reader.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | |||
| // 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 render | ||||
| 
 | ||||
| import ( | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| // Reader contains the IO reader and its length, and custom ContentType and other headers. | ||||
| type Reader struct { | ||||
| 	ContentType   string | ||||
| 	ContentLength int64 | ||||
| 	Reader        io.Reader | ||||
| 	Headers       map[string]string | ||||
| } | ||||
| 
 | ||||
| // Render (Reader) writes data with custom ContentType and headers. | ||||
| func (r Reader) Render(w http.ResponseWriter) (err error) { | ||||
| 	r.WriteContentType(w) | ||||
| 	if r.ContentLength >= 0 { | ||||
| 		if r.Headers == nil { | ||||
| 			r.Headers = map[string]string{} | ||||
| 		} | ||||
| 		r.Headers["Content-Length"] = strconv.FormatInt(r.ContentLength, 10) | ||||
| 	} | ||||
| 	r.writeHeaders(w, r.Headers) | ||||
| 	_, err = io.Copy(w, r.Reader) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (Reader) writes custom ContentType. | ||||
| func (r Reader) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, []string{r.ContentType}) | ||||
| } | ||||
| 
 | ||||
| // writeHeaders writes custom Header. | ||||
| func (r Reader) writeHeaders(w http.ResponseWriter, headers map[string]string) { | ||||
| 	header := w.Header() | ||||
| 	for k, v := range headers { | ||||
| 		if header.Get(k) == "" { | ||||
| 			header.Set(k, v) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										29
									
								
								vendor/github.com/gin-gonic/gin/render/redirect.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/gin-gonic/gin/render/redirect.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | |||
| // 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 render | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| // Redirect contains the http request reference and redirects status code and location. | ||||
| type Redirect struct { | ||||
| 	Code     int | ||||
| 	Request  *http.Request | ||||
| 	Location string | ||||
| } | ||||
| 
 | ||||
| // Render (Redirect) redirects the http request to new location and writes redirect response. | ||||
| func (r Redirect) Render(w http.ResponseWriter) error { | ||||
| 	if (r.Code < http.StatusMultipleChoices || r.Code > http.StatusPermanentRedirect) && r.Code != http.StatusCreated { | ||||
| 		panic(fmt.Sprintf("Cannot redirect with status code %d", r.Code)) | ||||
| 	} | ||||
| 	http.Redirect(w, r.Request, r.Location, r.Code) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (Redirect) don't write any ContentType. | ||||
| func (r Redirect) WriteContentType(http.ResponseWriter) {} | ||||
							
								
								
									
										40
									
								
								vendor/github.com/gin-gonic/gin/render/render.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								vendor/github.com/gin-gonic/gin/render/render.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | |||
| // 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 render | ||||
| 
 | ||||
| import "net/http" | ||||
| 
 | ||||
| // Render interface is to be implemented by JSON, XML, HTML, YAML and so on. | ||||
| type Render interface { | ||||
| 	// Render writes data with custom ContentType. | ||||
| 	Render(http.ResponseWriter) error | ||||
| 	// WriteContentType writes custom ContentType. | ||||
| 	WriteContentType(w http.ResponseWriter) | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	_ Render     = JSON{} | ||||
| 	_ Render     = IndentedJSON{} | ||||
| 	_ Render     = SecureJSON{} | ||||
| 	_ Render     = JsonpJSON{} | ||||
| 	_ Render     = XML{} | ||||
| 	_ Render     = String{} | ||||
| 	_ Render     = Redirect{} | ||||
| 	_ Render     = Data{} | ||||
| 	_ Render     = HTML{} | ||||
| 	_ HTMLRender = HTMLDebug{} | ||||
| 	_ HTMLRender = HTMLProduction{} | ||||
| 	_ Render     = YAML{} | ||||
| 	_ Render     = Reader{} | ||||
| 	_ Render     = AsciiJSON{} | ||||
| 	_ Render     = ProtoBuf{} | ||||
| ) | ||||
| 
 | ||||
| func writeContentType(w http.ResponseWriter, value []string) { | ||||
| 	header := w.Header() | ||||
| 	if val := header["Content-Type"]; len(val) == 0 { | ||||
| 		header["Content-Type"] = value | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										41
									
								
								vendor/github.com/gin-gonic/gin/render/text.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/gin-gonic/gin/render/text.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| // 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 render | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin/internal/bytesconv" | ||||
| ) | ||||
| 
 | ||||
| // String contains the given interface object slice and its format. | ||||
| type String struct { | ||||
| 	Format string | ||||
| 	Data   []interface{} | ||||
| } | ||||
| 
 | ||||
| var plainContentType = []string{"text/plain; charset=utf-8"} | ||||
| 
 | ||||
| // Render (String) writes data with custom ContentType. | ||||
| func (r String) Render(w http.ResponseWriter) error { | ||||
| 	return WriteString(w, r.Format, r.Data) | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (String) writes Plain ContentType. | ||||
| func (r String) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, plainContentType) | ||||
| } | ||||
| 
 | ||||
| // WriteString writes data according to its format and write custom ContentType. | ||||
| func WriteString(w http.ResponseWriter, format string, data []interface{}) (err error) { | ||||
| 	writeContentType(w, plainContentType) | ||||
| 	if len(data) > 0 { | ||||
| 		_, err = fmt.Fprintf(w, format, data...) | ||||
| 		return | ||||
| 	} | ||||
| 	_, err = w.Write(bytesconv.StringToBytes(format)) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										28
									
								
								vendor/github.com/gin-gonic/gin/render/xml.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/gin-gonic/gin/render/xml.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| // 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 render | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/xml" | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| // XML contains the given interface object. | ||||
| type XML struct { | ||||
| 	Data interface{} | ||||
| } | ||||
| 
 | ||||
| var xmlContentType = []string{"application/xml; charset=utf-8"} | ||||
| 
 | ||||
| // Render (XML) encodes the given interface object and writes data with custom ContentType. | ||||
| func (r XML) Render(w http.ResponseWriter) error { | ||||
| 	r.WriteContentType(w) | ||||
| 	return xml.NewEncoder(w).Encode(r.Data) | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (XML) writes XML ContentType for response. | ||||
| func (r XML) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, xmlContentType) | ||||
| } | ||||
							
								
								
									
										36
									
								
								vendor/github.com/gin-gonic/gin/render/yaml.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/gin-gonic/gin/render/yaml.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| // 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 render | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"gopkg.in/yaml.v2" | ||||
| ) | ||||
| 
 | ||||
| // YAML contains the given interface object. | ||||
| type YAML struct { | ||||
| 	Data interface{} | ||||
| } | ||||
| 
 | ||||
| var yamlContentType = []string{"application/x-yaml; charset=utf-8"} | ||||
| 
 | ||||
| // Render (YAML) marshals the given interface object and writes data with custom ContentType. | ||||
| func (r YAML) Render(w http.ResponseWriter) error { | ||||
| 	r.WriteContentType(w) | ||||
| 
 | ||||
| 	bytes, err := yaml.Marshal(r.Data) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = w.Write(bytes) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // WriteContentType (YAML) writes YAML ContentType for response. | ||||
| func (r YAML) WriteContentType(w http.ResponseWriter) { | ||||
| 	writeContentType(w, yamlContentType) | ||||
| } | ||||
							
								
								
									
										126
									
								
								vendor/github.com/gin-gonic/gin/response_writer.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								vendor/github.com/gin-gonic/gin/response_writer.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,126 @@ | |||
| // 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 ( | ||||
| 	"bufio" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	noWritten     = -1 | ||||
| 	defaultStatus = http.StatusOK | ||||
| ) | ||||
| 
 | ||||
| // ResponseWriter ... | ||||
| type ResponseWriter interface { | ||||
| 	http.ResponseWriter | ||||
| 	http.Hijacker | ||||
| 	http.Flusher | ||||
| 	http.CloseNotifier | ||||
| 
 | ||||
| 	// Returns the HTTP response status code of the current request. | ||||
| 	Status() int | ||||
| 
 | ||||
| 	// Returns the number of bytes already written into the response http body. | ||||
| 	// See Written() | ||||
| 	Size() int | ||||
| 
 | ||||
| 	// Writes the string into the response body. | ||||
| 	WriteString(string) (int, error) | ||||
| 
 | ||||
| 	// Returns true if the response body was already written. | ||||
| 	Written() bool | ||||
| 
 | ||||
| 	// Forces to write the http header (status code + headers). | ||||
| 	WriteHeaderNow() | ||||
| 
 | ||||
| 	// get the http.Pusher for server push | ||||
| 	Pusher() http.Pusher | ||||
| } | ||||
| 
 | ||||
| type responseWriter struct { | ||||
| 	http.ResponseWriter | ||||
| 	size   int | ||||
| 	status int | ||||
| } | ||||
| 
 | ||||
| var _ ResponseWriter = &responseWriter{} | ||||
| 
 | ||||
| func (w *responseWriter) reset(writer http.ResponseWriter) { | ||||
| 	w.ResponseWriter = writer | ||||
| 	w.size = noWritten | ||||
| 	w.status = defaultStatus | ||||
| } | ||||
| 
 | ||||
| func (w *responseWriter) WriteHeader(code int) { | ||||
| 	if code > 0 && w.status != code { | ||||
| 		if w.Written() { | ||||
| 			debugPrint("[WARNING] Headers were already written. Wanted to override status code %d with %d", w.status, code) | ||||
| 		} | ||||
| 		w.status = code | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (w *responseWriter) WriteHeaderNow() { | ||||
| 	if !w.Written() { | ||||
| 		w.size = 0 | ||||
| 		w.ResponseWriter.WriteHeader(w.status) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (w *responseWriter) Write(data []byte) (n int, err error) { | ||||
| 	w.WriteHeaderNow() | ||||
| 	n, err = w.ResponseWriter.Write(data) | ||||
| 	w.size += n | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (w *responseWriter) WriteString(s string) (n int, err error) { | ||||
| 	w.WriteHeaderNow() | ||||
| 	n, err = io.WriteString(w.ResponseWriter, s) | ||||
| 	w.size += n | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (w *responseWriter) Status() int { | ||||
| 	return w.status | ||||
| } | ||||
| 
 | ||||
| func (w *responseWriter) Size() int { | ||||
| 	return w.size | ||||
| } | ||||
| 
 | ||||
| func (w *responseWriter) Written() bool { | ||||
| 	return w.size != noWritten | ||||
| } | ||||
| 
 | ||||
| // Hijack implements the http.Hijacker interface. | ||||
| func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { | ||||
| 	if w.size < 0 { | ||||
| 		w.size = 0 | ||||
| 	} | ||||
| 	return w.ResponseWriter.(http.Hijacker).Hijack() | ||||
| } | ||||
| 
 | ||||
| // CloseNotify implements the http.CloseNotify interface. | ||||
| func (w *responseWriter) CloseNotify() <-chan bool { | ||||
| 	return w.ResponseWriter.(http.CloseNotifier).CloseNotify() | ||||
| } | ||||
| 
 | ||||
| // Flush implements the http.Flush interface. | ||||
| func (w *responseWriter) Flush() { | ||||
| 	w.WriteHeaderNow() | ||||
| 	w.ResponseWriter.(http.Flusher).Flush() | ||||
| } | ||||
| 
 | ||||
| func (w *responseWriter) Pusher() (pusher http.Pusher) { | ||||
| 	if pusher, ok := w.ResponseWriter.(http.Pusher); ok { | ||||
| 		return pusher | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										233
									
								
								vendor/github.com/gin-gonic/gin/routergroup.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								vendor/github.com/gin-gonic/gin/routergroup.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,233 @@ | |||
| // 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 ( | ||||
| 	"net/http" | ||||
| 	"path" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	// reg match english letters for http method name | ||||
| 	regEnLetter = regexp.MustCompile("^[A-Z]+$") | ||||
| ) | ||||
| 
 | ||||
| // IRouter defines all router handle interface includes single and group router. | ||||
| type IRouter interface { | ||||
| 	IRoutes | ||||
| 	Group(string, ...HandlerFunc) *RouterGroup | ||||
| } | ||||
| 
 | ||||
| // IRoutes defines all router handle interface. | ||||
| type IRoutes interface { | ||||
| 	Use(...HandlerFunc) IRoutes | ||||
| 
 | ||||
| 	Handle(string, string, ...HandlerFunc) IRoutes | ||||
| 	Any(string, ...HandlerFunc) IRoutes | ||||
| 	GET(string, ...HandlerFunc) IRoutes | ||||
| 	POST(string, ...HandlerFunc) IRoutes | ||||
| 	DELETE(string, ...HandlerFunc) IRoutes | ||||
| 	PATCH(string, ...HandlerFunc) IRoutes | ||||
| 	PUT(string, ...HandlerFunc) IRoutes | ||||
| 	OPTIONS(string, ...HandlerFunc) IRoutes | ||||
| 	HEAD(string, ...HandlerFunc) IRoutes | ||||
| 
 | ||||
| 	StaticFile(string, string) IRoutes | ||||
| 	Static(string, string) IRoutes | ||||
| 	StaticFS(string, http.FileSystem) IRoutes | ||||
| } | ||||
| 
 | ||||
| // RouterGroup is used internally to configure router, a RouterGroup is associated with | ||||
| // a prefix and an array of handlers (middleware). | ||||
| type RouterGroup struct { | ||||
| 	Handlers HandlersChain | ||||
| 	basePath string | ||||
| 	engine   *Engine | ||||
| 	root     bool | ||||
| } | ||||
| 
 | ||||
| var _ IRouter = &RouterGroup{} | ||||
| 
 | ||||
| // Use adds middleware to the group, see example code in GitHub. | ||||
| func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes { | ||||
| 	group.Handlers = append(group.Handlers, middleware...) | ||||
| 	return group.returnObj() | ||||
| } | ||||
| 
 | ||||
| // Group creates a new router group. You should add all the routes that have common middlewares or the same path prefix. | ||||
| // For example, all the routes that use a common middleware for authorization could be grouped. | ||||
| func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup { | ||||
| 	return &RouterGroup{ | ||||
| 		Handlers: group.combineHandlers(handlers), | ||||
| 		basePath: group.calculateAbsolutePath(relativePath), | ||||
| 		engine:   group.engine, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // BasePath returns the base path of router group. | ||||
| // For example, if v := router.Group("/rest/n/v1/api"), v.BasePath() is "/rest/n/v1/api". | ||||
| func (group *RouterGroup) BasePath() string { | ||||
| 	return group.basePath | ||||
| } | ||||
| 
 | ||||
| func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes { | ||||
| 	absolutePath := group.calculateAbsolutePath(relativePath) | ||||
| 	handlers = group.combineHandlers(handlers) | ||||
| 	group.engine.addRoute(httpMethod, absolutePath, handlers) | ||||
| 	return group.returnObj() | ||||
| } | ||||
| 
 | ||||
| // Handle registers a new request handle and middleware with the given path and method. | ||||
| // The last handler should be the real handler, the other ones should be middleware that can and should be shared among different routes. | ||||
| // See the example code in GitHub. | ||||
| // | ||||
| // For GET, POST, PUT, PATCH and DELETE requests the respective shortcut | ||||
| // functions can be used. | ||||
| // | ||||
| // This function is intended for bulk loading and to allow the usage of less | ||||
| // 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 matched := regEnLetter.MatchString(httpMethod); !matched { | ||||
| 		panic("http method " + httpMethod + " is not valid") | ||||
| 	} | ||||
| 	return group.handle(httpMethod, relativePath, handlers) | ||||
| } | ||||
| 
 | ||||
| // POST is a shortcut for router.Handle("POST", path, handle). | ||||
| func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes { | ||||
| 	return group.handle(http.MethodPost, relativePath, handlers) | ||||
| } | ||||
| 
 | ||||
| // GET is a shortcut for router.Handle("GET", path, handle). | ||||
| func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes { | ||||
| 	return group.handle(http.MethodGet, relativePath, handlers) | ||||
| } | ||||
| 
 | ||||
| // DELETE is a shortcut for router.Handle("DELETE", path, handle). | ||||
| func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes { | ||||
| 	return group.handle(http.MethodDelete, relativePath, handlers) | ||||
| } | ||||
| 
 | ||||
| // PATCH is a shortcut for router.Handle("PATCH", path, handle). | ||||
| func (group *RouterGroup) PATCH(relativePath string, handlers ...HandlerFunc) IRoutes { | ||||
| 	return group.handle(http.MethodPatch, relativePath, handlers) | ||||
| } | ||||
| 
 | ||||
| // PUT is a shortcut for router.Handle("PUT", path, handle). | ||||
| func (group *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc) IRoutes { | ||||
| 	return group.handle(http.MethodPut, relativePath, handlers) | ||||
| } | ||||
| 
 | ||||
| // OPTIONS is a shortcut for router.Handle("OPTIONS", path, handle). | ||||
| func (group *RouterGroup) OPTIONS(relativePath string, handlers ...HandlerFunc) IRoutes { | ||||
| 	return group.handle(http.MethodOptions, relativePath, handlers) | ||||
| } | ||||
| 
 | ||||
| // HEAD is a shortcut for router.Handle("HEAD", path, handle). | ||||
| func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRoutes { | ||||
| 	return group.handle(http.MethodHead, relativePath, handlers) | ||||
| } | ||||
| 
 | ||||
| // 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) | ||||
| 	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 { | ||||
| 	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() | ||||
| } | ||||
| 
 | ||||
| // Static serves files from the given file system root. | ||||
| // Internally a http.FileServer is used, therefore http.NotFound is used instead | ||||
| // of the Router's NotFound handler. | ||||
| // To use the operating system's file system implementation, | ||||
| // use : | ||||
| //     router.Static("/static", "/var/www") | ||||
| func (group *RouterGroup) Static(relativePath, root string) IRoutes { | ||||
| 	return group.StaticFS(relativePath, Dir(root, false)) | ||||
| } | ||||
| 
 | ||||
| // StaticFS works just like `Static()` but a custom `http.FileSystem` can be used instead. | ||||
| // Gin by default user: gin.Dir() | ||||
| func (group *RouterGroup) StaticFS(relativePath string, fs http.FileSystem) IRoutes { | ||||
| 	if strings.Contains(relativePath, ":") || strings.Contains(relativePath, "*") { | ||||
| 		panic("URL parameters can not be used when serving a static folder") | ||||
| 	} | ||||
| 	handler := group.createStaticHandler(relativePath, fs) | ||||
| 	urlPattern := path.Join(relativePath, "/*filepath") | ||||
| 
 | ||||
| 	// Register GET and HEAD handlers | ||||
| 	group.GET(urlPattern, handler) | ||||
| 	group.HEAD(urlPattern, handler) | ||||
| 	return group.returnObj() | ||||
| } | ||||
| 
 | ||||
| func (group *RouterGroup) createStaticHandler(relativePath string, fs http.FileSystem) HandlerFunc { | ||||
| 	absolutePath := group.calculateAbsolutePath(relativePath) | ||||
| 	fileServer := http.StripPrefix(absolutePath, http.FileServer(fs)) | ||||
| 
 | ||||
| 	return func(c *Context) { | ||||
| 		if _, noListing := fs.(*onlyFilesFS); noListing { | ||||
| 			c.Writer.WriteHeader(http.StatusNotFound) | ||||
| 		} | ||||
| 
 | ||||
| 		file := c.Param("filepath") | ||||
| 		// Check if file exists and/or if we have permission to access it | ||||
| 		f, err := fs.Open(file) | ||||
| 		if err != nil { | ||||
| 			c.Writer.WriteHeader(http.StatusNotFound) | ||||
| 			c.handlers = group.engine.noRoute | ||||
| 			// Reset index | ||||
| 			c.index = -1 | ||||
| 			return | ||||
| 		} | ||||
| 		f.Close() | ||||
| 
 | ||||
| 		fileServer.ServeHTTP(c.Writer, c.Request) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (group *RouterGroup) combineHandlers(handlers HandlersChain) HandlersChain { | ||||
| 	finalSize := len(group.Handlers) + len(handlers) | ||||
| 	assert1(finalSize < int(abortIndex), "too many handlers") | ||||
| 	mergedHandlers := make(HandlersChain, finalSize) | ||||
| 	copy(mergedHandlers, group.Handlers) | ||||
| 	copy(mergedHandlers[len(group.Handlers):], handlers) | ||||
| 	return mergedHandlers | ||||
| } | ||||
| 
 | ||||
| func (group *RouterGroup) calculateAbsolutePath(relativePath string) string { | ||||
| 	return joinPaths(group.basePath, relativePath) | ||||
| } | ||||
| 
 | ||||
| func (group *RouterGroup) returnObj() IRoutes { | ||||
| 	if group.root { | ||||
| 		return group.engine | ||||
| 	} | ||||
| 	return group | ||||
| } | ||||
							
								
								
									
										16
									
								
								vendor/github.com/gin-gonic/gin/test_helpers.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/gin-gonic/gin/test_helpers.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| // 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. | ||||
| 
 | ||||
| package gin | ||||
| 
 | ||||
| import "net/http" | ||||
| 
 | ||||
| // CreateTestContext returns a fresh engine and context for testing purposes | ||||
| func CreateTestContext(w http.ResponseWriter) (c *Context, r *Engine) { | ||||
| 	r = New() | ||||
| 	c = r.allocateContext() | ||||
| 	c.reset() | ||||
| 	c.writermem.reset(w) | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										842
									
								
								vendor/github.com/gin-gonic/gin/tree.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										842
									
								
								vendor/github.com/gin-gonic/gin/tree.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,842 @@ | |||
| // Copyright 2013 Julien Schmidt. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style license that can be found | ||||
| // at https://github.com/julienschmidt/httprouter/blob/master/LICENSE | ||||
| 
 | ||||
| package gin | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"net/url" | ||||
| 	"strings" | ||||
| 	"unicode" | ||||
| 	"unicode/utf8" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin/internal/bytesconv" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	strColon = []byte(":") | ||||
| 	strStar  = []byte("*") | ||||
| ) | ||||
| 
 | ||||
| // Param is a single URL parameter, consisting of a key and a value. | ||||
| type Param struct { | ||||
| 	Key   string | ||||
| 	Value string | ||||
| } | ||||
| 
 | ||||
| // Params is a Param-slice, as returned by the router. | ||||
| // The slice is ordered, the first URL parameter is also the first slice value. | ||||
| // 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 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 { | ||||
| 			return entry.Value, true | ||||
| 		} | ||||
| 	} | ||||
| 	return "", false | ||||
| } | ||||
| 
 | ||||
| // ByName returns the value of the first Param which key matches the given name. | ||||
| // If no matching Param is found, an empty string is returned. | ||||
| func (ps Params) ByName(name string) (va string) { | ||||
| 	va, _ = ps.Get(name) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| type methodTree struct { | ||||
| 	method string | ||||
| 	root   *node | ||||
| } | ||||
| 
 | ||||
| type methodTrees []methodTree | ||||
| 
 | ||||
| func (trees methodTrees) get(method string) *node { | ||||
| 	for _, tree := range trees { | ||||
| 		if tree.method == method { | ||||
| 			return tree.root | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func min(a, b int) int { | ||||
| 	if a <= b { | ||||
| 		return a | ||||
| 	} | ||||
| 	return b | ||||
| } | ||||
| 
 | ||||
| func longestCommonPrefix(a, b string) int { | ||||
| 	i := 0 | ||||
| 	max := min(len(a), len(b)) | ||||
| 	for i < max && a[i] == b[i] { | ||||
| 		i++ | ||||
| 	} | ||||
| 	return i | ||||
| } | ||||
| 
 | ||||
| // addChild will add a child node, keeping wildcards at the end | ||||
| func (n *node) addChild(child *node) { | ||||
| 	if n.wildChild && len(n.children) > 0 { | ||||
| 		wildcardChild := n.children[len(n.children)-1] | ||||
| 		n.children = append(n.children[:len(n.children)-1], child, wildcardChild) | ||||
| 	} else { | ||||
| 		n.children = append(n.children, child) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func countParams(path string) uint16 { | ||||
| 	var n uint16 | ||||
| 	s := bytesconv.StringToBytes(path) | ||||
| 	n += uint16(bytes.Count(s, strColon)) | ||||
| 	n += uint16(bytes.Count(s, strStar)) | ||||
| 	return n | ||||
| } | ||||
| 
 | ||||
| type nodeType uint8 | ||||
| 
 | ||||
| const ( | ||||
| 	static nodeType = iota // default | ||||
| 	root | ||||
| 	param | ||||
| 	catchAll | ||||
| ) | ||||
| 
 | ||||
| type node struct { | ||||
| 	path      string | ||||
| 	indices   string | ||||
| 	wildChild bool | ||||
| 	nType     nodeType | ||||
| 	priority  uint32 | ||||
| 	children  []*node // child nodes, at most 1 :param style node at the end of the array | ||||
| 	handlers  HandlersChain | ||||
| 	fullPath  string | ||||
| } | ||||
| 
 | ||||
| // Increments priority of the given child and reorders if necessary | ||||
| func (n *node) incrementChildPrio(pos int) int { | ||||
| 	cs := n.children | ||||
| 	cs[pos].priority++ | ||||
| 	prio := cs[pos].priority | ||||
| 
 | ||||
| 	// Adjust position (move to front) | ||||
| 	newPos := pos | ||||
| 	for ; newPos > 0 && cs[newPos-1].priority < prio; newPos-- { | ||||
| 		// Swap node positions | ||||
| 		cs[newPos-1], cs[newPos] = cs[newPos], cs[newPos-1] | ||||
| 	} | ||||
| 
 | ||||
| 	// Build new index char string | ||||
| 	if newPos != pos { | ||||
| 		n.indices = n.indices[:newPos] + // Unchanged prefix, might be empty | ||||
| 			n.indices[pos:pos+1] + // The index char we move | ||||
| 			n.indices[newPos:pos] + n.indices[pos+1:] // Rest without char at 'pos' | ||||
| 	} | ||||
| 
 | ||||
| 	return newPos | ||||
| } | ||||
| 
 | ||||
| // addRoute adds a node with the given handle to the path. | ||||
| // Not concurrency-safe! | ||||
| func (n *node) addRoute(path string, handlers HandlersChain) { | ||||
| 	fullPath := path | ||||
| 	n.priority++ | ||||
| 
 | ||||
| 	// Empty tree | ||||
| 	if len(n.path) == 0 && len(n.children) == 0 { | ||||
| 		n.insertChild(path, fullPath, handlers) | ||||
| 		n.nType = root | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	parentFullPathIndex := 0 | ||||
| 
 | ||||
| walk: | ||||
| 	for { | ||||
| 		// Find the longest common prefix. | ||||
| 		// This also implies that the common prefix contains no ':' or '*' | ||||
| 		// since the existing key can't contain those chars. | ||||
| 		i := longestCommonPrefix(path, n.path) | ||||
| 
 | ||||
| 		// Split edge | ||||
| 		if i < len(n.path) { | ||||
| 			child := node{ | ||||
| 				path:      n.path[i:], | ||||
| 				wildChild: n.wildChild, | ||||
| 				indices:   n.indices, | ||||
| 				children:  n.children, | ||||
| 				handlers:  n.handlers, | ||||
| 				priority:  n.priority - 1, | ||||
| 				fullPath:  n.fullPath, | ||||
| 			} | ||||
| 
 | ||||
| 			n.children = []*node{&child} | ||||
| 			// []byte for proper unicode char conversion, see #65 | ||||
| 			n.indices = bytesconv.BytesToString([]byte{n.path[i]}) | ||||
| 			n.path = path[:i] | ||||
| 			n.handlers = nil | ||||
| 			n.wildChild = false | ||||
| 			n.fullPath = fullPath[:parentFullPathIndex+i] | ||||
| 		} | ||||
| 
 | ||||
| 		// Make new node a child of this node | ||||
| 		if i < len(path) { | ||||
| 			path = path[i:] | ||||
| 			c := path[0] | ||||
| 
 | ||||
| 			// '/' after param | ||||
| 			if n.nType == param && c == '/' && len(n.children) == 1 { | ||||
| 				parentFullPathIndex += len(n.path) | ||||
| 				n = n.children[0] | ||||
| 				n.priority++ | ||||
| 				continue walk | ||||
| 			} | ||||
| 
 | ||||
| 			// Check if a child with the next path byte exists | ||||
| 			for i, max := 0, len(n.indices); i < max; i++ { | ||||
| 				if c == n.indices[i] { | ||||
| 					parentFullPathIndex += len(n.path) | ||||
| 					i = n.incrementChildPrio(i) | ||||
| 					n = n.children[i] | ||||
| 					continue walk | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			// Otherwise insert it | ||||
| 			if c != ':' && c != '*' && n.nType != catchAll { | ||||
| 				// []byte for proper unicode char conversion, see #65 | ||||
| 				n.indices += bytesconv.BytesToString([]byte{c}) | ||||
| 				child := &node{ | ||||
| 					fullPath: fullPath, | ||||
| 				} | ||||
| 				n.addChild(child) | ||||
| 				n.incrementChildPrio(len(n.indices) - 1) | ||||
| 				n = child | ||||
| 			} else if n.wildChild { | ||||
| 				// inserting a wildcard node, need to check if it conflicts with the existing wildcard | ||||
| 				n = n.children[len(n.children)-1] | ||||
| 				n.priority++ | ||||
| 
 | ||||
| 				// Check if the wildcard matches | ||||
| 				if len(path) >= len(n.path) && n.path == path[:len(n.path)] && | ||||
| 					// Adding a child to a catchAll is not possible | ||||
| 					n.nType != catchAll && | ||||
| 					// Check for longer wildcard, e.g. :name and :names | ||||
| 					(len(n.path) >= len(path) || path[len(n.path)] == '/') { | ||||
| 					continue walk | ||||
| 				} | ||||
| 
 | ||||
| 				// Wildcard conflict | ||||
| 				pathSeg := path | ||||
| 				if n.nType != catchAll { | ||||
| 					pathSeg = strings.SplitN(pathSeg, "/", 2)[0] | ||||
| 				} | ||||
| 				prefix := fullPath[:strings.Index(fullPath, pathSeg)] + n.path | ||||
| 				panic("'" + pathSeg + | ||||
| 					"' in new path '" + fullPath + | ||||
| 					"' conflicts with existing wildcard '" + n.path + | ||||
| 					"' in existing prefix '" + prefix + | ||||
| 					"'") | ||||
| 			} | ||||
| 
 | ||||
| 			n.insertChild(path, fullPath, handlers) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		// Otherwise add handle to current node | ||||
| 		if n.handlers != nil { | ||||
| 			panic("handlers are already registered for path '" + fullPath + "'") | ||||
| 		} | ||||
| 		n.handlers = handlers | ||||
| 		n.fullPath = fullPath | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Search for a wildcard segment and check the name for invalid characters. | ||||
| // Returns -1 as index, if no wildcard was found. | ||||
| func findWildcard(path string) (wildcard string, i int, valid bool) { | ||||
| 	// Find start | ||||
| 	for start, c := range []byte(path) { | ||||
| 		// A wildcard starts with ':' (param) or '*' (catch-all) | ||||
| 		if c != ':' && c != '*' { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		// Find end and check for invalid characters | ||||
| 		valid = true | ||||
| 		for end, c := range []byte(path[start+1:]) { | ||||
| 			switch c { | ||||
| 			case '/': | ||||
| 				return path[start : start+1+end], start, valid | ||||
| 			case ':', '*': | ||||
| 				valid = false | ||||
| 			} | ||||
| 		} | ||||
| 		return path[start:], start, valid | ||||
| 	} | ||||
| 	return "", -1, false | ||||
| } | ||||
| 
 | ||||
| func (n *node) insertChild(path string, fullPath string, handlers HandlersChain) { | ||||
| 	for { | ||||
| 		// Find prefix until first wildcard | ||||
| 		wildcard, i, valid := findWildcard(path) | ||||
| 		if i < 0 { // No wildcard found | ||||
| 			break | ||||
| 		} | ||||
| 
 | ||||
| 		// The wildcard name must not contain ':' and '*' | ||||
| 		if !valid { | ||||
| 			panic("only one wildcard per path segment is allowed, has: '" + | ||||
| 				wildcard + "' in path '" + fullPath + "'") | ||||
| 		} | ||||
| 
 | ||||
| 		// check if the wildcard has a name | ||||
| 		if len(wildcard) < 2 { | ||||
| 			panic("wildcards must be named with a non-empty name in path '" + fullPath + "'") | ||||
| 		} | ||||
| 
 | ||||
| 		if wildcard[0] == ':' { // param | ||||
| 			if i > 0 { | ||||
| 				// Insert prefix before the current wildcard | ||||
| 				n.path = path[:i] | ||||
| 				path = path[i:] | ||||
| 			} | ||||
| 
 | ||||
| 			child := &node{ | ||||
| 				nType:    param, | ||||
| 				path:     wildcard, | ||||
| 				fullPath: fullPath, | ||||
| 			} | ||||
| 			n.addChild(child) | ||||
| 			n.wildChild = true | ||||
| 			n = child | ||||
| 			n.priority++ | ||||
| 
 | ||||
| 			// if the path doesn't end with the wildcard, then there | ||||
| 			// will be another non-wildcard subpath starting with '/' | ||||
| 			if len(wildcard) < len(path) { | ||||
| 				path = path[len(wildcard):] | ||||
| 
 | ||||
| 				child := &node{ | ||||
| 					priority: 1, | ||||
| 					fullPath: fullPath, | ||||
| 				} | ||||
| 				n.addChild(child) | ||||
| 				n = child | ||||
| 				continue | ||||
| 			} | ||||
| 
 | ||||
| 			// Otherwise we're done. Insert the handle in the new leaf | ||||
| 			n.handlers = handlers | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		// catchAll | ||||
| 		if i+len(wildcard) != len(path) { | ||||
| 			panic("catch-all routes are only allowed at the end of the path in path '" + fullPath + "'") | ||||
| 		} | ||||
| 
 | ||||
| 		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 + "'") | ||||
| 		} | ||||
| 
 | ||||
| 		// currently fixed width 1 for '/' | ||||
| 		i-- | ||||
| 		if path[i] != '/' { | ||||
| 			panic("no / before catch-all in path '" + fullPath + "'") | ||||
| 		} | ||||
| 
 | ||||
| 		n.path = path[:i] | ||||
| 
 | ||||
| 		// First node: catchAll node with empty path | ||||
| 		child := &node{ | ||||
| 			wildChild: true, | ||||
| 			nType:     catchAll, | ||||
| 			fullPath:  fullPath, | ||||
| 		} | ||||
| 
 | ||||
| 		n.addChild(child) | ||||
| 		n.indices = string('/') | ||||
| 		n = child | ||||
| 		n.priority++ | ||||
| 
 | ||||
| 		// second node: node holding the variable | ||||
| 		child = &node{ | ||||
| 			path:     path[i:], | ||||
| 			nType:    catchAll, | ||||
| 			handlers: handlers, | ||||
| 			priority: 1, | ||||
| 			fullPath: fullPath, | ||||
| 		} | ||||
| 		n.children = []*node{child} | ||||
| 
 | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// If no wildcard was found, simply insert the path and handle | ||||
| 	n.path = path | ||||
| 	n.handlers = handlers | ||||
| 	n.fullPath = fullPath | ||||
| } | ||||
| 
 | ||||
| // nodeValue holds return values of (*Node).getValue method | ||||
| type nodeValue struct { | ||||
| 	handlers HandlersChain | ||||
| 	params   *Params | ||||
| 	tsr      bool | ||||
| 	fullPath string | ||||
| } | ||||
| 
 | ||||
| // Returns the handle registered with the given path (key). The values of | ||||
| // wildcards are saved to a map. | ||||
| // If no handle can be found, a TSR (trailing slash redirect) recommendation is | ||||
| // made if a handle exists with an extra (without the) trailing slash for the | ||||
| // given path. | ||||
| func (n *node) getValue(path string, params *Params, unescape bool) (value nodeValue) { | ||||
| 	// path: /abc/123/def | ||||
| 	// level 1 router:abc | ||||
| 	// level 2 router:123 | ||||
| 	// level 3 router:def | ||||
| 	var ( | ||||
| 		skippedPath string | ||||
| 		latestNode  = n // not found `level 2 router` use latestNode | ||||
| 
 | ||||
| 		// match '/' count | ||||
| 		// matchNum < 1: `level 2 router` not found,the current node needs to be equal to latestNode | ||||
| 		// matchNum >= 1: `level (2 or 3 or 4 or ...) router`: Normal handling | ||||
| 		matchNum int // each match will accumulate | ||||
| 	) | ||||
| 	//if path == "/", no need to look for tree node | ||||
| 	if len(path) == 1 { | ||||
| 		matchNum = 1 | ||||
| 	} | ||||
| 
 | ||||
| walk: // Outer loop for walking the tree | ||||
| 	for { | ||||
| 		prefix := n.path | ||||
| 		if len(path) > len(prefix) { | ||||
| 			if path[:len(prefix)] == prefix { | ||||
| 				path = path[len(prefix):] | ||||
| 
 | ||||
| 				// Try all the non-wildcard children first by matching the indices | ||||
| 				idxc := path[0] | ||||
| 				for i, c := range []byte(n.indices) { | ||||
| 					if c == idxc { | ||||
| 						//  strings.HasPrefix(n.children[len(n.children)-1].path, ":") == n.wildChild | ||||
| 						if n.wildChild { | ||||
| 							skippedPath = prefix + path | ||||
| 							latestNode = &node{ | ||||
| 								path:      n.path, | ||||
| 								wildChild: n.wildChild, | ||||
| 								nType:     n.nType, | ||||
| 								priority:  n.priority, | ||||
| 								children:  n.children, | ||||
| 								handlers:  n.handlers, | ||||
| 								fullPath:  n.fullPath, | ||||
| 							} | ||||
| 						} | ||||
| 
 | ||||
| 						n = n.children[i] | ||||
| 
 | ||||
| 						// match '/', If this condition is matched, the next route is found | ||||
| 						if (len(n.fullPath) != 0 && n.wildChild) || path[len(path)-1] == '/' { | ||||
| 							matchNum++ | ||||
| 						} | ||||
| 						continue walk | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				// level 2 router not found,the current node needs to be equal to latestNode | ||||
| 				if matchNum < 1 { | ||||
| 					n = latestNode | ||||
| 				} | ||||
| 
 | ||||
| 				// If there is no wildcard pattern, recommend a redirection | ||||
| 				if !n.wildChild { | ||||
| 					// Nothing found. | ||||
| 					// We can recommend to redirect to the same URL without a | ||||
| 					// trailing slash if a leaf exists for that path. | ||||
| 					value.tsr = path == "/" && n.handlers != nil | ||||
| 					return | ||||
| 				} | ||||
| 
 | ||||
| 				// Handle wildcard child, which is always at the end of the array | ||||
| 				n = n.children[len(n.children)-1] | ||||
| 
 | ||||
| 				switch n.nType { | ||||
| 				case param: | ||||
| 					// Find param end (either '/' or path end) | ||||
| 					end := 0 | ||||
| 					for end < len(path) && path[end] != '/' { | ||||
| 						end++ | ||||
| 					} | ||||
| 
 | ||||
| 					// Save param value | ||||
| 					if params != nil && cap(*params) > 0 { | ||||
| 						if value.params == nil { | ||||
| 							value.params = params | ||||
| 						} | ||||
| 						// Expand slice within preallocated capacity | ||||
| 						i := len(*value.params) | ||||
| 						*value.params = (*value.params)[:i+1] | ||||
| 						val := path[:end] | ||||
| 						if unescape { | ||||
| 							if v, err := url.QueryUnescape(val); err == nil { | ||||
| 								val = v | ||||
| 							} | ||||
| 						} | ||||
| 						(*value.params)[i] = Param{ | ||||
| 							Key:   n.path[1:], | ||||
| 							Value: val, | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					// we need to go deeper! | ||||
| 					if end < len(path) { | ||||
| 						if len(n.children) > 0 { | ||||
| 							path = path[end:] | ||||
| 							n = n.children[0] | ||||
| 							// next node,the latestNode needs to be equal to currentNode and handle next router | ||||
| 							latestNode = n | ||||
| 							// not found router in (level 1 router and handle next node),skippedPath cannot execute | ||||
| 							// example: | ||||
| 							// * /:cc/cc | ||||
| 							// call /a/cc 	     expectations:match/200      Actual:match/200 | ||||
| 							// call /a/dd 	     expectations:unmatch/404    Actual: panic | ||||
| 							// call /addr/dd/aa  expectations:unmatch/404    Actual: panic | ||||
| 							// skippedPath: It can only be executed if the secondary route is not found | ||||
| 							// matchNum: Go to the next level of routing tree node search,need add matchNum | ||||
| 							skippedPath = "" | ||||
| 							matchNum++ | ||||
| 							continue walk | ||||
| 						} | ||||
| 
 | ||||
| 						// ... but we can't | ||||
| 						value.tsr = len(path) == end+1 | ||||
| 						return | ||||
| 					} | ||||
| 
 | ||||
| 					if value.handlers = n.handlers; value.handlers != nil { | ||||
| 						value.fullPath = n.fullPath | ||||
| 						return | ||||
| 					} | ||||
| 					if len(n.children) == 1 { | ||||
| 						// 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 | ||||
| 					} | ||||
| 					return | ||||
| 
 | ||||
| 				case catchAll: | ||||
| 					// Save param value | ||||
| 					if params != nil { | ||||
| 						if value.params == nil { | ||||
| 							value.params = params | ||||
| 						} | ||||
| 						// Expand slice within preallocated capacity | ||||
| 						i := len(*value.params) | ||||
| 						*value.params = (*value.params)[:i+1] | ||||
| 						val := path | ||||
| 						if unescape { | ||||
| 							if v, err := url.QueryUnescape(path); err == nil { | ||||
| 								val = v | ||||
| 							} | ||||
| 						} | ||||
| 						(*value.params)[i] = Param{ | ||||
| 							Key:   n.path[2:], | ||||
| 							Value: val, | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					value.handlers = n.handlers | ||||
| 					value.fullPath = n.fullPath | ||||
| 					return | ||||
| 
 | ||||
| 				default: | ||||
| 					panic("invalid node type") | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if path == prefix { | ||||
| 			// level 2 router not found and latestNode.wildChild is true | ||||
| 			if matchNum < 1 && latestNode.wildChild { | ||||
| 				n = latestNode.children[len(latestNode.children)-1] | ||||
| 			} | ||||
| 			// We should have reached the node containing the handle. | ||||
| 			// Check if this node has a handle registered. | ||||
| 			if value.handlers = n.handlers; value.handlers != nil { | ||||
| 				value.fullPath = n.fullPath | ||||
| 				return | ||||
| 			} | ||||
| 
 | ||||
| 			// If there is no handle for this route, but this route has a | ||||
| 			// wildcard child, there must be a handle for this path with an | ||||
| 			// additional trailing slash | ||||
| 			if path == "/" && n.wildChild && n.nType != root { | ||||
| 				value.tsr = true | ||||
| 				return | ||||
| 			} | ||||
| 
 | ||||
| 			// No handle found. Check if a handle for this path + a | ||||
| 			// trailing slash exists for trailing slash recommendation | ||||
| 			for i, c := range []byte(n.indices) { | ||||
| 				if c == '/' { | ||||
| 					n = n.children[i] | ||||
| 					value.tsr = (len(n.path) == 1 && n.handlers != nil) || | ||||
| 						(n.nType == catchAll && n.children[0].handlers != nil) | ||||
| 					return | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		// path != "/" && skippedPath != "" | ||||
| 		if len(path) != 1 && len(skippedPath) > 0 && strings.HasSuffix(skippedPath, path) { | ||||
| 			path = skippedPath | ||||
| 			n = latestNode | ||||
| 			skippedPath = "" | ||||
| 			continue walk | ||||
| 		} | ||||
| 
 | ||||
| 		// Nothing found. We can recommend to redirect to the same URL with an | ||||
| 		// extra trailing slash if a leaf exists for that path | ||||
| 		value.tsr = path == "/" || | ||||
| 			(len(prefix) == len(path)+1 && n.handlers != nil) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Makes a case-insensitive lookup of the given path and tries to find a handler. | ||||
| // It can optionally also fix trailing slashes. | ||||
| // It returns the case-corrected path and a bool indicating whether the lookup | ||||
| // was successful. | ||||
| func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) ([]byte, bool) { | ||||
| 	const stackBufSize = 128 | ||||
| 
 | ||||
| 	// Use a static sized buffer on the stack in the common case. | ||||
| 	// If the path is too long, allocate a buffer on the heap instead. | ||||
| 	buf := make([]byte, 0, stackBufSize) | ||||
| 	if length := len(path) + 1; length > stackBufSize { | ||||
| 		buf = make([]byte, 0, length) | ||||
| 	} | ||||
| 
 | ||||
| 	ciPath := n.findCaseInsensitivePathRec( | ||||
| 		path, | ||||
| 		buf,       // Preallocate enough memory for new path | ||||
| 		[4]byte{}, // Empty rune buffer | ||||
| 		fixTrailingSlash, | ||||
| 	) | ||||
| 
 | ||||
| 	return ciPath, ciPath != nil | ||||
| } | ||||
| 
 | ||||
| // Shift bytes in array by n bytes left | ||||
| func shiftNRuneBytes(rb [4]byte, n int) [4]byte { | ||||
| 	switch n { | ||||
| 	case 0: | ||||
| 		return rb | ||||
| 	case 1: | ||||
| 		return [4]byte{rb[1], rb[2], rb[3], 0} | ||||
| 	case 2: | ||||
| 		return [4]byte{rb[2], rb[3]} | ||||
| 	case 3: | ||||
| 		return [4]byte{rb[3]} | ||||
| 	default: | ||||
| 		return [4]byte{} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Recursive case-insensitive lookup function used by n.findCaseInsensitivePath | ||||
| func (n *node) findCaseInsensitivePathRec(path string, ciPath []byte, rb [4]byte, fixTrailingSlash bool) []byte { | ||||
| 	npLen := len(n.path) | ||||
| 
 | ||||
| walk: // Outer loop for walking the tree | ||||
| 	for len(path) >= npLen && (npLen == 0 || strings.EqualFold(path[1:npLen], n.path[1:])) { | ||||
| 		// Add common prefix to result | ||||
| 		oldPath := path | ||||
| 		path = path[npLen:] | ||||
| 		ciPath = append(ciPath, n.path...) | ||||
| 
 | ||||
| 		if len(path) == 0 { | ||||
| 			// We should have reached the node containing the handle. | ||||
| 			// Check if this node has a handle registered. | ||||
| 			if n.handlers != nil { | ||||
| 				return ciPath | ||||
| 			} | ||||
| 
 | ||||
| 			// No handle found. | ||||
| 			// Try to fix the path by adding a trailing slash | ||||
| 			if fixTrailingSlash { | ||||
| 				for i, c := range []byte(n.indices) { | ||||
| 					if c == '/' { | ||||
| 						n = n.children[i] | ||||
| 						if (len(n.path) == 1 && n.handlers != nil) || | ||||
| 							(n.nType == catchAll && n.children[0].handlers != nil) { | ||||
| 							return append(ciPath, '/') | ||||
| 						} | ||||
| 						return nil | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			return nil | ||||
| 		} | ||||
| 
 | ||||
| 		// If this node does not have a wildcard (param or catchAll) child, | ||||
| 		// we can just look up the next child node and continue to walk down | ||||
| 		// the tree | ||||
| 		if !n.wildChild { | ||||
| 			// Skip rune bytes already processed | ||||
| 			rb = shiftNRuneBytes(rb, npLen) | ||||
| 
 | ||||
| 			if rb[0] != 0 { | ||||
| 				// Old rune not finished | ||||
| 				idxc := rb[0] | ||||
| 				for i, c := range []byte(n.indices) { | ||||
| 					if c == idxc { | ||||
| 						// continue with child node | ||||
| 						n = n.children[i] | ||||
| 						npLen = len(n.path) | ||||
| 						continue walk | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 				// Process a new rune | ||||
| 				var rv rune | ||||
| 
 | ||||
| 				// Find rune start. | ||||
| 				// Runes are up to 4 byte long, | ||||
| 				// -4 would definitely be another rune. | ||||
| 				var off int | ||||
| 				for max := min(npLen, 3); off < max; off++ { | ||||
| 					if i := npLen - off; utf8.RuneStart(oldPath[i]) { | ||||
| 						// read rune from cached path | ||||
| 						rv, _ = utf8.DecodeRuneInString(oldPath[i:]) | ||||
| 						break | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				// Calculate lowercase bytes of current rune | ||||
| 				lo := unicode.ToLower(rv) | ||||
| 				utf8.EncodeRune(rb[:], lo) | ||||
| 
 | ||||
| 				// Skip already processed bytes | ||||
| 				rb = shiftNRuneBytes(rb, off) | ||||
| 
 | ||||
| 				idxc := rb[0] | ||||
| 				for i, c := range []byte(n.indices) { | ||||
| 					// Lowercase matches | ||||
| 					if c == idxc { | ||||
| 						// must use a recursive approach since both the | ||||
| 						// uppercase byte and the lowercase byte might exist | ||||
| 						// as an index | ||||
| 						if out := n.children[i].findCaseInsensitivePathRec( | ||||
| 							path, ciPath, rb, fixTrailingSlash, | ||||
| 						); out != nil { | ||||
| 							return out | ||||
| 						} | ||||
| 						break | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				// If we found no match, the same for the uppercase rune, | ||||
| 				// if it differs | ||||
| 				if up := unicode.ToUpper(rv); up != lo { | ||||
| 					utf8.EncodeRune(rb[:], up) | ||||
| 					rb = shiftNRuneBytes(rb, off) | ||||
| 
 | ||||
| 					idxc := rb[0] | ||||
| 					for i, c := range []byte(n.indices) { | ||||
| 						// Uppercase matches | ||||
| 						if c == idxc { | ||||
| 							// Continue with child node | ||||
| 							n = n.children[i] | ||||
| 							npLen = len(n.path) | ||||
| 							continue walk | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			// Nothing found. We can recommend to redirect to the same URL | ||||
| 			// without a trailing slash if a leaf exists for that path | ||||
| 			if fixTrailingSlash && path == "/" && n.handlers != nil { | ||||
| 				return ciPath | ||||
| 			} | ||||
| 			return nil | ||||
| 		} | ||||
| 
 | ||||
| 		n = n.children[0] | ||||
| 		switch n.nType { | ||||
| 		case param: | ||||
| 			// Find param end (either '/' or path end) | ||||
| 			end := 0 | ||||
| 			for end < len(path) && path[end] != '/' { | ||||
| 				end++ | ||||
| 			} | ||||
| 
 | ||||
| 			// Add param value to case insensitive path | ||||
| 			ciPath = append(ciPath, path[:end]...) | ||||
| 
 | ||||
| 			// We need to go deeper! | ||||
| 			if end < len(path) { | ||||
| 				if len(n.children) > 0 { | ||||
| 					// Continue with child node | ||||
| 					n = n.children[0] | ||||
| 					npLen = len(n.path) | ||||
| 					path = path[end:] | ||||
| 					continue | ||||
| 				} | ||||
| 
 | ||||
| 				// ... but we can't | ||||
| 				if fixTrailingSlash && len(path) == end+1 { | ||||
| 					return ciPath | ||||
| 				} | ||||
| 				return nil | ||||
| 			} | ||||
| 
 | ||||
| 			if n.handlers != nil { | ||||
| 				return ciPath | ||||
| 			} | ||||
| 
 | ||||
| 			if fixTrailingSlash && len(n.children) == 1 { | ||||
| 				// No handle found. Check if a handle for this path + a | ||||
| 				// trailing slash exists | ||||
| 				n = n.children[0] | ||||
| 				if n.path == "/" && n.handlers != nil { | ||||
| 					return append(ciPath, '/') | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			return nil | ||||
| 
 | ||||
| 		case catchAll: | ||||
| 			return append(ciPath, path...) | ||||
| 
 | ||||
| 		default: | ||||
| 			panic("invalid node type") | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Nothing found. | ||||
| 	// Try to fix the path by adding / removing a trailing slash | ||||
| 	if fixTrailingSlash { | ||||
| 		if path == "/" { | ||||
| 			return ciPath | ||||
| 		} | ||||
| 		if len(path)+1 == npLen && n.path[len(path)] == '/' && | ||||
| 			strings.EqualFold(path[1:], n.path[1:len(path)]) && n.handlers != nil { | ||||
| 			return append(ciPath, n.path...) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										153
									
								
								vendor/github.com/gin-gonic/gin/utils.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								vendor/github.com/gin-gonic/gin/utils.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,153 @@ | |||
| // 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 ( | ||||
| 	"encoding/xml" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"reflect" | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // 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 { | ||||
| 	value := reflect.ValueOf(val) | ||||
| 	if value.Kind() == reflect.Ptr { | ||||
| 		panic(`Bind struct can not be a pointer. Example: | ||||
| 	Use: gin.Bind(Struct{}) instead of gin.Bind(&Struct{}) | ||||
| `) | ||||
| 	} | ||||
| 	typ := value.Type() | ||||
| 
 | ||||
| 	return func(c *Context) { | ||||
| 		obj := reflect.New(typ).Interface() | ||||
| 		if c.Bind(obj) == nil { | ||||
| 			c.Set(BindKey, obj) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // WrapF is a helper function for wrapping http.HandlerFunc and returns a Gin middleware. | ||||
| func WrapF(f http.HandlerFunc) HandlerFunc { | ||||
| 	return func(c *Context) { | ||||
| 		f(c.Writer, c.Request) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // WrapH is a helper function for wrapping http.Handler and returns a Gin middleware. | ||||
| func WrapH(h http.Handler) HandlerFunc { | ||||
| 	return func(c *Context) { | ||||
| 		h.ServeHTTP(c.Writer, c.Request) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // H is a shortcut for map[string]interface{} | ||||
| type H map[string]interface{} | ||||
| 
 | ||||
| // MarshalXML allows type H to be used with xml.Marshal. | ||||
| func (h H) MarshalXML(e *xml.Encoder, start xml.StartElement) error { | ||||
| 	start.Name = xml.Name{ | ||||
| 		Space: "", | ||||
| 		Local: "map", | ||||
| 	} | ||||
| 	if err := e.EncodeToken(start); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for key, value := range h { | ||||
| 		elem := xml.StartElement{ | ||||
| 			Name: xml.Name{Space: "", Local: key}, | ||||
| 			Attr: []xml.Attr{}, | ||||
| 		} | ||||
| 		if err := e.EncodeElement(value, elem); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return e.EncodeToken(xml.EndElement{Name: start.Name}) | ||||
| } | ||||
| 
 | ||||
| func assert1(guard bool, text string) { | ||||
| 	if !guard { | ||||
| 		panic(text) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func filterFlags(content string) string { | ||||
| 	for i, char := range content { | ||||
| 		if char == ' ' || char == ';' { | ||||
| 			return content[:i] | ||||
| 		} | ||||
| 	} | ||||
| 	return content | ||||
| } | ||||
| 
 | ||||
| func chooseData(custom, wildcard interface{}) interface{} { | ||||
| 	if custom != nil { | ||||
| 		return custom | ||||
| 	} | ||||
| 	if wildcard != nil { | ||||
| 		return wildcard | ||||
| 	} | ||||
| 	panic("negotiation config is invalid") | ||||
| } | ||||
| 
 | ||||
| func parseAccept(acceptHeader string) []string { | ||||
| 	parts := strings.Split(acceptHeader, ",") | ||||
| 	out := make([]string, 0, len(parts)) | ||||
| 	for _, part := range parts { | ||||
| 		if i := strings.IndexByte(part, ';'); i > 0 { | ||||
| 			part = part[:i] | ||||
| 		} | ||||
| 		if part = strings.TrimSpace(part); part != "" { | ||||
| 			out = append(out, part) | ||||
| 		} | ||||
| 	} | ||||
| 	return out | ||||
| } | ||||
| 
 | ||||
| func lastChar(str string) uint8 { | ||||
| 	if str == "" { | ||||
| 		panic("The length of the string can't be 0") | ||||
| 	} | ||||
| 	return str[len(str)-1] | ||||
| } | ||||
| 
 | ||||
| func nameOfFunction(f interface{}) string { | ||||
| 	return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name() | ||||
| } | ||||
| 
 | ||||
| func joinPaths(absolutePath, relativePath string) string { | ||||
| 	if relativePath == "" { | ||||
| 		return absolutePath | ||||
| 	} | ||||
| 
 | ||||
| 	finalPath := path.Join(absolutePath, relativePath) | ||||
| 	if lastChar(relativePath) == '/' && lastChar(finalPath) != '/' { | ||||
| 		return finalPath + "/" | ||||
| 	} | ||||
| 	return finalPath | ||||
| } | ||||
| 
 | ||||
| func resolveAddress(addr []string) string { | ||||
| 	switch len(addr) { | ||||
| 	case 0: | ||||
| 		if port := os.Getenv("PORT"); port != "" { | ||||
| 			debugPrint("Environment variable PORT=\"%s\"", port) | ||||
| 			return ":" + port | ||||
| 		} | ||||
| 		debugPrint("Environment variable PORT is undefined. Using port :8080 by default") | ||||
| 		return ":8080" | ||||
| 	case 1: | ||||
| 		return addr[0] | ||||
| 	default: | ||||
| 		panic("too many parameters") | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										8
									
								
								vendor/github.com/gin-gonic/gin/version.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/gin-gonic/gin/version.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| // 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.2" | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue