update
							parent
							
								
									866b2cf1ed
								
							
						
					
					
						commit
						ea6896cf05
					
				
							
								
								
									
										17
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										17
									
								
								go.mod
								
								
								
								
							| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
module git.makemake.in/kzkzzzz/mycommon
 | 
					module git.makemake.in/kzkzzzz/mycommon
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.23.0
 | 
					go 1.24.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/gin-contrib/pprof v1.5.2
 | 
						github.com/gin-contrib/pprof v1.5.2
 | 
				
			||||||
| 
						 | 
					@ -32,13 +32,15 @@ require (
 | 
				
			||||||
	github.com/spf13/viper v1.19.0
 | 
						github.com/spf13/viper v1.19.0
 | 
				
			||||||
	github.com/stretchr/testify v1.10.0
 | 
						github.com/stretchr/testify v1.10.0
 | 
				
			||||||
	go.uber.org/zap v1.24.0
 | 
						go.uber.org/zap v1.24.0
 | 
				
			||||||
	golang.org/x/sync v0.12.0
 | 
						golang.org/x/sync v0.17.0
 | 
				
			||||||
 | 
						golang.org/x/time v0.5.0
 | 
				
			||||||
	google.golang.org/grpc v1.67.1
 | 
						google.golang.org/grpc v1.67.1
 | 
				
			||||||
	gorm.io/driver/mysql v1.5.7
 | 
						gorm.io/driver/mysql v1.5.7
 | 
				
			||||||
	gorm.io/gorm v1.25.12
 | 
						gorm.io/gorm v1.25.12
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
 | 
						github.com/andybalholm/brotli v1.2.0 // indirect
 | 
				
			||||||
	github.com/armon/go-metrics v0.4.1 // indirect
 | 
						github.com/armon/go-metrics v0.4.1 // indirect
 | 
				
			||||||
	github.com/beorn7/perks v1.0.1 // indirect
 | 
						github.com/beorn7/perks v1.0.1 // indirect
 | 
				
			||||||
	github.com/bytedance/sonic v1.13.2 // indirect
 | 
						github.com/bytedance/sonic v1.13.2 // indirect
 | 
				
			||||||
| 
						 | 
					@ -64,6 +66,7 @@ require (
 | 
				
			||||||
	github.com/hashicorp/serf v0.10.1 // indirect
 | 
						github.com/hashicorp/serf v0.10.1 // indirect
 | 
				
			||||||
	github.com/jinzhu/inflection v1.0.0 // indirect
 | 
						github.com/jinzhu/inflection v1.0.0 // indirect
 | 
				
			||||||
	github.com/jinzhu/now v1.1.5 // indirect
 | 
						github.com/jinzhu/now v1.1.5 // indirect
 | 
				
			||||||
 | 
						github.com/klauspost/compress v1.18.0 // indirect
 | 
				
			||||||
	github.com/klauspost/cpuid/v2 v2.2.10 // indirect
 | 
						github.com/klauspost/cpuid/v2 v2.2.10 // indirect
 | 
				
			||||||
	github.com/knadh/koanf/maps v0.1.1 // indirect
 | 
						github.com/knadh/koanf/maps v0.1.1 // indirect
 | 
				
			||||||
	github.com/leodido/go-urn v1.4.0 // indirect
 | 
						github.com/leodido/go-urn v1.4.0 // indirect
 | 
				
			||||||
| 
						 | 
					@ -90,14 +93,16 @@ require (
 | 
				
			||||||
	github.com/subosito/gotenv v1.6.0 // indirect
 | 
						github.com/subosito/gotenv v1.6.0 // indirect
 | 
				
			||||||
	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 | 
						github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 | 
				
			||||||
	github.com/ugorji/go/codec v1.2.12 // indirect
 | 
						github.com/ugorji/go/codec v1.2.12 // indirect
 | 
				
			||||||
 | 
						github.com/valyala/bytebufferpool v1.0.0 // indirect
 | 
				
			||||||
 | 
						github.com/valyala/fasthttp v1.66.0 // indirect
 | 
				
			||||||
	go.uber.org/atomic v1.10.0 // indirect
 | 
						go.uber.org/atomic v1.10.0 // indirect
 | 
				
			||||||
	go.uber.org/multierr v1.9.0 // indirect
 | 
						go.uber.org/multierr v1.9.0 // indirect
 | 
				
			||||||
	golang.org/x/arch v0.15.0 // indirect
 | 
						golang.org/x/arch v0.15.0 // indirect
 | 
				
			||||||
	golang.org/x/crypto v0.36.0 // indirect
 | 
						golang.org/x/crypto v0.42.0 // indirect
 | 
				
			||||||
	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
 | 
						golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
 | 
				
			||||||
	golang.org/x/net v0.37.0 // indirect
 | 
						golang.org/x/net v0.44.0 // indirect
 | 
				
			||||||
	golang.org/x/sys v0.31.0 // indirect
 | 
						golang.org/x/sys v0.36.0 // indirect
 | 
				
			||||||
	golang.org/x/text v0.23.0 // indirect
 | 
						golang.org/x/text v0.29.0 // indirect
 | 
				
			||||||
	google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
 | 
						google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
 | 
				
			||||||
	google.golang.org/protobuf v1.36.5 // indirect
 | 
						google.golang.org/protobuf v1.36.5 // indirect
 | 
				
			||||||
	gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
 | 
						gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										30
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										30
									
								
								go.sum
								
								
								
								
							| 
						 | 
					@ -3,6 +3,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
 | 
				
			||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 | 
					github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 | 
				
			||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 | 
					github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 | 
				
			||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 | 
					github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 | 
				
			||||||
 | 
					github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
 | 
				
			||||||
 | 
					github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
 | 
				
			||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 | 
					github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 | 
				
			||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 | 
					github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 | 
				
			||||||
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
 | 
					github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
 | 
				
			||||||
| 
						 | 
					@ -152,6 +154,8 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
 | 
				
			||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 | 
					github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 | 
				
			||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 | 
					github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 | 
				
			||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 | 
					github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 | 
				
			||||||
 | 
					github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
 | 
				
			||||||
 | 
					github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
 | 
				
			||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 | 
					github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 | 
				
			||||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
 | 
					github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
 | 
				
			||||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
 | 
					github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
 | 
				
			||||||
| 
						 | 
					@ -303,6 +307,10 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
 | 
				
			||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 | 
					github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 | 
				
			||||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
 | 
					github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
 | 
				
			||||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 | 
					github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 | 
				
			||||||
 | 
					github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 | 
				
			||||||
 | 
					github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 | 
				
			||||||
 | 
					github.com/valyala/fasthttp v1.66.0 h1:M87A0Z7EayeyNaV6pfO3tUTUiYO0dZfEJnRGXTVNuyU=
 | 
				
			||||||
 | 
					github.com/valyala/fasthttp v1.66.0/go.mod h1:Y4eC+zwoocmXSVCB1JmhNbYtS7tZPRI2ztPB72EVObs=
 | 
				
			||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
 | 
					go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
 | 
				
			||||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
 | 
					go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
 | 
				
			||||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
 | 
					go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
 | 
				
			||||||
| 
						 | 
					@ -316,8 +324,8 @@ golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
					golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
					golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
 | 
					golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
 | 
				
			||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
 | 
					golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
 | 
				
			||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
 | 
					golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
 | 
				
			||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
 | 
					golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
 | 
				
			||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
 | 
					golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
 | 
				
			||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
				
			||||||
| 
						 | 
					@ -327,15 +335,15 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
 | 
				
			||||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
					golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
					golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
 | 
					golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
 | 
				
			||||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
 | 
					golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
 | 
				
			||||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
 | 
					golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
 | 
					golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
 | 
				
			||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 | 
					golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
| 
						 | 
					@ -357,15 +365,17 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc
 | 
				
			||||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
 | 
					golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
 | 
				
			||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 | 
					golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
 | 
				
			||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
					golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
				
			||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
					golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
				
			||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
					golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
				
			||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
					golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
				
			||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
					golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
				
			||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
 | 
					golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
 | 
				
			||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
 | 
					golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
 | 
				
			||||||
 | 
					golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
 | 
				
			||||||
 | 
					golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
					golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
					golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					package fasthttpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						HeaderUserAgent      = "User-Agent"
 | 
				
			||||||
 | 
						HeaderContentType    = "Content-Type"
 | 
				
			||||||
 | 
						HeaderCookie         = "Cookie"
 | 
				
			||||||
 | 
						HeaderAccept         = "Accept"
 | 
				
			||||||
 | 
						HeaderOrigin         = "Origin"
 | 
				
			||||||
 | 
						HeaderReferer        = "Referer"
 | 
				
			||||||
 | 
						HeaderAcceptLanguage = "Accept-Language"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ContentTypeJSON = "application/json; charset=utf-8"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						MobileUserAgent  = "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/124.0.6367.68 MobileRequest/15E148 Safari/604.1"
 | 
				
			||||||
 | 
						PcUserAgent      = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
 | 
				
			||||||
 | 
						AcceptHtml       = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
 | 
				
			||||||
 | 
						AcceptCNLanguage = "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,366 @@
 | 
				
			||||||
 | 
					package fasthttpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						jsoniter "github.com/json-iterator/go"
 | 
				
			||||||
 | 
						"github.com/valyala/fasthttp"
 | 
				
			||||||
 | 
						"golang.org/x/time/rate"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"net/url"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						defaultClient *HttpClient
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						defaultClient = New()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ReInitDefault(timeout time.Duration) {
 | 
				
			||||||
 | 
						defaultClient = New(WithTimout(timeout))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ReInitDefaultOpt(opts ...ConfigOpt) {
 | 
				
			||||||
 | 
						defaultClient = New(opts...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Client() *HttpClient {
 | 
				
			||||||
 | 
						return defaultClient
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Request struct {
 | 
				
			||||||
 | 
						ctx         context.Context
 | 
				
			||||||
 | 
						header      http.Header
 | 
				
			||||||
 | 
						body        any
 | 
				
			||||||
 | 
						mapQuery    map[string]string
 | 
				
			||||||
 | 
						urlQuery    url.Values
 | 
				
			||||||
 | 
						httpClient  *HttpClient
 | 
				
			||||||
 | 
						contentType string
 | 
				
			||||||
 | 
						noWaitQps   bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type HttpClient struct {
 | 
				
			||||||
 | 
						config     *Config
 | 
				
			||||||
 | 
						client     *fasthttp.Client
 | 
				
			||||||
 | 
						qpsLimiter *rate.Limiter
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func New(opts ...ConfigOpt) *HttpClient {
 | 
				
			||||||
 | 
						config := &Config{}
 | 
				
			||||||
 | 
						for _, opt := range opts {
 | 
				
			||||||
 | 
							opt(config)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if config.timeout <= 0 {
 | 
				
			||||||
 | 
							config.timeout = time.Second * 3
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if config.fasthttpTimeout <= 0 {
 | 
				
			||||||
 | 
							config.fasthttpTimeout = time.Second * 10
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if config.maxConnPerHost <= 0 {
 | 
				
			||||||
 | 
							config.maxConnPerHost = 10000
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if config.client == nil {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							client := &fasthttp.Client{
 | 
				
			||||||
 | 
								TLSConfig: &tls.Config{InsecureSkipVerify: true},
 | 
				
			||||||
 | 
								DialTimeout: (&fasthttp.TCPDialer{
 | 
				
			||||||
 | 
									Concurrency:      0,
 | 
				
			||||||
 | 
									DNSCacheDuration: time.Second * 600,
 | 
				
			||||||
 | 
								}).DialTimeout,
 | 
				
			||||||
 | 
								MaxConnsPerHost:           config.maxConnPerHost,
 | 
				
			||||||
 | 
								MaxIdleConnDuration:       time.Second * 90,
 | 
				
			||||||
 | 
								MaxIdemponentCallAttempts: 5,
 | 
				
			||||||
 | 
								ReadTimeout:               config.fasthttpTimeout + time.Second,
 | 
				
			||||||
 | 
								MaxConnWaitTimeout:        0,
 | 
				
			||||||
 | 
								RetryIfErr: func(req *fasthttp.Request, attempts int, err error) (bool, bool) {
 | 
				
			||||||
 | 
									if errors.Is(err, fasthttp.ErrConnectionClosed) || errors.Is(err, io.EOF) {
 | 
				
			||||||
 | 
										return false, true
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return false, false
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							config.client = client
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hc := &HttpClient{
 | 
				
			||||||
 | 
							config: config,
 | 
				
			||||||
 | 
							client: config.client,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if config.qpsLimiter != nil {
 | 
				
			||||||
 | 
							hc.qpsLimiter = config.qpsLimiter
 | 
				
			||||||
 | 
						} else if config.qps > 0 {
 | 
				
			||||||
 | 
							hc.qpsLimiter = rate.NewLimiter(rate.Every(time.Second/time.Duration(config.qps)), config.qps)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return hc
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *HttpClient) RawClient() *fasthttp.Client {
 | 
				
			||||||
 | 
						return h.client
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *HttpClient) NewRequest(ctx context.Context) *Request {
 | 
				
			||||||
 | 
						r := &Request{
 | 
				
			||||||
 | 
							ctx:        ctx,
 | 
				
			||||||
 | 
							header:     nil,
 | 
				
			||||||
 | 
							mapQuery:   nil,
 | 
				
			||||||
 | 
							httpClient: h,
 | 
				
			||||||
 | 
							urlQuery:   url.Values{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *HttpClient) NewPcRequest(ctx context.Context) *Request {
 | 
				
			||||||
 | 
						r := h.NewRequest(ctx)
 | 
				
			||||||
 | 
						r.SetHeaderPcAgent()
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *HttpClient) NewMobileRequest(ctx context.Context) *Request {
 | 
				
			||||||
 | 
						r := h.NewRequest(ctx)
 | 
				
			||||||
 | 
						r.SetHeaderMobileAgent()
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) SetContentType(contentType string) *Request {
 | 
				
			||||||
 | 
						r.contentType = contentType
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) SetBody(body any) *Request {
 | 
				
			||||||
 | 
						r.body = body
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) SetQueryParam(k string, v string) *Request {
 | 
				
			||||||
 | 
						if r.mapQuery == nil {
 | 
				
			||||||
 | 
							r.mapQuery = make(map[string]string)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						r.mapQuery[k] = v
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) SetQueryParams(params map[string]string) *Request {
 | 
				
			||||||
 | 
						for k, v := range params {
 | 
				
			||||||
 | 
							r.SetQueryParam(k, v)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) SetUrlQueryParam(k string, v string) *Request {
 | 
				
			||||||
 | 
						r.urlQuery.Add(k, v)
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) SetHeader(k, v string) *Request {
 | 
				
			||||||
 | 
						if r.header == nil {
 | 
				
			||||||
 | 
							r.header = http.Header{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						r.header.Set(k, v)
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) SetHeaders(headers map[string]string) *Request {
 | 
				
			||||||
 | 
						for k, v := range headers {
 | 
				
			||||||
 | 
							r.SetHeader(k, v)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) NoWaitQps() *Request {
 | 
				
			||||||
 | 
						r.noWaitQps = true
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) Get(rawUrl string) (*Response, error) {
 | 
				
			||||||
 | 
						return r.Do(http.MethodGet, rawUrl)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) Post(rawUrl string) (*Response, error) {
 | 
				
			||||||
 | 
						return r.Do(http.MethodPost, rawUrl)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var QpsLimitError = fmt.Errorf("qps limit")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) DoTimeout(timeout time.Duration, method, rawUrl string) (*Response, error) {
 | 
				
			||||||
 | 
						if timeout <= time.Millisecond {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("timeout is too small <= 1 millisecond")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.httpClient.config.useCtxTimeout == false {
 | 
				
			||||||
 | 
							return r.doRequest(timeout, method, rawUrl)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx, cancel := context.WithTimeout(r.ctx, timeout)
 | 
				
			||||||
 | 
						defer cancel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type tmpRes struct {
 | 
				
			||||||
 | 
							res *Response
 | 
				
			||||||
 | 
							err error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var resChan = make(chan tmpRes, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							res, err := r.doRequest(r.httpClient.config.fasthttpTimeout, method, rawUrl)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								resChan <- tmpRes{err: err}
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							resChan <- tmpRes{res: res}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						select {
 | 
				
			||||||
 | 
						case <-ctx.Done():
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("request timeout: %s (%s)", timeout, ctx.Err())
 | 
				
			||||||
 | 
						case res := <-resChan:
 | 
				
			||||||
 | 
							return res.res, res.err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) Do(method, rawUrl string) (*Response, error) {
 | 
				
			||||||
 | 
						return r.DoTimeout(r.httpClient.config.timeout, method, rawUrl)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) doRequest(timeout time.Duration, method, rawUrl string) (*Response, error) {
 | 
				
			||||||
 | 
						if r.httpClient.qpsLimiter != nil {
 | 
				
			||||||
 | 
							if r.noWaitQps {
 | 
				
			||||||
 | 
								allow := r.httpClient.qpsLimiter.Allow()
 | 
				
			||||||
 | 
								if !allow {
 | 
				
			||||||
 | 
									return nil, QpsLimitError
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								err := r.httpClient.qpsLimiter.Wait(r.ctx)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req := fasthttp.AcquireRequest()
 | 
				
			||||||
 | 
						resp := fasthttp.AcquireResponse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							fasthttp.ReleaseRequest(req)
 | 
				
			||||||
 | 
							fasthttp.ReleaseResponse(resp)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var reqBody []byte
 | 
				
			||||||
 | 
						if r.body != nil {
 | 
				
			||||||
 | 
							switch v := r.body.(type) {
 | 
				
			||||||
 | 
							case string:
 | 
				
			||||||
 | 
								reqBody = []byte(v)
 | 
				
			||||||
 | 
							case []byte:
 | 
				
			||||||
 | 
								reqBody = v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								marshal, err := jsoniter.Marshal(r.body)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								reqBody = marshal
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req.SetBody(reqBody)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reqUrl, err := url.Parse(rawUrl)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("parse url err: %s (%s)", err.Error(), rawUrl)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						urlQuery := reqUrl.Query()
 | 
				
			||||||
 | 
						for k, v := range r.mapQuery {
 | 
				
			||||||
 | 
							urlQuery.Add(k, v)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for k, v := range r.urlQuery {
 | 
				
			||||||
 | 
							urlQuery[k] = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(urlQuery) > 0 {
 | 
				
			||||||
 | 
							reqUrl.RawQuery = urlQuery.Encode()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req.SetRequestURI(reqUrl.String())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//if len(urlQuery) > 0 {
 | 
				
			||||||
 | 
						//	req.URI().SetQueryString(urlQuery.Encode())
 | 
				
			||||||
 | 
						//}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.contentType != "" {
 | 
				
			||||||
 | 
							req.Header.Set("Content-Type", r.contentType)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for k := range r.header {
 | 
				
			||||||
 | 
							req.Header.Set(k, r.header.Get(k))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						req.Header.SetMethod(method)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = r.httpClient.client.DoTimeout(req, resp, timeout)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if errors.Is(err, fasthttp.ErrTimeout) {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("req err: %s (%s)", err, reqUrl.String())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tmpBody := resp.Body()
 | 
				
			||||||
 | 
						body := make([]byte, len(tmpBody))
 | 
				
			||||||
 | 
						copy(body, tmpBody)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.httpClient.config.noCheckStatus == false {
 | 
				
			||||||
 | 
							if resp.StatusCode() != http.StatusOK {
 | 
				
			||||||
 | 
								return nil, fmt.Errorf("status code err: %d (%s)", resp.StatusCode(), body)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						copyHeader := &fasthttp.ResponseHeader{}
 | 
				
			||||||
 | 
						resp.Header.CopyTo(copyHeader)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res := &Response{
 | 
				
			||||||
 | 
							Header: copyHeader,
 | 
				
			||||||
 | 
							body:   body,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return res, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) SetHeaderPcAgent() *Request {
 | 
				
			||||||
 | 
						r.SetHeader(HeaderUserAgent, PcUserAgent)
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) SetHeaderMobileAgent() *Request {
 | 
				
			||||||
 | 
						r.SetHeader(HeaderUserAgent, MobileUserAgent)
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Request) SetHeaderAcceptHtml() *Request {
 | 
				
			||||||
 | 
						r.SetHeader(HeaderAccept, AcceptHtml)
 | 
				
			||||||
 | 
						return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Response struct {
 | 
				
			||||||
 | 
						Header *fasthttp.ResponseHeader
 | 
				
			||||||
 | 
						body   []byte
 | 
				
			||||||
 | 
						//Response *http.Response
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *Response) GetBody() []byte {
 | 
				
			||||||
 | 
						return r.body
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,39 @@
 | 
				
			||||||
 | 
					package fasthttpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestClient(t *testing.T) {
 | 
				
			||||||
 | 
						client := New(WithUseCtxTimeout(true), WithTimout(time.Second*5))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reqUrl := "http://127.0.0.1:18001/swap-instructions"
 | 
				
			||||||
 | 
						res, err := client.NewRequest(context.Background()).
 | 
				
			||||||
 | 
							SetQueryParams(map[string]string{
 | 
				
			||||||
 | 
								"a":    "b",
 | 
				
			||||||
 | 
								"name": "qwe123",
 | 
				
			||||||
 | 
								"time": "100",
 | 
				
			||||||
 | 
							}).
 | 
				
			||||||
 | 
							SetContentType(ContentTypeJSON).
 | 
				
			||||||
 | 
							SetHeaders(map[string]string{
 | 
				
			||||||
 | 
								"Api": "ok",
 | 
				
			||||||
 | 
							}).
 | 
				
			||||||
 | 
							SetBody(map[string]any{
 | 
				
			||||||
 | 
								"hello": "world",
 | 
				
			||||||
 | 
								"id":    5,
 | 
				
			||||||
 | 
							}).
 | 
				
			||||||
 | 
							Post(reqUrl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Println(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Printf("%+v\n", string(res.GetBody()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Println(res.Header.String())
 | 
				
			||||||
 | 
						fmt.Println(res.Header.StatusCode())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,84 @@
 | 
				
			||||||
 | 
					package fasthttpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/valyala/fasthttp"
 | 
				
			||||||
 | 
						"golang.org/x/time/rate"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type (
 | 
				
			||||||
 | 
						Config struct {
 | 
				
			||||||
 | 
							timeout         time.Duration
 | 
				
			||||||
 | 
							client          *fasthttp.Client
 | 
				
			||||||
 | 
							noCheckStatus   bool
 | 
				
			||||||
 | 
							qps             int
 | 
				
			||||||
 | 
							qpsLimiter      *rate.Limiter
 | 
				
			||||||
 | 
							maxConnPerHost  int
 | 
				
			||||||
 | 
							fasthttpTimeout time.Duration
 | 
				
			||||||
 | 
							useCtxTimeout   bool
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ConfigOpt func(c *Config)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithTimout(v time.Duration) ConfigOpt {
 | 
				
			||||||
 | 
						return func(c *Config) {
 | 
				
			||||||
 | 
							c.timeout = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithUseCtxTimeout(v bool) ConfigOpt {
 | 
				
			||||||
 | 
						return func(c *Config) {
 | 
				
			||||||
 | 
							c.useCtxTimeout = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithFasthttpimout(v time.Duration) ConfigOpt {
 | 
				
			||||||
 | 
						return func(c *Config) {
 | 
				
			||||||
 | 
							c.fasthttpTimeout = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithClient(v *fasthttp.Client) ConfigOpt {
 | 
				
			||||||
 | 
						return func(c *Config) {
 | 
				
			||||||
 | 
							c.client = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithMaxConnPerHost(v int) ConfigOpt {
 | 
				
			||||||
 | 
						return func(c *Config) {
 | 
				
			||||||
 | 
							c.maxConnPerHost = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//func WithRedirectFn(v func(req *http.Request, via []*http.Request) error) ConfigOpt {
 | 
				
			||||||
 | 
					//	return func(c *Config) {
 | 
				
			||||||
 | 
					//		c.redirectFn = v
 | 
				
			||||||
 | 
					//	}
 | 
				
			||||||
 | 
					//}
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//func WithNoRedirect() ConfigOpt {
 | 
				
			||||||
 | 
					//	return func(c *Config) {
 | 
				
			||||||
 | 
					//		c.redirectFn = func(req *http.Request, via []*http.Request) error {
 | 
				
			||||||
 | 
					//			return http.ErrUseLastResponse
 | 
				
			||||||
 | 
					//		}
 | 
				
			||||||
 | 
					//	}
 | 
				
			||||||
 | 
					//}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithNoCheckStatus(v bool) ConfigOpt {
 | 
				
			||||||
 | 
						return func(c *Config) {
 | 
				
			||||||
 | 
							c.noCheckStatus = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithQps(v int) ConfigOpt {
 | 
				
			||||||
 | 
						return func(c *Config) {
 | 
				
			||||||
 | 
							c.qps = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WithQpsLimiter(v *rate.Limiter) ConfigOpt {
 | 
				
			||||||
 | 
						return func(c *Config) {
 | 
				
			||||||
 | 
							c.qpsLimiter = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue