Compare commits
4 Commits
b1f0c375c6
...
0d9bd79582
Author | SHA1 | Date | |
---|---|---|---|
0d9bd79582 | |||
2adc293678 | |||
0fa2d41f52 | |||
bf3be98a9a |
20
go.mod
20
go.mod
@ -1,32 +1,32 @@
|
|||||||
module git.paulbsd.com/paulbsd/qrz
|
module git.paulbsd.com/paulbsd/qrz
|
||||||
|
|
||||||
go 1.21
|
go 1.22
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/antchfx/htmlquery v1.3.0
|
github.com/antchfx/htmlquery v1.3.1
|
||||||
github.com/antchfx/xpath v1.2.5 // indirect
|
github.com/antchfx/xpath v1.3.0 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/labstack/echo/v4 v4.11.2
|
github.com/labstack/echo/v4 v4.12.0
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||||
github.com/onsi/gomega v1.23.0 // indirect
|
github.com/onsi/gomega v1.23.0 // indirect
|
||||||
github.com/robfig/cron v1.2.0
|
github.com/robfig/cron v1.2.0
|
||||||
golang.org/x/crypto v0.14.0 // indirect
|
golang.org/x/crypto v0.22.0 // indirect
|
||||||
golang.org/x/net v0.17.0
|
golang.org/x/net v0.24.0
|
||||||
golang.org/x/sys v0.13.0 // indirect
|
golang.org/x/sys v0.19.0 // indirect
|
||||||
golang.org/x/text v0.13.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
xorm.io/builder v0.3.13 // indirect
|
xorm.io/builder v0.3.13 // indirect
|
||||||
xorm.io/xorm v1.3.4
|
xorm.io/xorm v1.3.9
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/labstack/gommon v0.4.0 // indirect
|
github.com/labstack/gommon v0.4.2 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
29
go.sum
29
go.sum
@ -19,11 +19,15 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
|
|||||||
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/antchfx/htmlquery v1.3.0 h1:5I5yNFOVI+egyia5F2s/5Do2nFWxJz41Tr3DyfKD25E=
|
github.com/antchfx/htmlquery v1.3.0 h1:5I5yNFOVI+egyia5F2s/5Do2nFWxJz41Tr3DyfKD25E=
|
||||||
github.com/antchfx/htmlquery v1.3.0/go.mod h1:zKPDVTMhfOmcwxheXUsx4rKJy8KEY/PU6eXr/2SebQ8=
|
github.com/antchfx/htmlquery v1.3.0/go.mod h1:zKPDVTMhfOmcwxheXUsx4rKJy8KEY/PU6eXr/2SebQ8=
|
||||||
|
github.com/antchfx/htmlquery v1.3.1 h1:wm0LxjLMsZhRHfQKKZscDf2COyH4vDYA3wyH+qZ+Ylc=
|
||||||
|
github.com/antchfx/htmlquery v1.3.1/go.mod h1:PTj+f1V2zksPlwNt7uVvZPsxpKNa7mlVliCRxLX6Nx8=
|
||||||
github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||||
github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY=
|
github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY=
|
||||||
github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||||
github.com/antchfx/xpath v1.2.5 h1:hqZ+wtQ+KIOV/S3bGZcIhpgYC26um2bZYP2KVGcR7VY=
|
github.com/antchfx/xpath v1.2.5 h1:hqZ+wtQ+KIOV/S3bGZcIhpgYC26um2bZYP2KVGcR7VY=
|
||||||
github.com/antchfx/xpath v1.2.5/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
github.com/antchfx/xpath v1.2.5/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||||
|
github.com/antchfx/xpath v1.3.0 h1:nTMlzGAK3IJ0bPpME2urTuFL76o4A96iYvoKFHRXJgc=
|
||||||
|
github.com/antchfx/xpath v1.3.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
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=
|
||||||
@ -255,8 +259,14 @@ github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUU
|
|||||||
github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ=
|
github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ=
|
||||||
github.com/labstack/echo/v4 v4.11.2 h1:T+cTLQxWCDfqDEoydYm5kCobjmHwOwcv4OJAPHilmdE=
|
github.com/labstack/echo/v4 v4.11.2 h1:T+cTLQxWCDfqDEoydYm5kCobjmHwOwcv4OJAPHilmdE=
|
||||||
github.com/labstack/echo/v4 v4.11.2/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws=
|
github.com/labstack/echo/v4 v4.11.2/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws=
|
||||||
|
github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
|
||||||
|
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
|
||||||
|
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
|
||||||
|
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
|
||||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||||
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||||
|
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||||
|
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
@ -488,6 +498,10 @@ golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
|||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||||
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
|
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||||
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
@ -523,6 +537,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||||
@ -535,6 +550,10 @@ golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
|
|||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
|
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||||
|
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
|
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -599,6 +618,10 @@ golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
|||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||||
|
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
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/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
@ -622,6 +645,8 @@ golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
|||||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -849,3 +874,7 @@ xorm.io/xorm v1.3.3 h1:L5/GOhvgMcwJYYRjzPf3lTTTf6JcaTd1Mb9A/Iqvccw=
|
|||||||
xorm.io/xorm v1.3.3/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
|
xorm.io/xorm v1.3.3/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
|
||||||
xorm.io/xorm v1.3.4 h1:vWFKzR3DhGUDl5b4srhUjhDwjxkZAc4C7BFszpu0swI=
|
xorm.io/xorm v1.3.4 h1:vWFKzR3DhGUDl5b4srhUjhDwjxkZAc4C7BFszpu0swI=
|
||||||
xorm.io/xorm v1.3.4/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
|
xorm.io/xorm v1.3.4/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
|
||||||
|
xorm.io/xorm v1.3.8 h1:CJmplmWqfSRpLWSPMmqz+so8toBp3m7ehuRehIWedZo=
|
||||||
|
xorm.io/xorm v1.3.8/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=
|
||||||
|
xorm.io/xorm v1.3.9 h1:TUovzS0ko+IQ1XnNLfs5dqK1cJl1H5uHpWbWqAQ04nU=
|
||||||
|
xorm.io/xorm v1.3.9/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=
|
||||||
|
16
vendor/github.com/antchfx/htmlquery/.travis.yml
generated
vendored
16
vendor/github.com/antchfx/htmlquery/.travis.yml
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.9.x
|
|
||||||
- 1.12.x
|
|
||||||
- 1.13.x
|
|
||||||
|
|
||||||
install:
|
|
||||||
- go get golang.org/x/net/html/charset
|
|
||||||
- go get golang.org/x/net/html
|
|
||||||
- go get github.com/antchfx/xpath
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
- go get github.com/golang/groupcache
|
|
||||||
|
|
||||||
script:
|
|
||||||
- $HOME/gopath/bin/goveralls -service=travis-ci
|
|
35
vendor/github.com/antchfx/htmlquery/README.md
generated
vendored
35
vendor/github.com/antchfx/htmlquery/README.md
generated
vendored
@ -1,12 +1,10 @@
|
|||||||
htmlquery
|
# htmlquery
|
||||||
====
|
|
||||||
[![Build Status](https://travis-ci.org/antchfx/htmlquery.svg?branch=master)](https://travis-ci.org/antchfx/htmlquery)
|
[![Build Status](https://github.com/antchfx/htmlquery/actions/workflows/testing.yml/badge.svg)](https://github.com/antchfx/htmlquery/actions/workflows/testing.yml)
|
||||||
[![Coverage Status](https://coveralls.io/repos/github/antchfx/htmlquery/badge.svg?branch=master)](https://coveralls.io/github/antchfx/htmlquery?branch=master)
|
|
||||||
[![GoDoc](https://godoc.org/github.com/antchfx/htmlquery?status.svg)](https://godoc.org/github.com/antchfx/htmlquery)
|
[![GoDoc](https://godoc.org/github.com/antchfx/htmlquery?status.svg)](https://godoc.org/github.com/antchfx/htmlquery)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/antchfx/htmlquery)](https://goreportcard.com/report/github.com/antchfx/htmlquery)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/antchfx/htmlquery)](https://goreportcard.com/report/github.com/antchfx/htmlquery)
|
||||||
|
|
||||||
Overview
|
# Overview
|
||||||
====
|
|
||||||
|
|
||||||
`htmlquery` is an XPath query package for HTML, lets you extract data or evaluate from HTML documents by an XPath expression.
|
`htmlquery` is an XPath query package for HTML, lets you extract data or evaluate from HTML documents by an XPath expression.
|
||||||
|
|
||||||
@ -14,23 +12,21 @@ Overview
|
|||||||
|
|
||||||
You can visit this page to learn about the supported XPath(1.0/2.0) syntax. https://github.com/antchfx/xpath
|
You can visit this page to learn about the supported XPath(1.0/2.0) syntax. https://github.com/antchfx/xpath
|
||||||
|
|
||||||
XPath query packages for Go
|
# XPath query packages for Go
|
||||||
===
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| ------------------------------------------------- | ----------------------------------------- |
|
| ------------------------------------------------- | ----------------------------------------- |
|
||||||
| [htmlquery](https://github.com/antchfx/htmlquery) | XPath query package for the HTML document |
|
| [htmlquery](https://github.com/antchfx/htmlquery) | XPath query package for the HTML document |
|
||||||
| [xmlquery](https://github.com/antchfx/xmlquery) | XPath query package for the XML document |
|
| [xmlquery](https://github.com/antchfx/xmlquery) | XPath query package for the XML document |
|
||||||
| [jsonquery](https://github.com/antchfx/jsonquery) | XPath query package for the JSON document |
|
| [jsonquery](https://github.com/antchfx/jsonquery) | XPath query package for the JSON document |
|
||||||
|
|
||||||
Installation
|
# Installation
|
||||||
====
|
|
||||||
|
|
||||||
```
|
```
|
||||||
go get github.com/antchfx/htmlquery
|
go get github.com/antchfx/htmlquery
|
||||||
```
|
```
|
||||||
|
|
||||||
Getting Started
|
# Getting Started
|
||||||
====
|
|
||||||
|
|
||||||
#### Query, returns matched elements or error.
|
#### Query, returns matched elements or error.
|
||||||
|
|
||||||
@ -78,7 +74,7 @@ list := htmlquery.Find(doc, "//a[@href]")
|
|||||||
```go
|
```go
|
||||||
list := htmlquery.Find(doc, "//a/@href")
|
list := htmlquery.Find(doc, "//a/@href")
|
||||||
for _ , n := range list{
|
for _ , n := range list{
|
||||||
fmt.Println(htmlquery.SelectAttr(n, "href")) // output @href value
|
fmt.Println(htmlquery.InnerText(n)) // output @href value
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -89,6 +85,7 @@ a := htmlquery.FindOne(doc, "//a[3]")
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Find children element (img) under A `href` and print the source
|
### Find children element (img) under A `href` and print the source
|
||||||
|
|
||||||
```go
|
```go
|
||||||
a := htmlquery.FindOne(doc, "//a")
|
a := htmlquery.FindOne(doc, "//a")
|
||||||
img := htmlquery.FindOne(a, "//img")
|
img := htmlquery.FindOne(a, "//img")
|
||||||
@ -103,9 +100,7 @@ v := expr.Evaluate(htmlquery.CreateXPathNavigator(doc)).(float64)
|
|||||||
fmt.Printf("total count is %f", v)
|
fmt.Printf("total count is %f", v)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Quick Starts
|
||||||
Quick Starts
|
|
||||||
===
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func main() {
|
func main() {
|
||||||
@ -127,9 +122,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# FAQ
|
||||||
FAQ
|
|
||||||
====
|
|
||||||
|
|
||||||
#### `Find()` vs `QueryAll()`, which is better?
|
#### `Find()` vs `QueryAll()`, which is better?
|
||||||
|
|
||||||
@ -158,6 +151,6 @@ BenchmarkDisableSelectorCache-4 500000 3162 ns/op
|
|||||||
htmlquery.DisableSelectorCache = true
|
htmlquery.DisableSelectorCache = true
|
||||||
```
|
```
|
||||||
|
|
||||||
Questions
|
# Questions
|
||||||
===
|
|
||||||
Please let me know if you have any questions.
|
Please let me know if you have any questions.
|
||||||
|
39
vendor/github.com/antchfx/htmlquery/query.go
generated
vendored
39
vendor/github.com/antchfx/htmlquery/query.go
generated
vendored
@ -5,6 +5,8 @@ package htmlquery
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"compress/gzip"
|
||||||
|
"compress/zlib"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -88,15 +90,44 @@ func QuerySelectorAll(top *html.Node, selector *xpath.Expr) []*html.Node {
|
|||||||
return elems
|
return elems
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadURL loads the HTML document from the specified URL.
|
// LoadURL loads the HTML document from the specified URL. Default enabling gzip on a HTTP request.
|
||||||
func LoadURL(url string) (*html.Node, error) {
|
func LoadURL(url string) (*html.Node, error) {
|
||||||
resp, err := http.Get(url)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
// Enable gzip compression.
|
||||||
|
req.Header.Add("Accept-Encoding", "gzip")
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var reader io.ReadCloser
|
||||||
|
|
||||||
r, err := charset.NewReader(resp.Body, resp.Header.Get("Content-Type"))
|
defer func() {
|
||||||
|
if reader != nil {
|
||||||
|
reader.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
encoding := resp.Header.Get("Content-Encoding")
|
||||||
|
switch encoding {
|
||||||
|
case "gzip":
|
||||||
|
reader, err = gzip.NewReader(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case "deflate":
|
||||||
|
reader, err = zlib.NewReader(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case "":
|
||||||
|
reader = resp.Body
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("%s compression is not support", encoding)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := charset.NewReader(reader, resp.Header.Get("Content-Type"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
12
vendor/github.com/antchfx/xpath/.travis.yml
generated
vendored
12
vendor/github.com/antchfx/xpath/.travis.yml
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.6
|
|
||||||
- 1.9
|
|
||||||
- '1.10'
|
|
||||||
|
|
||||||
install:
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
|
|
||||||
script:
|
|
||||||
- $HOME/gopath/bin/goveralls -service=travis-ci
|
|
130
vendor/github.com/antchfx/xpath/README.md
generated
vendored
130
vendor/github.com/antchfx/xpath/README.md
generated
vendored
@ -1,14 +1,13 @@
|
|||||||
XPath
|
# XPath
|
||||||
====
|
|
||||||
[![GoDoc](https://godoc.org/github.com/antchfx/xpath?status.svg)](https://godoc.org/github.com/antchfx/xpath)
|
[![GoDoc](https://godoc.org/github.com/antchfx/xpath?status.svg)](https://godoc.org/github.com/antchfx/xpath)
|
||||||
[![Coverage Status](https://coveralls.io/repos/github/antchfx/xpath/badge.svg?branch=master)](https://coveralls.io/github/antchfx/xpath?branch=master)
|
[![Coverage Status](https://coveralls.io/repos/github/antchfx/xpath/badge.svg?branch=master)](https://coveralls.io/github/antchfx/xpath?branch=master)
|
||||||
[![Build Status](https://travis-ci.org/antchfx/xpath.svg?branch=master)](https://travis-ci.org/antchfx/xpath)
|
[![Build Status](https://github.com/antchfx/xpath/actions/workflows/testing.yml/badge.svg)](https://github.com/antchfx/xpath/actions/workflows/testing.yml)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/antchfx/xpath)](https://goreportcard.com/report/github.com/antchfx/xpath)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/antchfx/xpath)](https://goreportcard.com/report/github.com/antchfx/xpath)
|
||||||
|
|
||||||
XPath is Go package provides selecting nodes from XML, HTML or other documents using XPath expression.
|
XPath is Go package provides selecting nodes from XML, HTML or other documents using XPath expression.
|
||||||
|
|
||||||
Implementation
|
# Implementation
|
||||||
===
|
|
||||||
|
|
||||||
- [htmlquery](https://github.com/antchfx/htmlquery) - an XPath query package for HTML document
|
- [htmlquery](https://github.com/antchfx/htmlquery) - an XPath query package for HTML document
|
||||||
|
|
||||||
@ -16,8 +15,7 @@ Implementation
|
|||||||
|
|
||||||
- [jsonquery](https://github.com/antchfx/jsonquery) - an XPath query package for JSON document
|
- [jsonquery](https://github.com/antchfx/jsonquery) - an XPath query package for JSON document
|
||||||
|
|
||||||
Supported Features
|
# Supported Features
|
||||||
===
|
|
||||||
|
|
||||||
#### The basic XPath patterns.
|
#### The basic XPath patterns.
|
||||||
|
|
||||||
@ -63,11 +61,14 @@ Supported Features
|
|||||||
|
|
||||||
- `child::*` : The child axis selects children of the current node.
|
- `child::*` : The child axis selects children of the current node.
|
||||||
|
|
||||||
|
- `child::node()`: Selects all the children of the context node.
|
||||||
|
- `child::text()`: Selects all text node children of the context node.
|
||||||
|
|
||||||
- `descendant::*` : The descendant axis selects descendants of the current node. It is equivalent to '//'.
|
- `descendant::*` : The descendant axis selects descendants of the current node. It is equivalent to '//'.
|
||||||
|
|
||||||
- `descendant-or-self::*` : Selects descendants including the current node.
|
- `descendant-or-self::*` : Selects descendants including the current node.
|
||||||
|
|
||||||
- `attribute::*` : Selects attributes of the current element. It is equivalent to @*
|
- `attribute::*` : Selects attributes of the current element. It is equivalent to @\*
|
||||||
|
|
||||||
- `following-sibling::*` : Selects nodes after the current node.
|
- `following-sibling::*` : Selects nodes after the current node.
|
||||||
|
|
||||||
@ -87,27 +88,27 @@ Supported Features
|
|||||||
|
|
||||||
#### Expressions
|
#### Expressions
|
||||||
|
|
||||||
The gxpath supported three types: number, boolean, string.
|
The gxpath supported three types: number, boolean, string.
|
||||||
|
|
||||||
- `path` : Selects nodes based on the path.
|
- `path` : Selects nodes based on the path.
|
||||||
|
|
||||||
- `a = b` : Standard comparisons.
|
- `a = b` : Standard comparisons.
|
||||||
|
|
||||||
* a = b True if a equals b.
|
- `a = b` : True if a equals b.
|
||||||
* a != b True if a is not equal to b.
|
- `a != b` : True if a is not equal to b.
|
||||||
* a < b True if a is less than b.
|
- `a < b` : True if a is less than b.
|
||||||
* a <= b True if a is less than or equal to b.
|
- `a <= b` : True if a is less than or equal to b.
|
||||||
* a > b True if a is greater than b.
|
- `a > b` : True if a is greater than b.
|
||||||
* a >= b True if a is greater than or equal to b.
|
- `a >= b` : True if a is greater than or equal to b.
|
||||||
|
|
||||||
- `a + b` : Arithmetic expressions.
|
- `a + b` : Arithmetic expressions.
|
||||||
|
|
||||||
* `- a` Unary minus
|
- `- a` Unary minus
|
||||||
* a + b Add
|
- `a + b` : Addition
|
||||||
* a - b Substract
|
- `a - b` : Subtraction
|
||||||
* a * b Multiply
|
- `a * b` : Multiplication
|
||||||
* a div b Divide
|
- `a div b` : Division
|
||||||
* a mod b Floating point mod, like Java.
|
- `a mod b` : Modulus (division remainder)
|
||||||
|
|
||||||
- `a or b` : Boolean `or` operation.
|
- `a or b` : Boolean `or` operation.
|
||||||
|
|
||||||
@ -118,48 +119,49 @@ Supported Features
|
|||||||
- `fun(arg1, ..., argn)` : Function calls:
|
- `fun(arg1, ..., argn)` : Function calls:
|
||||||
|
|
||||||
| Function | Supported |
|
| Function | Supported |
|
||||||
| --- | --- |
|
| ----------------------- | --------- |
|
||||||
`boolean()`| ✓ |
|
| `boolean()` | ✓ |
|
||||||
`ceiling()`| ✓ |
|
| `ceiling()` | ✓ |
|
||||||
`choose()`| ✗ |
|
| `choose()` | ✗ |
|
||||||
`concat()`| ✓ |
|
| `concat()` | ✓ |
|
||||||
`contains()`| ✓ |
|
| `contains()` | ✓ |
|
||||||
`count()`| ✓ |
|
| `count()` | ✓ |
|
||||||
`current()`| ✗ |
|
| `current()` | ✗ |
|
||||||
`document()`| ✗ |
|
| `document()` | ✗ |
|
||||||
`element-available()`| ✗ |
|
| `element-available()` | ✗ |
|
||||||
`ends-with()`| ✓ |
|
| `ends-with()` | ✓ |
|
||||||
`false()`| ✓ |
|
| `false()` | ✓ |
|
||||||
`floor()`| ✓ |
|
| `floor()` | ✓ |
|
||||||
`format-number()`| ✗ |
|
| `format-number()` | ✗ |
|
||||||
`function-available()`| ✗ |
|
| `function-available()` | ✗ |
|
||||||
`generate-id()`| ✗ |
|
| `generate-id()` | ✗ |
|
||||||
`id()`| ✗ |
|
| `id()` | ✗ |
|
||||||
`key()`| ✗ |
|
| `key()` | ✗ |
|
||||||
`lang()`| ✗ |
|
| `lang()` | ✗ |
|
||||||
`last()`| ✓ |
|
| `last()` | ✓ |
|
||||||
`local-name()`| ✓ |
|
| `local-name()` | ✓ |
|
||||||
`matches()`| ✓ |
|
| `lower-case()`[^1] | ✓ |
|
||||||
`name()`| ✓ |
|
| `matches()` | ✓ |
|
||||||
`namespace-uri()`| ✓ |
|
| `name()` | ✓ |
|
||||||
`normalize-space()`| ✓ |
|
| `namespace-uri()` | ✓ |
|
||||||
`not()`| ✓ |
|
| `normalize-space()` | ✓ |
|
||||||
`number()`| ✓ |
|
| `not()` | ✓ |
|
||||||
`position()`| ✓ |
|
| `number()` | ✓ |
|
||||||
`replace()`| ✓ |
|
| `position()` | ✓ |
|
||||||
`reverse()`| ✓ |
|
| `replace()` | ✓ |
|
||||||
`round()`| ✓ |
|
| `reverse()` | ✓ |
|
||||||
`starts-with()`| ✓ |
|
| `round()` | ✓ |
|
||||||
`string()`| ✓ |
|
| `starts-with()` | ✓ |
|
||||||
`string-join()`[^1]| ✓ |
|
| `string()` | ✓ |
|
||||||
`string-length()`| ✓ |
|
| `string-join()`[^1] | ✓ |
|
||||||
`substring()`| ✓ |
|
| `string-length()` | ✓ |
|
||||||
`substring-after()`| ✓ |
|
| `substring()` | ✓ |
|
||||||
`substring-before()`| ✓ |
|
| `substring-after()` | ✓ |
|
||||||
`sum()`| ✓ |
|
| `substring-before()` | ✓ |
|
||||||
`system-property()`| ✗ |
|
| `sum()` | ✓ |
|
||||||
`translate()`| ✓ |
|
| `system-property()` | ✗ |
|
||||||
`true()`| ✓ |
|
| `translate()` | ✓ |
|
||||||
`unparsed-entity-url()` | ✗ |
|
| `true()` | ✓ |
|
||||||
|
| `unparsed-entity-url()` | ✗ |
|
||||||
|
|
||||||
[^1]: XPath-2.0 expression
|
[^1]: XPath-2.0 expression
|
381
vendor/github.com/antchfx/xpath/build.go
generated
vendored
381
vendor/github.com/antchfx/xpath/build.go
generated
vendored
@ -7,15 +7,39 @@ import (
|
|||||||
|
|
||||||
type flag int
|
type flag int
|
||||||
|
|
||||||
const (
|
var flagsEnum = struct {
|
||||||
noneFlag flag = iota
|
None flag
|
||||||
filterFlag
|
SmartDesc flag
|
||||||
)
|
PosFilter flag
|
||||||
|
Filter flag
|
||||||
|
Condition flag
|
||||||
|
}{
|
||||||
|
None: 0,
|
||||||
|
SmartDesc: 1,
|
||||||
|
PosFilter: 2,
|
||||||
|
Filter: 4,
|
||||||
|
Condition: 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
type builderProp int
|
||||||
|
|
||||||
|
var builderProps = struct {
|
||||||
|
None builderProp
|
||||||
|
PosFilter builderProp
|
||||||
|
HasPosition builderProp
|
||||||
|
HasLast builderProp
|
||||||
|
NonFlat builderProp
|
||||||
|
}{
|
||||||
|
None: 0,
|
||||||
|
PosFilter: 1,
|
||||||
|
HasPosition: 2,
|
||||||
|
HasLast: 4,
|
||||||
|
NonFlat: 8,
|
||||||
|
}
|
||||||
|
|
||||||
// builder provides building an XPath expressions.
|
// builder provides building an XPath expressions.
|
||||||
type builder struct {
|
type builder struct {
|
||||||
depth int
|
parseDepth int
|
||||||
flag flag
|
|
||||||
firstInput query
|
firstInput query
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,23 +87,26 @@ func axisPredicate(root *axisNode) func(NodeNavigator) bool {
|
|||||||
return predicate
|
return predicate
|
||||||
}
|
}
|
||||||
|
|
||||||
// processAxisNode processes a query for the XPath axis node.
|
// processAxis processes a query for the XPath axis node.
|
||||||
func (b *builder) processAxisNode(root *axisNode) (query, error) {
|
func (b *builder) processAxis(root *axisNode, flags flag, props *builderProp) (query, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
qyInput query
|
qyInput query
|
||||||
qyOutput query
|
qyOutput query
|
||||||
predicate = axisPredicate(root)
|
|
||||||
)
|
)
|
||||||
|
b.firstInput = nil
|
||||||
|
predicate := axisPredicate(root)
|
||||||
|
|
||||||
if root.Input == nil {
|
if root.Input == nil {
|
||||||
qyInput = &contextQuery{}
|
qyInput = &contextQuery{}
|
||||||
|
*props = builderProps.None
|
||||||
} else {
|
} else {
|
||||||
|
inputFlags := flagsEnum.None
|
||||||
if root.AxeType == "child" && (root.Input.Type() == nodeAxis) {
|
if root.AxeType == "child" && (root.Input.Type() == nodeAxis) {
|
||||||
if input := root.Input.(*axisNode); input.AxeType == "descendant-or-self" {
|
if input := root.Input.(*axisNode); input.AxeType == "descendant-or-self" {
|
||||||
var qyGrandInput query
|
var qyGrandInput query
|
||||||
if input.Input != nil {
|
if input.Input != nil {
|
||||||
qyGrandInput, _ = b.processNode(input.Input)
|
qyGrandInput, _ = b.processNode(input.Input, flagsEnum.SmartDesc, props)
|
||||||
} else {
|
} else {
|
||||||
qyGrandInput = &contextQuery{}
|
qyGrandInput = &contextQuery{}
|
||||||
}
|
}
|
||||||
@ -94,14 +121,14 @@ func (b *builder) processAxisNode(root *axisNode) (query, error) {
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
// fix `//*[contains(@id,"food")]//*[contains(@id,"food")]`, see https://github.com/antchfx/htmlquery/issues/52
|
qyOutput = &descendantQuery{name: root.LocalName, Input: qyGrandInput, Predicate: filter, Self: false}
|
||||||
// Skip the current node(Self:false) for the next descendants nodes.
|
*props |= builderProps.NonFlat
|
||||||
_, ok := qyGrandInput.(*contextQuery)
|
|
||||||
qyOutput = &descendantQuery{Input: qyGrandInput, Predicate: filter, Self: ok}
|
|
||||||
return qyOutput, nil
|
return qyOutput, nil
|
||||||
}
|
}
|
||||||
|
} else if ((flags & flagsEnum.Filter) == 0) && (root.AxeType == "descendant" || root.AxeType == "descendant-or-self") {
|
||||||
|
inputFlags |= flagsEnum.SmartDesc
|
||||||
}
|
}
|
||||||
qyInput, err = b.processNode(root.Input)
|
qyInput, err = b.processNode(root.Input, inputFlags, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -109,11 +136,13 @@ func (b *builder) processAxisNode(root *axisNode) (query, error) {
|
|||||||
|
|
||||||
switch root.AxeType {
|
switch root.AxeType {
|
||||||
case "ancestor":
|
case "ancestor":
|
||||||
qyOutput = &ancestorQuery{Input: qyInput, Predicate: predicate}
|
qyOutput = &ancestorQuery{name: root.LocalName, Input: qyInput, Predicate: predicate}
|
||||||
|
*props |= builderProps.NonFlat
|
||||||
case "ancestor-or-self":
|
case "ancestor-or-self":
|
||||||
qyOutput = &ancestorQuery{Input: qyInput, Predicate: predicate, Self: true}
|
qyOutput = &ancestorQuery{name: root.LocalName, Input: qyInput, Predicate: predicate, Self: true}
|
||||||
|
*props |= builderProps.NonFlat
|
||||||
case "attribute":
|
case "attribute":
|
||||||
qyOutput = &attributeQuery{Input: qyInput, Predicate: predicate}
|
qyOutput = &attributeQuery{name: root.LocalName, Input: qyInput, Predicate: predicate}
|
||||||
case "child":
|
case "child":
|
||||||
filter := func(n NodeNavigator) bool {
|
filter := func(n NodeNavigator) bool {
|
||||||
v := predicate(n)
|
v := predicate(n)
|
||||||
@ -127,19 +156,35 @@ func (b *builder) processAxisNode(root *axisNode) (query, error) {
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
qyOutput = &childQuery{Input: qyInput, Predicate: filter}
|
if (*props & builderProps.NonFlat) == 0 {
|
||||||
|
qyOutput = &childQuery{name: root.LocalName, Input: qyInput, Predicate: filter}
|
||||||
|
} else {
|
||||||
|
qyOutput = &cachedChildQuery{name: root.LocalName, Input: qyInput, Predicate: filter}
|
||||||
|
}
|
||||||
case "descendant":
|
case "descendant":
|
||||||
qyOutput = &descendantQuery{Input: qyInput, Predicate: predicate}
|
if (flags & flagsEnum.SmartDesc) != flagsEnum.None {
|
||||||
|
qyOutput = &descendantOverDescendantQuery{name: root.LocalName, Input: qyInput, MatchSelf: false, Predicate: predicate}
|
||||||
|
} else {
|
||||||
|
qyOutput = &descendantQuery{name: root.LocalName, Input: qyInput, Predicate: predicate}
|
||||||
|
}
|
||||||
|
*props |= builderProps.NonFlat
|
||||||
case "descendant-or-self":
|
case "descendant-or-self":
|
||||||
qyOutput = &descendantQuery{Input: qyInput, Predicate: predicate, Self: true}
|
if (flags & flagsEnum.SmartDesc) != flagsEnum.None {
|
||||||
|
qyOutput = &descendantOverDescendantQuery{name: root.LocalName, Input: qyInput, MatchSelf: true, Predicate: predicate}
|
||||||
|
} else {
|
||||||
|
qyOutput = &descendantQuery{name: root.LocalName, Input: qyInput, Predicate: predicate, Self: true}
|
||||||
|
}
|
||||||
|
*props |= builderProps.NonFlat
|
||||||
case "following":
|
case "following":
|
||||||
qyOutput = &followingQuery{Input: qyInput, Predicate: predicate}
|
qyOutput = &followingQuery{Input: qyInput, Predicate: predicate}
|
||||||
|
*props |= builderProps.NonFlat
|
||||||
case "following-sibling":
|
case "following-sibling":
|
||||||
qyOutput = &followingQuery{Input: qyInput, Predicate: predicate, Sibling: true}
|
qyOutput = &followingQuery{Input: qyInput, Predicate: predicate, Sibling: true}
|
||||||
case "parent":
|
case "parent":
|
||||||
qyOutput = &parentQuery{Input: qyInput, Predicate: predicate}
|
qyOutput = &parentQuery{Input: qyInput, Predicate: predicate}
|
||||||
case "preceding":
|
case "preceding":
|
||||||
qyOutput = &precedingQuery{Input: qyInput, Predicate: predicate}
|
qyOutput = &precedingQuery{Input: qyInput, Predicate: predicate}
|
||||||
|
*props |= builderProps.NonFlat
|
||||||
case "preceding-sibling":
|
case "preceding-sibling":
|
||||||
qyOutput = &precedingQuery{Input: qyInput, Predicate: predicate, Sibling: true}
|
qyOutput = &precedingQuery{Input: qyInput, Predicate: predicate, Sibling: true}
|
||||||
case "self":
|
case "self":
|
||||||
@ -153,56 +198,182 @@ func (b *builder) processAxisNode(root *axisNode) (query, error) {
|
|||||||
return qyOutput, nil
|
return qyOutput, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// processFilterNode builds query for the XPath filter predicate.
|
func canBeNumber(q query) bool {
|
||||||
func (b *builder) processFilterNode(root *filterNode) (query, error) {
|
if q.ValueType() != xpathResultType.Any {
|
||||||
b.flag |= filterFlag
|
return q.ValueType() == xpathResultType.Number
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
qyInput, err := b.processNode(root.Input)
|
// processFilterNode builds query for the XPath filter predicate.
|
||||||
|
func (b *builder) processFilter(root *filterNode, flags flag, props *builderProp) (query, error) {
|
||||||
|
first := (flags & flagsEnum.Filter) == 0
|
||||||
|
|
||||||
|
qyInput, err := b.processNode(root.Input, (flags | flagsEnum.Filter), props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qyCond, err := b.processNode(root.Condition)
|
firstInput := b.firstInput
|
||||||
|
|
||||||
|
var propsCond builderProp
|
||||||
|
cond, err := b.processNode(root.Condition, flags, &propsCond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qyOutput := &filterQuery{Input: qyInput, Predicate: qyCond}
|
|
||||||
return qyOutput, nil
|
// Checking whether is number
|
||||||
|
if canBeNumber(cond) || ((propsCond & (builderProps.HasPosition | builderProps.HasLast)) != 0) {
|
||||||
|
propsCond |= builderProps.HasPosition
|
||||||
|
flags |= flagsEnum.PosFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
if root.Input.Type() != nodeFilter {
|
||||||
|
*props &= ^builderProps.PosFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propsCond & builderProps.HasPosition) != 0 {
|
||||||
|
*props |= builderProps.PosFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
merge := (qyInput.Properties() & queryProps.Merge) != 0
|
||||||
|
if (propsCond & builderProps.HasPosition) != builderProps.None {
|
||||||
|
if (propsCond & builderProps.HasLast) != 0 {
|
||||||
|
// https://github.com/antchfx/xpath/issues/76
|
||||||
|
// https://github.com/antchfx/xpath/issues/78
|
||||||
|
if qyFunc, ok := cond.(*functionQuery); ok {
|
||||||
|
switch qyFunc.Input.(type) {
|
||||||
|
case *filterQuery:
|
||||||
|
cond = &lastQuery{Input: qyFunc.Input}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if first && firstInput != nil {
|
||||||
|
if merge && ((*props & builderProps.PosFilter) != 0) {
|
||||||
|
qyInput = &filterQuery{Input: qyInput, Predicate: cond, NoPosition: false}
|
||||||
|
|
||||||
|
var (
|
||||||
|
rootQuery = &contextQuery{}
|
||||||
|
parent query
|
||||||
|
)
|
||||||
|
switch axisQuery := firstInput.(type) {
|
||||||
|
case *ancestorQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
case *attributeQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
case *childQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
case *cachedChildQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
case *descendantQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
case *followingQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
case *precedingQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
case *parentQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
case *selfQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
case *groupQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
case *descendantOverDescendantQuery:
|
||||||
|
if _, ok := axisQuery.Input.(*contextQuery); !ok {
|
||||||
|
parent = axisQuery.Input
|
||||||
|
axisQuery.Input = rootQuery
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.firstInput = nil
|
||||||
|
if parent != nil {
|
||||||
|
return &mergeQuery{Input: parent, Child: qyInput}, nil
|
||||||
|
}
|
||||||
|
return qyInput, nil
|
||||||
|
}
|
||||||
|
b.firstInput = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
resultQuery := &filterQuery{
|
||||||
|
Input: qyInput,
|
||||||
|
Predicate: cond,
|
||||||
|
NoPosition: (propsCond & builderProps.HasPosition) == 0,
|
||||||
|
}
|
||||||
|
return resultQuery, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// processFunctionNode processes query for the XPath function node.
|
// processFunctionNode processes query for the XPath function node.
|
||||||
func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
func (b *builder) processFunction(root *functionNode, props *builderProp) (query, error) {
|
||||||
|
// Reset builder props
|
||||||
|
*props = builderProps.None
|
||||||
|
|
||||||
var qyOutput query
|
var qyOutput query
|
||||||
switch root.FuncName {
|
switch root.FuncName {
|
||||||
|
case "lower-case":
|
||||||
|
arg, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
qyOutput = &functionQuery{Input: arg, Func: lowerCaseFunc}
|
||||||
case "starts-with":
|
case "starts-with":
|
||||||
arg1, err := b.processNode(root.Args[0])
|
arg1, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
arg2, err := b.processNode(root.Args[1])
|
arg2, err := b.processNode(root.Args[1], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: startwithFunc(arg1, arg2)}
|
qyOutput = &functionQuery{Func: startwithFunc(arg1, arg2)}
|
||||||
case "ends-with":
|
case "ends-with":
|
||||||
arg1, err := b.processNode(root.Args[0])
|
arg1, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
arg2, err := b.processNode(root.Args[1])
|
arg2, err := b.processNode(root.Args[1], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: endwithFunc(arg1, arg2)}
|
qyOutput = &functionQuery{Func: endwithFunc(arg1, arg2)}
|
||||||
case "contains":
|
case "contains":
|
||||||
arg1, err := b.processNode(root.Args[0])
|
arg1, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
arg2, err := b.processNode(root.Args[1])
|
arg2, err := b.processNode(root.Args[1], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: containsFunc(arg1, arg2)}
|
qyOutput = &functionQuery{Func: containsFunc(arg1, arg2)}
|
||||||
case "matches":
|
case "matches":
|
||||||
//matches(string , pattern)
|
//matches(string , pattern)
|
||||||
if len(root.Args) != 2 {
|
if len(root.Args) != 2 {
|
||||||
@ -212,10 +383,10 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
arg1, arg2 query
|
arg1, arg2 query
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if arg1, err = b.processNode(root.Args[0]); err != nil {
|
if arg1, err = b.processNode(root.Args[0], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if arg2, err = b.processNode(root.Args[1]); err != nil {
|
if arg2, err = b.processNode(root.Args[1], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Issue #92, testing the regular expression before.
|
// Issue #92, testing the regular expression before.
|
||||||
@ -224,7 +395,7 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
return nil, fmt.Errorf("matches() got error. %v", err)
|
return nil, fmt.Errorf("matches() got error. %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: matchesFunc(arg1, arg2)}
|
qyOutput = &functionQuery{Func: matchesFunc(arg1, arg2)}
|
||||||
case "substring":
|
case "substring":
|
||||||
//substring( string , start [, length] )
|
//substring( string , start [, length] )
|
||||||
if len(root.Args) < 2 {
|
if len(root.Args) < 2 {
|
||||||
@ -234,18 +405,18 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
arg1, arg2, arg3 query
|
arg1, arg2, arg3 query
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if arg1, err = b.processNode(root.Args[0]); err != nil {
|
if arg1, err = b.processNode(root.Args[0], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if arg2, err = b.processNode(root.Args[1]); err != nil {
|
if arg2, err = b.processNode(root.Args[1], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(root.Args) == 3 {
|
if len(root.Args) == 3 {
|
||||||
if arg3, err = b.processNode(root.Args[2]); err != nil {
|
if arg3, err = b.processNode(root.Args[2], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: substringFunc(arg1, arg2, arg3)}
|
qyOutput = &functionQuery{Func: substringFunc(arg1, arg2, arg3)}
|
||||||
case "substring-before", "substring-after":
|
case "substring-before", "substring-after":
|
||||||
//substring-xxxx( haystack, needle )
|
//substring-xxxx( haystack, needle )
|
||||||
if len(root.Args) != 2 {
|
if len(root.Args) != 2 {
|
||||||
@ -255,14 +426,13 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
arg1, arg2 query
|
arg1, arg2 query
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if arg1, err = b.processNode(root.Args[0]); err != nil {
|
if arg1, err = b.processNode(root.Args[0], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if arg2, err = b.processNode(root.Args[1]); err != nil {
|
if arg2, err = b.processNode(root.Args[1], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{
|
qyOutput = &functionQuery{
|
||||||
Input: b.firstInput,
|
|
||||||
Func: substringIndFunc(arg1, arg2, root.FuncName == "substring-after"),
|
Func: substringIndFunc(arg1, arg2, root.FuncName == "substring-after"),
|
||||||
}
|
}
|
||||||
case "string-length":
|
case "string-length":
|
||||||
@ -270,16 +440,16 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
if len(root.Args) < 1 {
|
if len(root.Args) < 1 {
|
||||||
return nil, errors.New("xpath: string-length function must have at least one parameter")
|
return nil, errors.New("xpath: string-length function must have at least one parameter")
|
||||||
}
|
}
|
||||||
arg1, err := b.processNode(root.Args[0])
|
arg1, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: stringLengthFunc(arg1)}
|
qyOutput = &functionQuery{Func: stringLengthFunc(arg1)}
|
||||||
case "normalize-space":
|
case "normalize-space":
|
||||||
if len(root.Args) == 0 {
|
if len(root.Args) == 0 {
|
||||||
return nil, errors.New("xpath: normalize-space function must have at least one parameter")
|
return nil, errors.New("xpath: normalize-space function must have at least one parameter")
|
||||||
}
|
}
|
||||||
argQuery, err := b.processNode(root.Args[0])
|
argQuery, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -293,16 +463,16 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
arg1, arg2, arg3 query
|
arg1, arg2, arg3 query
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if arg1, err = b.processNode(root.Args[0]); err != nil {
|
if arg1, err = b.processNode(root.Args[0], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if arg2, err = b.processNode(root.Args[1]); err != nil {
|
if arg2, err = b.processNode(root.Args[1], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if arg3, err = b.processNode(root.Args[2]); err != nil {
|
if arg3, err = b.processNode(root.Args[2], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: replaceFunc(arg1, arg2, arg3)}
|
qyOutput = &functionQuery{Func: replaceFunc(arg1, arg2, arg3)}
|
||||||
case "translate":
|
case "translate":
|
||||||
//translate( string , string, string )
|
//translate( string , string, string )
|
||||||
if len(root.Args) != 3 {
|
if len(root.Args) != 3 {
|
||||||
@ -312,21 +482,21 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
arg1, arg2, arg3 query
|
arg1, arg2, arg3 query
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if arg1, err = b.processNode(root.Args[0]); err != nil {
|
if arg1, err = b.processNode(root.Args[0], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if arg2, err = b.processNode(root.Args[1]); err != nil {
|
if arg2, err = b.processNode(root.Args[1], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if arg3, err = b.processNode(root.Args[2]); err != nil {
|
if arg3, err = b.processNode(root.Args[2], flagsEnum.None, props); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: translateFunc(arg1, arg2, arg3)}
|
qyOutput = &functionQuery{Func: translateFunc(arg1, arg2, arg3)}
|
||||||
case "not":
|
case "not":
|
||||||
if len(root.Args) == 0 {
|
if len(root.Args) == 0 {
|
||||||
return nil, errors.New("xpath: not function must have at least one parameter")
|
return nil, errors.New("xpath: not function must have at least one parameter")
|
||||||
}
|
}
|
||||||
argQuery, err := b.processNode(root.Args[0])
|
argQuery, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -340,46 +510,46 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if len(root.Args) == 1 {
|
if len(root.Args) == 1 {
|
||||||
arg, err = b.processNode(root.Args[0])
|
arg, err = b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch root.FuncName {
|
switch root.FuncName {
|
||||||
case "name":
|
case "name":
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: nameFunc(arg)}
|
qyOutput = &functionQuery{Func: nameFunc(arg)}
|
||||||
case "local-name":
|
case "local-name":
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: localNameFunc(arg)}
|
qyOutput = &functionQuery{Func: localNameFunc(arg)}
|
||||||
case "namespace-uri":
|
case "namespace-uri":
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: namespaceFunc(arg)}
|
qyOutput = &functionQuery{Func: namespaceFunc(arg)}
|
||||||
}
|
}
|
||||||
case "true", "false":
|
case "true", "false":
|
||||||
val := root.FuncName == "true"
|
val := root.FuncName == "true"
|
||||||
qyOutput = &functionQuery{
|
qyOutput = &functionQuery{
|
||||||
Input: b.firstInput,
|
|
||||||
Func: func(_ query, _ iterator) interface{} {
|
Func: func(_ query, _ iterator) interface{} {
|
||||||
return val
|
return val
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
case "last":
|
case "last":
|
||||||
switch typ := b.firstInput.(type) {
|
//switch typ := b.firstInput.(type) {
|
||||||
case *groupQuery, *filterQuery:
|
//case *groupQuery, *filterQuery:
|
||||||
// https://github.com/antchfx/xpath/issues/76
|
// https://github.com/antchfx/xpath/issues/76
|
||||||
// https://github.com/antchfx/xpath/issues/78
|
// https://github.com/antchfx/xpath/issues/78
|
||||||
qyOutput = &lastQuery{Input: typ}
|
//qyOutput = &lastQuery{Input: typ}
|
||||||
default:
|
//default:
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: lastFunc}
|
qyOutput = &functionQuery{Func: lastFunc}
|
||||||
}
|
//}
|
||||||
|
*props |= builderProps.HasLast
|
||||||
case "position":
|
case "position":
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: positionFunc}
|
qyOutput = &functionQuery{Func: positionFunc}
|
||||||
|
*props |= builderProps.HasPosition
|
||||||
case "boolean", "number", "string":
|
case "boolean", "number", "string":
|
||||||
inp := b.firstInput
|
var inp query
|
||||||
if len(root.Args) > 1 {
|
if len(root.Args) > 1 {
|
||||||
return nil, fmt.Errorf("xpath: %s function must have at most one parameter", root.FuncName)
|
return nil, fmt.Errorf("xpath: %s function must have at most one parameter", root.FuncName)
|
||||||
}
|
}
|
||||||
if len(root.Args) == 1 {
|
if len(root.Args) == 1 {
|
||||||
argQuery, err := b.processNode(root.Args[0])
|
argQuery, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -396,13 +566,10 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
}
|
}
|
||||||
qyOutput = f
|
qyOutput = f
|
||||||
case "count":
|
case "count":
|
||||||
//if b.firstInput == nil {
|
|
||||||
// return nil, errors.New("xpath: expression must evaluate to node-set")
|
|
||||||
//}
|
|
||||||
if len(root.Args) == 0 {
|
if len(root.Args) == 0 {
|
||||||
return nil, fmt.Errorf("xpath: count(node-sets) function must with have parameters node-sets")
|
return nil, fmt.Errorf("xpath: count(node-sets) function must with have parameters node-sets")
|
||||||
}
|
}
|
||||||
argQuery, err := b.processNode(root.Args[0])
|
argQuery, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -411,7 +578,7 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
if len(root.Args) == 0 {
|
if len(root.Args) == 0 {
|
||||||
return nil, fmt.Errorf("xpath: sum(node-sets) function must with have parameters node-sets")
|
return nil, fmt.Errorf("xpath: sum(node-sets) function must with have parameters node-sets")
|
||||||
}
|
}
|
||||||
argQuery, err := b.processNode(root.Args[0])
|
argQuery, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -420,7 +587,7 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
if len(root.Args) == 0 {
|
if len(root.Args) == 0 {
|
||||||
return nil, fmt.Errorf("xpath: ceiling(node-sets) function must with have parameters node-sets")
|
return nil, fmt.Errorf("xpath: ceiling(node-sets) function must with have parameters node-sets")
|
||||||
}
|
}
|
||||||
argQuery, err := b.processNode(root.Args[0])
|
argQuery, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -440,18 +607,18 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
}
|
}
|
||||||
var args []query
|
var args []query
|
||||||
for _, v := range root.Args {
|
for _, v := range root.Args {
|
||||||
q, err := b.processNode(v)
|
q, err := b.processNode(v, flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
args = append(args, q)
|
args = append(args, q)
|
||||||
}
|
}
|
||||||
qyOutput = &functionQuery{Input: b.firstInput, Func: concatFunc(args...)}
|
qyOutput = &functionQuery{Func: concatFunc(args...)}
|
||||||
case "reverse":
|
case "reverse":
|
||||||
if len(root.Args) == 0 {
|
if len(root.Args) == 0 {
|
||||||
return nil, fmt.Errorf("xpath: reverse(node-sets) function must with have parameters node-sets")
|
return nil, fmt.Errorf("xpath: reverse(node-sets) function must with have parameters node-sets")
|
||||||
}
|
}
|
||||||
argQuery, err := b.processNode(root.Args[0])
|
argQuery, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -460,11 +627,11 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
if len(root.Args) != 2 {
|
if len(root.Args) != 2 {
|
||||||
return nil, fmt.Errorf("xpath: string-join(node-sets, separator) function requires node-set and argument")
|
return nil, fmt.Errorf("xpath: string-join(node-sets, separator) function requires node-set and argument")
|
||||||
}
|
}
|
||||||
argQuery, err := b.processNode(root.Args[0])
|
argQuery, err := b.processNode(root.Args[0], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
arg1, err := b.processNode(root.Args[1])
|
arg1, err := b.processNode(root.Args[1], flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -472,18 +639,29 @@ func (b *builder) processFunctionNode(root *functionNode) (query, error) {
|
|||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("not yet support this function %s()", root.FuncName)
|
return nil, fmt.Errorf("not yet support this function %s()", root.FuncName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if funcQuery, ok := qyOutput.(*functionQuery); ok && funcQuery.Input == nil {
|
||||||
|
funcQuery.Input = b.firstInput
|
||||||
|
}
|
||||||
return qyOutput, nil
|
return qyOutput, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *builder) processOperatorNode(root *operatorNode) (query, error) {
|
func (b *builder) processOperator(root *operatorNode, props *builderProp) (query, error) {
|
||||||
left, err := b.processNode(root.Left)
|
var (
|
||||||
|
leftProp builderProp
|
||||||
|
rightProp builderProp
|
||||||
|
)
|
||||||
|
|
||||||
|
left, err := b.processNode(root.Left, flagsEnum.None, &leftProp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
right, err := b.processNode(root.Right)
|
right, err := b.processNode(root.Right, flagsEnum.None, &rightProp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
*props = leftProp | rightProp
|
||||||
|
|
||||||
var qyOutput query
|
var qyOutput query
|
||||||
switch root.Op {
|
switch root.Op {
|
||||||
case "+", "-", "*", "div", "mod": // Numeric operator
|
case "+", "-", "*", "div", "mod": // Numeric operator
|
||||||
@ -525,41 +703,45 @@ func (b *builder) processOperatorNode(root *operatorNode) (query, error) {
|
|||||||
}
|
}
|
||||||
qyOutput = &booleanQuery{Left: left, Right: right, IsOr: isOr}
|
qyOutput = &booleanQuery{Left: left, Right: right, IsOr: isOr}
|
||||||
case "|":
|
case "|":
|
||||||
|
*props |= builderProps.NonFlat
|
||||||
qyOutput = &unionQuery{Left: left, Right: right}
|
qyOutput = &unionQuery{Left: left, Right: right}
|
||||||
}
|
}
|
||||||
return qyOutput, nil
|
return qyOutput, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *builder) processNode(root node) (q query, err error) {
|
func (b *builder) processNode(root node, flags flag, props *builderProp) (q query, err error) {
|
||||||
if b.depth = b.depth + 1; b.depth > 1024 {
|
if b.parseDepth = b.parseDepth + 1; b.parseDepth > 1024 {
|
||||||
err = errors.New("the xpath expressions is too complex")
|
err = errors.New("the xpath expressions is too complex")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
*props = builderProps.None
|
||||||
switch root.Type() {
|
switch root.Type() {
|
||||||
case nodeConstantOperand:
|
case nodeConstantOperand:
|
||||||
n := root.(*operandNode)
|
n := root.(*operandNode)
|
||||||
q = &constantQuery{Val: n.Val}
|
q = &constantQuery{Val: n.Val}
|
||||||
case nodeRoot:
|
case nodeRoot:
|
||||||
q = &contextQuery{Root: true}
|
q = &absoluteQuery{}
|
||||||
case nodeAxis:
|
case nodeAxis:
|
||||||
q, err = b.processAxisNode(root.(*axisNode))
|
q, err = b.processAxis(root.(*axisNode), flags, props)
|
||||||
b.firstInput = q
|
b.firstInput = q
|
||||||
case nodeFilter:
|
case nodeFilter:
|
||||||
q, err = b.processFilterNode(root.(*filterNode))
|
q, err = b.processFilter(root.(*filterNode), flags, props)
|
||||||
b.firstInput = q
|
b.firstInput = q
|
||||||
case nodeFunction:
|
case nodeFunction:
|
||||||
q, err = b.processFunctionNode(root.(*functionNode))
|
q, err = b.processFunction(root.(*functionNode), props)
|
||||||
case nodeOperator:
|
case nodeOperator:
|
||||||
q, err = b.processOperatorNode(root.(*operatorNode))
|
q, err = b.processOperator(root.(*operatorNode), props)
|
||||||
case nodeGroup:
|
case nodeGroup:
|
||||||
q, err = b.processNode(root.(*groupNode).Input)
|
q, err = b.processNode(root.(*groupNode).Input, flagsEnum.None, props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q = &groupQuery{Input: q}
|
q = &groupQuery{Input: q}
|
||||||
|
if b.firstInput == nil {
|
||||||
b.firstInput = q
|
b.firstInput = q
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
b.parseDepth--
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,5 +761,6 @@ func build(expr string, namespaces map[string]string) (q query, err error) {
|
|||||||
}()
|
}()
|
||||||
root := parse(expr, namespaces)
|
root := parse(expr, namespaces)
|
||||||
b := &builder{}
|
b := &builder{}
|
||||||
return b.processNode(root)
|
props := builderProps.None
|
||||||
|
return b.processNode(root, flagsEnum.None, &props)
|
||||||
}
|
}
|
||||||
|
6
vendor/github.com/antchfx/xpath/func.go
generated
vendored
6
vendor/github.com/antchfx/xpath/func.go
generated
vendored
@ -645,3 +645,9 @@ func stringJoinFunc(arg1 query) func(query, iterator) interface{} {
|
|||||||
return strings.Join(parts, separator)
|
return strings.Join(parts, separator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lower-case is XPATH function that converts a string to lower case.
|
||||||
|
func lowerCaseFunc(q query, t iterator) interface{} {
|
||||||
|
v := functionArgs(q).Evaluate(t)
|
||||||
|
return strings.ToLower(asString(t, v))
|
||||||
|
}
|
||||||
|
56
vendor/github.com/antchfx/xpath/operator.go
generated
vendored
56
vendor/github.com/antchfx/xpath/operator.go
generated
vendored
@ -1,40 +1,12 @@
|
|||||||
package xpath
|
package xpath
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The XPath number operator function list.
|
// The XPath number operator function list.
|
||||||
|
|
||||||
// valueType is a return value type.
|
|
||||||
type valueType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
booleanType valueType = iota
|
|
||||||
numberType
|
|
||||||
stringType
|
|
||||||
nodeSetType
|
|
||||||
)
|
|
||||||
|
|
||||||
func getValueType(i interface{}) valueType {
|
|
||||||
v := reflect.ValueOf(i)
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Float64:
|
|
||||||
return numberType
|
|
||||||
case reflect.String:
|
|
||||||
return stringType
|
|
||||||
case reflect.Bool:
|
|
||||||
return booleanType
|
|
||||||
default:
|
|
||||||
if _, ok := i.(query); ok {
|
|
||||||
return nodeSetType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic(fmt.Errorf("xpath unknown value type: %v", v.Kind()))
|
|
||||||
}
|
|
||||||
|
|
||||||
type logical func(iterator, string, interface{}, interface{}) bool
|
type logical func(iterator, string, interface{}, interface{}) bool
|
||||||
|
|
||||||
var logicalFuncs = [][]logical{
|
var logicalFuncs = [][]logical{
|
||||||
@ -228,50 +200,50 @@ func cmpBooleanBoolean(t iterator, op string, m, n interface{}) bool {
|
|||||||
|
|
||||||
// eqFunc is an `=` operator.
|
// eqFunc is an `=` operator.
|
||||||
func eqFunc(t iterator, m, n interface{}) interface{} {
|
func eqFunc(t iterator, m, n interface{}) interface{} {
|
||||||
t1 := getValueType(m)
|
t1 := getXPathType(m)
|
||||||
t2 := getValueType(n)
|
t2 := getXPathType(n)
|
||||||
return logicalFuncs[t1][t2](t, "=", m, n)
|
return logicalFuncs[t1][t2](t, "=", m, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// gtFunc is an `>` operator.
|
// gtFunc is an `>` operator.
|
||||||
func gtFunc(t iterator, m, n interface{}) interface{} {
|
func gtFunc(t iterator, m, n interface{}) interface{} {
|
||||||
t1 := getValueType(m)
|
t1 := getXPathType(m)
|
||||||
t2 := getValueType(n)
|
t2 := getXPathType(n)
|
||||||
return logicalFuncs[t1][t2](t, ">", m, n)
|
return logicalFuncs[t1][t2](t, ">", m, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// geFunc is an `>=` operator.
|
// geFunc is an `>=` operator.
|
||||||
func geFunc(t iterator, m, n interface{}) interface{} {
|
func geFunc(t iterator, m, n interface{}) interface{} {
|
||||||
t1 := getValueType(m)
|
t1 := getXPathType(m)
|
||||||
t2 := getValueType(n)
|
t2 := getXPathType(n)
|
||||||
return logicalFuncs[t1][t2](t, ">=", m, n)
|
return logicalFuncs[t1][t2](t, ">=", m, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ltFunc is an `<` operator.
|
// ltFunc is an `<` operator.
|
||||||
func ltFunc(t iterator, m, n interface{}) interface{} {
|
func ltFunc(t iterator, m, n interface{}) interface{} {
|
||||||
t1 := getValueType(m)
|
t1 := getXPathType(m)
|
||||||
t2 := getValueType(n)
|
t2 := getXPathType(n)
|
||||||
return logicalFuncs[t1][t2](t, "<", m, n)
|
return logicalFuncs[t1][t2](t, "<", m, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// leFunc is an `<=` operator.
|
// leFunc is an `<=` operator.
|
||||||
func leFunc(t iterator, m, n interface{}) interface{} {
|
func leFunc(t iterator, m, n interface{}) interface{} {
|
||||||
t1 := getValueType(m)
|
t1 := getXPathType(m)
|
||||||
t2 := getValueType(n)
|
t2 := getXPathType(n)
|
||||||
return logicalFuncs[t1][t2](t, "<=", m, n)
|
return logicalFuncs[t1][t2](t, "<=", m, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// neFunc is an `!=` operator.
|
// neFunc is an `!=` operator.
|
||||||
func neFunc(t iterator, m, n interface{}) interface{} {
|
func neFunc(t iterator, m, n interface{}) interface{} {
|
||||||
t1 := getValueType(m)
|
t1 := getXPathType(m)
|
||||||
t2 := getValueType(n)
|
t2 := getXPathType(n)
|
||||||
return logicalFuncs[t1][t2](t, "!=", m, n)
|
return logicalFuncs[t1][t2](t, "!=", m, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// orFunc is an `or` operator.
|
// orFunc is an `or` operator.
|
||||||
var orFunc = func(t iterator, m, n interface{}) interface{} {
|
var orFunc = func(t iterator, m, n interface{}) interface{} {
|
||||||
t1 := getValueType(m)
|
t1 := getXPathType(m)
|
||||||
t2 := getValueType(n)
|
t2 := getXPathType(n)
|
||||||
return logicalFuncs[t1][t2](t, "or", m, n)
|
return logicalFuncs[t1][t2](t, "or", m, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
515
vendor/github.com/antchfx/xpath/query.go
generated
vendored
515
vendor/github.com/antchfx/xpath/query.go
generated
vendored
@ -7,6 +7,44 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The return type of the XPath expression.
|
||||||
|
type resultType int
|
||||||
|
|
||||||
|
var xpathResultType = struct {
|
||||||
|
Boolean resultType
|
||||||
|
// A numeric value
|
||||||
|
Number resultType
|
||||||
|
String resultType
|
||||||
|
// A node collection.
|
||||||
|
NodeSet resultType
|
||||||
|
// Any of the XPath node types.
|
||||||
|
Any resultType
|
||||||
|
}{
|
||||||
|
Boolean: 0,
|
||||||
|
Number: 1,
|
||||||
|
String: 2,
|
||||||
|
NodeSet: 3,
|
||||||
|
Any: 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
type queryProp int
|
||||||
|
|
||||||
|
var queryProps = struct {
|
||||||
|
None queryProp
|
||||||
|
Position queryProp
|
||||||
|
Count queryProp
|
||||||
|
Cached queryProp
|
||||||
|
Reverse queryProp
|
||||||
|
Merge queryProp
|
||||||
|
}{
|
||||||
|
None: 0,
|
||||||
|
Position: 1,
|
||||||
|
Count: 2,
|
||||||
|
Cached: 4,
|
||||||
|
Reverse: 8,
|
||||||
|
Merge: 16,
|
||||||
|
}
|
||||||
|
|
||||||
type iterator interface {
|
type iterator interface {
|
||||||
Current() NodeNavigator
|
Current() NodeNavigator
|
||||||
}
|
}
|
||||||
@ -20,12 +58,15 @@ type query interface {
|
|||||||
Evaluate(iterator) interface{}
|
Evaluate(iterator) interface{}
|
||||||
|
|
||||||
Clone() query
|
Clone() query
|
||||||
|
|
||||||
|
// ValueType returns the value type of the current query.
|
||||||
|
ValueType() resultType
|
||||||
|
|
||||||
|
Properties() queryProp
|
||||||
}
|
}
|
||||||
|
|
||||||
// nopQuery is an empty query that always return nil for any query.
|
// nopQuery is an empty query that always return nil for any query.
|
||||||
type nopQuery struct {
|
type nopQuery struct{}
|
||||||
query
|
|
||||||
}
|
|
||||||
|
|
||||||
func (nopQuery) Select(iterator) NodeNavigator { return nil }
|
func (nopQuery) Select(iterator) NodeNavigator { return nil }
|
||||||
|
|
||||||
@ -33,21 +74,23 @@ func (nopQuery) Evaluate(iterator) interface{} { return nil }
|
|||||||
|
|
||||||
func (nopQuery) Clone() query { return nopQuery{} }
|
func (nopQuery) Clone() query { return nopQuery{} }
|
||||||
|
|
||||||
|
func (nopQuery) ValueType() resultType { return xpathResultType.NodeSet }
|
||||||
|
|
||||||
|
func (nopQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge | queryProps.Position | queryProps.Count | queryProps.Cached
|
||||||
|
}
|
||||||
|
|
||||||
// contextQuery is returns current node on the iterator object query.
|
// contextQuery is returns current node on the iterator object query.
|
||||||
type contextQuery struct {
|
type contextQuery struct {
|
||||||
count int
|
count int
|
||||||
Root bool // Moving to root-level node in the current context iterator.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *contextQuery) Select(t iterator) (n NodeNavigator) {
|
func (c *contextQuery) Select(t iterator) NodeNavigator {
|
||||||
if c.count == 0 {
|
if c.count > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
c.count++
|
c.count++
|
||||||
n = t.Current().Copy()
|
return t.Current().Copy()
|
||||||
if c.Root {
|
|
||||||
n.MoveToRoot()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *contextQuery) Evaluate(iterator) interface{} {
|
func (c *contextQuery) Evaluate(iterator) interface{} {
|
||||||
@ -56,12 +99,53 @@ func (c *contextQuery) Evaluate(iterator) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *contextQuery) Clone() query {
|
func (c *contextQuery) Clone() query {
|
||||||
return &contextQuery{Root: c.Root}
|
return &contextQuery{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *contextQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *contextQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge | queryProps.Position | queryProps.Count | queryProps.Cached
|
||||||
|
}
|
||||||
|
|
||||||
|
type absoluteQuery struct {
|
||||||
|
count int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *absoluteQuery) Select(t iterator) (n NodeNavigator) {
|
||||||
|
if a.count > 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a.count++
|
||||||
|
n = t.Current().Copy()
|
||||||
|
n.MoveToRoot()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *absoluteQuery) Evaluate(t iterator) interface{} {
|
||||||
|
a.count = 0
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *absoluteQuery) Clone() query {
|
||||||
|
return &absoluteQuery{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *absoluteQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *absoluteQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge | queryProps.Position | queryProps.Count | queryProps.Cached
|
||||||
}
|
}
|
||||||
|
|
||||||
// ancestorQuery is an XPath ancestor node query.(ancestor::*|ancestor-self::*)
|
// ancestorQuery is an XPath ancestor node query.(ancestor::*|ancestor-self::*)
|
||||||
type ancestorQuery struct {
|
type ancestorQuery struct {
|
||||||
|
name string
|
||||||
iterator func() NodeNavigator
|
iterator func() NodeNavigator
|
||||||
|
table map[uint64]bool
|
||||||
|
|
||||||
Self bool
|
Self bool
|
||||||
Input query
|
Input query
|
||||||
@ -69,6 +153,10 @@ type ancestorQuery struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *ancestorQuery) Select(t iterator) NodeNavigator {
|
func (a *ancestorQuery) Select(t iterator) NodeNavigator {
|
||||||
|
if a.table == nil {
|
||||||
|
a.table = make(map[uint64]bool)
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if a.iterator == nil {
|
if a.iterator == nil {
|
||||||
node := a.Input.Select(t)
|
node := a.Input.Select(t)
|
||||||
@ -78,25 +166,28 @@ func (a *ancestorQuery) Select(t iterator) NodeNavigator {
|
|||||||
first := true
|
first := true
|
||||||
node = node.Copy()
|
node = node.Copy()
|
||||||
a.iterator = func() NodeNavigator {
|
a.iterator = func() NodeNavigator {
|
||||||
if first && a.Self {
|
if first {
|
||||||
first = false
|
first = false
|
||||||
if a.Predicate(node) {
|
if a.Self && a.Predicate(node) {
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for node.MoveToParent() {
|
for node.MoveToParent() {
|
||||||
if !a.Predicate(node) {
|
if a.Predicate(node) {
|
||||||
continue
|
|
||||||
}
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if node := a.iterator(); node != nil {
|
for node := a.iterator(); node != nil; node = a.iterator() {
|
||||||
|
node_id := getHashCode(node.Copy())
|
||||||
|
if _, ok := a.table[node_id]; !ok {
|
||||||
|
a.table[node_id] = true
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
}
|
||||||
a.iterator = nil
|
a.iterator = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,11 +203,20 @@ func (a *ancestorQuery) Test(n NodeNavigator) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *ancestorQuery) Clone() query {
|
func (a *ancestorQuery) Clone() query {
|
||||||
return &ancestorQuery{Self: a.Self, Input: a.Input.Clone(), Predicate: a.Predicate}
|
return &ancestorQuery{name: a.name, Self: a.Self, Input: a.Input.Clone(), Predicate: a.Predicate}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ancestorQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ancestorQuery) Properties() queryProp {
|
||||||
|
return queryProps.Position | queryProps.Count | queryProps.Cached | queryProps.Merge | queryProps.Reverse
|
||||||
}
|
}
|
||||||
|
|
||||||
// attributeQuery is an XPath attribute node query.(@*)
|
// attributeQuery is an XPath attribute node query.(@*)
|
||||||
type attributeQuery struct {
|
type attributeQuery struct {
|
||||||
|
name string
|
||||||
iterator func() NodeNavigator
|
iterator func() NodeNavigator
|
||||||
|
|
||||||
Input query
|
Input query
|
||||||
@ -162,11 +262,20 @@ func (a *attributeQuery) Test(n NodeNavigator) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *attributeQuery) Clone() query {
|
func (a *attributeQuery) Clone() query {
|
||||||
return &attributeQuery{Input: a.Input.Clone(), Predicate: a.Predicate}
|
return &attributeQuery{name: a.name, Input: a.Input.Clone(), Predicate: a.Predicate}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *attributeQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *attributeQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
}
|
}
|
||||||
|
|
||||||
// childQuery is an XPath child node query.(child::*)
|
// childQuery is an XPath child node query.(child::*)
|
||||||
type childQuery struct {
|
type childQuery struct {
|
||||||
|
name string
|
||||||
posit int
|
posit int
|
||||||
iterator func() NodeNavigator
|
iterator func() NodeNavigator
|
||||||
|
|
||||||
@ -216,7 +325,15 @@ func (c *childQuery) Test(n NodeNavigator) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *childQuery) Clone() query {
|
func (c *childQuery) Clone() query {
|
||||||
return &childQuery{Input: c.Input.Clone(), Predicate: c.Predicate}
|
return &childQuery{name: c.name, Input: c.Input.Clone(), Predicate: c.Predicate}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *childQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *childQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
}
|
}
|
||||||
|
|
||||||
// position returns a position of current NodeNavigator.
|
// position returns a position of current NodeNavigator.
|
||||||
@ -224,8 +341,75 @@ func (c *childQuery) position() int {
|
|||||||
return c.posit
|
return c.posit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type cachedChildQuery struct {
|
||||||
|
name string
|
||||||
|
posit int
|
||||||
|
iterator func() NodeNavigator
|
||||||
|
|
||||||
|
Input query
|
||||||
|
Predicate func(NodeNavigator) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cachedChildQuery) Select(t iterator) NodeNavigator {
|
||||||
|
for {
|
||||||
|
if c.iterator == nil {
|
||||||
|
c.posit = 0
|
||||||
|
node := c.Input.Select(t)
|
||||||
|
if node == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
node = node.Copy()
|
||||||
|
first := true
|
||||||
|
c.iterator = func() NodeNavigator {
|
||||||
|
for {
|
||||||
|
if (first && !node.MoveToChild()) || (!first && !node.MoveToNext()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
first = false
|
||||||
|
if c.Predicate(node) {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node := c.iterator(); node != nil {
|
||||||
|
c.posit++
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
c.iterator = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cachedChildQuery) Evaluate(t iterator) interface{} {
|
||||||
|
c.Input.Evaluate(t)
|
||||||
|
c.iterator = nil
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cachedChildQuery) position() int {
|
||||||
|
return c.posit
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cachedChildQuery) Test(n NodeNavigator) bool {
|
||||||
|
return c.Predicate(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cachedChildQuery) Clone() query {
|
||||||
|
return &childQuery{name: c.name, Input: c.Input.Clone(), Predicate: c.Predicate}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cachedChildQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cachedChildQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
// descendantQuery is an XPath descendant node query.(descendant::* | descendant-or-self::*)
|
// descendantQuery is an XPath descendant node query.(descendant::* | descendant-or-self::*)
|
||||||
type descendantQuery struct {
|
type descendantQuery struct {
|
||||||
|
name string
|
||||||
iterator func() NodeNavigator
|
iterator func() NodeNavigator
|
||||||
posit int
|
posit int
|
||||||
level int
|
level int
|
||||||
@ -245,14 +429,11 @@ func (d *descendantQuery) Select(t iterator) NodeNavigator {
|
|||||||
}
|
}
|
||||||
node = node.Copy()
|
node = node.Copy()
|
||||||
d.level = 0
|
d.level = 0
|
||||||
positmap := make(map[int]int)
|
|
||||||
first := true
|
first := true
|
||||||
d.iterator = func() NodeNavigator {
|
d.iterator = func() NodeNavigator {
|
||||||
if first && d.Self {
|
if first {
|
||||||
first = false
|
first = false
|
||||||
if d.Predicate(node) {
|
if d.Self && d.Predicate(node) {
|
||||||
d.posit = 1
|
|
||||||
positmap[d.level] = 1
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,7 +441,6 @@ func (d *descendantQuery) Select(t iterator) NodeNavigator {
|
|||||||
for {
|
for {
|
||||||
if node.MoveToChild() {
|
if node.MoveToChild() {
|
||||||
d.level = d.level + 1
|
d.level = d.level + 1
|
||||||
positmap[d.level] = 0
|
|
||||||
} else {
|
} else {
|
||||||
for {
|
for {
|
||||||
if d.level == 0 {
|
if d.level == 0 {
|
||||||
@ -274,8 +454,6 @@ func (d *descendantQuery) Select(t iterator) NodeNavigator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if d.Predicate(node) {
|
if d.Predicate(node) {
|
||||||
positmap[d.level]++
|
|
||||||
d.posit = positmap[d.level]
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,6 +461,7 @@ func (d *descendantQuery) Select(t iterator) NodeNavigator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if node := d.iterator(); node != nil {
|
if node := d.iterator(); node != nil {
|
||||||
|
d.posit++
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
d.iterator = nil
|
d.iterator = nil
|
||||||
@ -309,7 +488,15 @@ func (d *descendantQuery) depth() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *descendantQuery) Clone() query {
|
func (d *descendantQuery) Clone() query {
|
||||||
return &descendantQuery{Self: d.Self, Input: d.Input.Clone(), Predicate: d.Predicate}
|
return &descendantQuery{name: d.name, Self: d.Self, Input: d.Input.Clone(), Predicate: d.Predicate}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *descendantQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *descendantQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
}
|
}
|
||||||
|
|
||||||
// followingQuery is an XPath following node query.(following::*|following-sibling::*)
|
// followingQuery is an XPath following node query.(following::*|following-sibling::*)
|
||||||
@ -390,6 +577,14 @@ func (f *followingQuery) Clone() query {
|
|||||||
return &followingQuery{Input: f.Input.Clone(), Sibling: f.Sibling, Predicate: f.Predicate}
|
return &followingQuery{Input: f.Input.Clone(), Sibling: f.Sibling, Predicate: f.Predicate}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *followingQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *followingQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
func (f *followingQuery) position() int {
|
func (f *followingQuery) position() int {
|
||||||
return f.posit
|
return f.posit
|
||||||
}
|
}
|
||||||
@ -471,6 +666,14 @@ func (p *precedingQuery) Clone() query {
|
|||||||
return &precedingQuery{Input: p.Input.Clone(), Sibling: p.Sibling, Predicate: p.Predicate}
|
return &precedingQuery{Input: p.Input.Clone(), Sibling: p.Sibling, Predicate: p.Predicate}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *precedingQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *precedingQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge | queryProps.Reverse
|
||||||
|
}
|
||||||
|
|
||||||
func (p *precedingQuery) position() int {
|
func (p *precedingQuery) position() int {
|
||||||
return p.posit
|
return p.posit
|
||||||
}
|
}
|
||||||
@ -503,6 +706,14 @@ func (p *parentQuery) Clone() query {
|
|||||||
return &parentQuery{Input: p.Input.Clone(), Predicate: p.Predicate}
|
return &parentQuery{Input: p.Input.Clone(), Predicate: p.Predicate}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *parentQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *parentQuery) Properties() queryProp {
|
||||||
|
return queryProps.Position | queryProps.Count | queryProps.Cached | queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
func (p *parentQuery) Test(n NodeNavigator) bool {
|
func (p *parentQuery) Test(n NodeNavigator) bool {
|
||||||
return p.Predicate(n)
|
return p.Predicate(n)
|
||||||
}
|
}
|
||||||
@ -539,10 +750,20 @@ func (s *selfQuery) Clone() query {
|
|||||||
return &selfQuery{Input: s.Input.Clone(), Predicate: s.Predicate}
|
return &selfQuery{Input: s.Input.Clone(), Predicate: s.Predicate}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *selfQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *selfQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
// filterQuery is an XPath query for predicate filter.
|
// filterQuery is an XPath query for predicate filter.
|
||||||
type filterQuery struct {
|
type filterQuery struct {
|
||||||
Input query
|
Input query
|
||||||
Predicate query
|
Predicate query
|
||||||
|
NoPosition bool
|
||||||
|
|
||||||
posit int
|
posit int
|
||||||
positmap map[int]int
|
positmap map[int]int
|
||||||
}
|
}
|
||||||
@ -602,6 +823,14 @@ func (f *filterQuery) Clone() query {
|
|||||||
return &filterQuery{Input: f.Input.Clone(), Predicate: f.Predicate.Clone()}
|
return &filterQuery{Input: f.Input.Clone(), Predicate: f.Predicate.Clone()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *filterQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *filterQuery) Properties() queryProp {
|
||||||
|
return (queryProps.Position | f.Input.Properties()) & (queryProps.Reverse | queryProps.Merge)
|
||||||
|
}
|
||||||
|
|
||||||
// functionQuery is an XPath function that returns a computed value for
|
// functionQuery is an XPath function that returns a computed value for
|
||||||
// the Evaluate call of the current NodeNavigator node. Select call isn't
|
// the Evaluate call of the current NodeNavigator node. Select call isn't
|
||||||
// applicable for functionQuery.
|
// applicable for functionQuery.
|
||||||
@ -624,6 +853,14 @@ func (f *functionQuery) Clone() query {
|
|||||||
return &functionQuery{Input: f.Input.Clone(), Func: f.Func}
|
return &functionQuery{Input: f.Input.Clone(), Func: f.Func}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *functionQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.Any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *functionQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
// transformFunctionQuery diffs from functionQuery where the latter computes a scalar
|
// transformFunctionQuery diffs from functionQuery where the latter computes a scalar
|
||||||
// value (number,string,boolean) for the current NodeNavigator node while the former
|
// value (number,string,boolean) for the current NodeNavigator node while the former
|
||||||
// (transformFunctionQuery) performs a mapping or transform of the current NodeNavigator
|
// (transformFunctionQuery) performs a mapping or transform of the current NodeNavigator
|
||||||
@ -652,6 +889,14 @@ func (f *transformFunctionQuery) Clone() query {
|
|||||||
return &transformFunctionQuery{Input: f.Input.Clone(), Func: f.Func}
|
return &transformFunctionQuery{Input: f.Input.Clone(), Func: f.Func}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *transformFunctionQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.Any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *transformFunctionQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
// constantQuery is an XPath constant operand.
|
// constantQuery is an XPath constant operand.
|
||||||
type constantQuery struct {
|
type constantQuery struct {
|
||||||
Val interface{}
|
Val interface{}
|
||||||
@ -669,6 +914,14 @@ func (c *constantQuery) Clone() query {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *constantQuery) ValueType() resultType {
|
||||||
|
return getXPathType(c.Val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *constantQuery) Properties() queryProp {
|
||||||
|
return queryProps.Position | queryProps.Count | queryProps.Cached | queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
type groupQuery struct {
|
type groupQuery struct {
|
||||||
posit int
|
posit int
|
||||||
|
|
||||||
@ -692,6 +945,14 @@ func (g *groupQuery) Clone() query {
|
|||||||
return &groupQuery{Input: g.Input.Clone()}
|
return &groupQuery{Input: g.Input.Clone()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *groupQuery) ValueType() resultType {
|
||||||
|
return g.Input.ValueType()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *groupQuery) Properties() queryProp {
|
||||||
|
return queryProps.Position
|
||||||
|
}
|
||||||
|
|
||||||
func (g *groupQuery) position() int {
|
func (g *groupQuery) position() int {
|
||||||
return g.posit
|
return g.posit
|
||||||
}
|
}
|
||||||
@ -726,6 +987,14 @@ func (l *logicalQuery) Clone() query {
|
|||||||
return &logicalQuery{Left: l.Left.Clone(), Right: l.Right.Clone(), Do: l.Do}
|
return &logicalQuery{Left: l.Left.Clone(), Right: l.Right.Clone(), Do: l.Do}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *logicalQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logicalQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
// numericQuery is an XPath numeric operator expression.
|
// numericQuery is an XPath numeric operator expression.
|
||||||
type numericQuery struct {
|
type numericQuery struct {
|
||||||
Left, Right query
|
Left, Right query
|
||||||
@ -747,6 +1016,14 @@ func (n *numericQuery) Clone() query {
|
|||||||
return &numericQuery{Left: n.Left.Clone(), Right: n.Right.Clone(), Do: n.Do}
|
return &numericQuery{Left: n.Left.Clone(), Right: n.Right.Clone(), Do: n.Do}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *numericQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.Number
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *numericQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
type booleanQuery struct {
|
type booleanQuery struct {
|
||||||
IsOr bool
|
IsOr bool
|
||||||
Left, Right query
|
Left, Right query
|
||||||
@ -837,6 +1114,14 @@ func (b *booleanQuery) Clone() query {
|
|||||||
return &booleanQuery{IsOr: b.IsOr, Left: b.Left.Clone(), Right: b.Right.Clone()}
|
return &booleanQuery{IsOr: b.IsOr, Left: b.Left.Clone(), Right: b.Right.Clone()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *booleanQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *booleanQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
type unionQuery struct {
|
type unionQuery struct {
|
||||||
Left, Right query
|
Left, Right query
|
||||||
iterator func() NodeNavigator
|
iterator func() NodeNavigator
|
||||||
@ -894,6 +1179,14 @@ func (u *unionQuery) Clone() query {
|
|||||||
return &unionQuery{Left: u.Left.Clone(), Right: u.Right.Clone()}
|
return &unionQuery{Left: u.Left.Clone(), Right: u.Right.Clone()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *unionQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *unionQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
type lastQuery struct {
|
type lastQuery struct {
|
||||||
buffer []NodeNavigator
|
buffer []NodeNavigator
|
||||||
counted bool
|
counted bool
|
||||||
@ -923,6 +1216,147 @@ func (q *lastQuery) Clone() query {
|
|||||||
return &lastQuery{Input: q.Input.Clone()}
|
return &lastQuery{Input: q.Input.Clone()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *lastQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.Number
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *lastQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
|
type descendantOverDescendantQuery struct {
|
||||||
|
name string
|
||||||
|
level int
|
||||||
|
posit int
|
||||||
|
currentNode NodeNavigator
|
||||||
|
|
||||||
|
Input query
|
||||||
|
MatchSelf bool
|
||||||
|
Predicate func(NodeNavigator) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *descendantOverDescendantQuery) moveToFirstChild() bool {
|
||||||
|
if d.currentNode.MoveToChild() {
|
||||||
|
d.level++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *descendantOverDescendantQuery) moveUpUntilNext() bool {
|
||||||
|
for !d.currentNode.MoveToNext() {
|
||||||
|
d.level--
|
||||||
|
if d.level == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
d.currentNode.MoveToParent()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *descendantOverDescendantQuery) Select(t iterator) NodeNavigator {
|
||||||
|
for {
|
||||||
|
if d.level == 0 {
|
||||||
|
node := d.Input.Select(t)
|
||||||
|
if node == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
d.currentNode = node.Copy()
|
||||||
|
d.posit = 0
|
||||||
|
if d.MatchSelf && d.Predicate(d.currentNode) {
|
||||||
|
d.posit = 1
|
||||||
|
return d.currentNode
|
||||||
|
}
|
||||||
|
d.moveToFirstChild()
|
||||||
|
} else if !d.moveUpUntilNext() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for ok := true; ok; ok = d.moveToFirstChild() {
|
||||||
|
if d.Predicate(d.currentNode) {
|
||||||
|
d.posit++
|
||||||
|
return d.currentNode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *descendantOverDescendantQuery) Evaluate(t iterator) interface{} {
|
||||||
|
d.Input.Evaluate(t)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *descendantOverDescendantQuery) Clone() query {
|
||||||
|
return &descendantOverDescendantQuery{Input: d.Input.Clone(), Predicate: d.Predicate, MatchSelf: d.MatchSelf}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *descendantOverDescendantQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *descendantOverDescendantQuery) Properties() queryProp {
|
||||||
|
return queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *descendantOverDescendantQuery) position() int {
|
||||||
|
return d.posit
|
||||||
|
}
|
||||||
|
|
||||||
|
type mergeQuery struct {
|
||||||
|
Input query
|
||||||
|
Child query
|
||||||
|
|
||||||
|
iterator func() NodeNavigator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mergeQuery) Select(t iterator) NodeNavigator {
|
||||||
|
for {
|
||||||
|
if m.iterator == nil {
|
||||||
|
root := m.Input.Select(t)
|
||||||
|
if root == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
m.Child.Evaluate(t)
|
||||||
|
root = root.Copy()
|
||||||
|
t.Current().MoveTo(root)
|
||||||
|
var list []NodeNavigator
|
||||||
|
for node := m.Child.Select(t); node != nil; node = m.Child.Select(t) {
|
||||||
|
list = append(list, node.Copy())
|
||||||
|
}
|
||||||
|
i := 0
|
||||||
|
m.iterator = func() NodeNavigator {
|
||||||
|
if i >= len(list) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
result := list[i]
|
||||||
|
i++
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if node := m.iterator(); node != nil {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
m.iterator = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mergeQuery) Evaluate(t iterator) interface{} {
|
||||||
|
m.Input.Evaluate(t)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mergeQuery) Clone() query {
|
||||||
|
return &mergeQuery{Input: m.Input.Clone(), Child: m.Child.Clone()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mergeQuery) ValueType() resultType {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mergeQuery) Properties() queryProp {
|
||||||
|
return queryProps.Position | queryProps.Count | queryProps.Cached | queryProps.Merge
|
||||||
|
}
|
||||||
|
|
||||||
func getHashCode(n NodeNavigator) uint64 {
|
func getHashCode(n NodeNavigator) uint64 {
|
||||||
var sb bytes.Buffer
|
var sb bytes.Buffer
|
||||||
switch n.NodeType() {
|
switch n.NodeType() {
|
||||||
@ -958,7 +1392,7 @@ func getHashCode(n NodeNavigator) uint64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
h := fnv.New64a()
|
h := fnv.New64a()
|
||||||
h.Write([]byte(sb.String()))
|
h.Write(sb.Bytes())
|
||||||
return h.Sum64()
|
return h.Sum64()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -981,3 +1415,20 @@ func getNodeDepth(q query) int {
|
|||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getXPathType(i interface{}) resultType {
|
||||||
|
v := reflect.ValueOf(i)
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Float64:
|
||||||
|
return xpathResultType.Number
|
||||||
|
case reflect.String:
|
||||||
|
return xpathResultType.String
|
||||||
|
case reflect.Bool:
|
||||||
|
return xpathResultType.Boolean
|
||||||
|
default:
|
||||||
|
if _, ok := i.(query); ok {
|
||||||
|
return xpathResultType.NodeSet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic(fmt.Errorf("xpath unknown value type: %v", v.Kind()))
|
||||||
|
}
|
||||||
|
17
vendor/github.com/antchfx/xpath/xpath.go
generated
vendored
17
vendor/github.com/antchfx/xpath/xpath.go
generated
vendored
@ -74,6 +74,7 @@ type NodeNavigator interface {
|
|||||||
type NodeIterator struct {
|
type NodeIterator struct {
|
||||||
node NodeNavigator
|
node NodeNavigator
|
||||||
query query
|
query query
|
||||||
|
table map[uint64]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current returns current node which matched.
|
// Current returns current node which matched.
|
||||||
@ -83,14 +84,22 @@ func (t *NodeIterator) Current() NodeNavigator {
|
|||||||
|
|
||||||
// MoveNext moves Navigator to the next match node.
|
// MoveNext moves Navigator to the next match node.
|
||||||
func (t *NodeIterator) MoveNext() bool {
|
func (t *NodeIterator) MoveNext() bool {
|
||||||
|
for {
|
||||||
n := t.query.Select(t)
|
n := t.query.Select(t)
|
||||||
if n != nil {
|
if n == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if !t.node.MoveTo(n) {
|
if !t.node.MoveTo(n) {
|
||||||
t.node = n.Copy()
|
t.node = n.Copy()
|
||||||
}
|
}
|
||||||
|
// https://github.com/antchfx/xpath/issues/94
|
||||||
|
id := getHashCode(n.Copy())
|
||||||
|
if _, ok := t.table[id]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.table[id] = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select selects a node set using the specified XPath expression.
|
// Select selects a node set using the specified XPath expression.
|
||||||
@ -121,14 +130,14 @@ func (expr *Expr) Evaluate(root NodeNavigator) interface{} {
|
|||||||
val := expr.q.Evaluate(iteratorFunc(func() NodeNavigator { return root }))
|
val := expr.q.Evaluate(iteratorFunc(func() NodeNavigator { return root }))
|
||||||
switch val.(type) {
|
switch val.(type) {
|
||||||
case query:
|
case query:
|
||||||
return &NodeIterator{query: expr.q.Clone(), node: root}
|
return &NodeIterator{query: expr.q.Clone(), node: root, table: make(map[uint64]bool)}
|
||||||
}
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select selects a node set using the specified XPath expression.
|
// Select selects a node set using the specified XPath expression.
|
||||||
func (expr *Expr) Select(root NodeNavigator) *NodeIterator {
|
func (expr *Expr) Select(root NodeNavigator) *NodeIterator {
|
||||||
return &NodeIterator{query: expr.q.Clone(), node: root}
|
return &NodeIterator{query: expr.q.Clone(), node: root, table: make(map[uint64]bool)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns XPath expression string.
|
// String returns XPath expression string.
|
||||||
|
56
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
56
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
@ -1,5 +1,61 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v4.12.0 - 2024-04-15
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
|
||||||
|
* Update golang.org/x/net dep because of [GO-2024-2687](https://pkg.go.dev/vuln/GO-2024-2687) by @aldas in https://github.com/labstack/echo/pull/2625
|
||||||
|
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* binder: make binding to Map work better with string destinations by @aldas in https://github.com/labstack/echo/pull/2554
|
||||||
|
* README.md: add Encore as sponsor by @marcuskohlberg in https://github.com/labstack/echo/pull/2579
|
||||||
|
* Reorder paragraphs in README.md by @aldas in https://github.com/labstack/echo/pull/2581
|
||||||
|
* CI: upgrade actions/checkout to v4 by @aldas in https://github.com/labstack/echo/pull/2584
|
||||||
|
* Remove default charset from 'application/json' Content-Type header by @doortts in https://github.com/labstack/echo/pull/2568
|
||||||
|
* CI: Use Go 1.22 by @aldas in https://github.com/labstack/echo/pull/2588
|
||||||
|
* binder: allow binding to a nil map by @georgmu in https://github.com/labstack/echo/pull/2574
|
||||||
|
* Add Skipper Unit Test In BasicBasicAuthConfig and Add More Detail Explanation regarding BasicAuthValidator by @RyoKusnadi in https://github.com/labstack/echo/pull/2461
|
||||||
|
* fix some typos by @teslaedison in https://github.com/labstack/echo/pull/2603
|
||||||
|
* fix: some typos by @pomadev in https://github.com/labstack/echo/pull/2596
|
||||||
|
* Allow ResponseWriters to unwrap writers when flushing/hijacking by @aldas in https://github.com/labstack/echo/pull/2595
|
||||||
|
* Add SPDX licence comments to files. by @aldas in https://github.com/labstack/echo/pull/2604
|
||||||
|
* Upgrade deps by @aldas in https://github.com/labstack/echo/pull/2605
|
||||||
|
* Change type definition blocks to single declarations. This helps copy… by @aldas in https://github.com/labstack/echo/pull/2606
|
||||||
|
* Fix Real IP logic by @cl-bvl in https://github.com/labstack/echo/pull/2550
|
||||||
|
* Default binder can use `UnmarshalParams(params []string) error` inter… by @aldas in https://github.com/labstack/echo/pull/2607
|
||||||
|
* Default binder can bind pointer to slice as struct field. For example `*[]string` by @aldas in https://github.com/labstack/echo/pull/2608
|
||||||
|
* Remove maxparam dependence from Context by @aldas in https://github.com/labstack/echo/pull/2611
|
||||||
|
* When route is registered with empty path it is normalized to `/`. by @aldas in https://github.com/labstack/echo/pull/2616
|
||||||
|
* proxy middleware should use httputil.ReverseProxy for SSE requests by @aldas in https://github.com/labstack/echo/pull/2624
|
||||||
|
|
||||||
|
|
||||||
|
## v4.11.4 - 2023-12-20
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
|
||||||
|
* Upgrade golang.org/x/crypto to v0.17.0 to fix vulnerability [issue](https://pkg.go.dev/vuln/GO-2023-2402) [#2562](https://github.com/labstack/echo/pull/2562)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Update deps and mark Go version to 1.18 as this is what golang.org/x/* use [#2563](https://github.com/labstack/echo/pull/2563)
|
||||||
|
* Request logger: add example for Slog https://pkg.go.dev/log/slog [#2543](https://github.com/labstack/echo/pull/2543)
|
||||||
|
|
||||||
|
|
||||||
|
## v4.11.3 - 2023-11-07
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
|
||||||
|
* 'c.Attachment' and 'c.Inline' should escape filename in 'Content-Disposition' header to avoid 'Reflect File Download' vulnerability. [#2541](https://github.com/labstack/echo/pull/2541)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Tests: refactor context tests to be separate functions [#2540](https://github.com/labstack/echo/pull/2540)
|
||||||
|
* Proxy middleware: reuse echo request context [#2537](https://github.com/labstack/echo/pull/2537)
|
||||||
|
* Mark unmarshallable yaml struct tags as ignored [#2536](https://github.com/labstack/echo/pull/2536)
|
||||||
|
|
||||||
|
|
||||||
## v4.11.2 - 2023-10-11
|
## v4.11.2 - 2023-10-11
|
||||||
|
|
||||||
**Security**
|
**Security**
|
||||||
|
4
vendor/github.com/labstack/echo/v4/Makefile
generated
vendored
4
vendor/github.com/labstack/echo/v4/Makefile
generated
vendored
@ -31,6 +31,6 @@ benchmark: ## Run benchmarks
|
|||||||
help: ## Display this help screen
|
help: ## Display this help screen
|
||||||
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
||||||
goversion ?= "1.17"
|
goversion ?= "1.19"
|
||||||
test_version: ## Run tests inside Docker with given version (defaults to 1.17 oldest supported). Example: make test_version goversion=1.17
|
test_version: ## Run tests inside Docker with given version (defaults to 1.19 oldest supported). Example: make test_version goversion=1.19
|
||||||
@docker run --rm -it -v $(shell pwd):/project golang:$(goversion) /bin/sh -c "cd /project && make init check"
|
@docker run --rm -it -v $(shell pwd):/project golang:$(goversion) /bin/sh -c "cd /project && make init check"
|
||||||
|
33
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
33
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
@ -9,20 +9,18 @@
|
|||||||
[![Twitter](https://img.shields.io/badge/twitter-@labstack-55acee.svg?style=flat-square)](https://twitter.com/labstack)
|
[![Twitter](https://img.shields.io/badge/twitter-@labstack-55acee.svg?style=flat-square)](https://twitter.com/labstack)
|
||||||
[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/labstack/echo/master/LICENSE)
|
[![License](http://img.shields.io/badge/license-mit-blue.svg?style=flat-square)](https://raw.githubusercontent.com/labstack/echo/master/LICENSE)
|
||||||
|
|
||||||
## Supported Go versions
|
## Echo
|
||||||
|
|
||||||
Latest version of Echo supports last four Go major [releases](https://go.dev/doc/devel/release) and might work with
|
High performance, extensible, minimalist Go web framework.
|
||||||
older versions.
|
|
||||||
|
|
||||||
As of version 4.0.0, Echo is available as a [Go module](https://github.com/golang/go/wiki/Modules).
|
* [Official website](https://echo.labstack.com)
|
||||||
Therefore a Go version capable of understanding /vN suffixed imports is required:
|
* [Quick start](https://echo.labstack.com/docs/quick-start)
|
||||||
|
* [Middlewares](https://echo.labstack.com/docs/category/middleware)
|
||||||
|
|
||||||
Any of these versions will allow you to import Echo as `github.com/labstack/echo/v4` which is the recommended
|
Help and questions: [Github Discussions](https://github.com/labstack/echo/discussions)
|
||||||
way of using Echo going forward.
|
|
||||||
|
|
||||||
For older versions, please use the latest v3 tag.
|
|
||||||
|
|
||||||
## Feature Overview
|
### Feature Overview
|
||||||
|
|
||||||
- Optimized HTTP router which smartly prioritize routes
|
- Optimized HTTP router which smartly prioritize routes
|
||||||
- Build robust and scalable RESTful APIs
|
- Build robust and scalable RESTful APIs
|
||||||
@ -38,6 +36,18 @@ For older versions, please use the latest v3 tag.
|
|||||||
- Automatic TLS via Let’s Encrypt
|
- Automatic TLS via Let’s Encrypt
|
||||||
- HTTP/2 support
|
- HTTP/2 support
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<a href="https://encore.dev" style="display: inline-flex; align-items: center; gap: 10px">
|
||||||
|
<img src="https://user-images.githubusercontent.com/78424526/214602214-52e0483a-b5fc-4d4c-b03e-0b7b23e012df.svg" height="28px" alt="encore icon"></img>
|
||||||
|
<b>Encore – the platform for building Go-based cloud backends</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
Click [here](https://github.com/sponsors/labstack) for more information on sponsorship.
|
||||||
|
|
||||||
## Benchmarks
|
## Benchmarks
|
||||||
|
|
||||||
Date: 2020/11/11<br>
|
Date: 2020/11/11<br>
|
||||||
@ -57,6 +67,7 @@ The benchmarks above were run on an Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
|
|||||||
// go get github.com/labstack/echo/{version}
|
// go get github.com/labstack/echo/{version}
|
||||||
go get github.com/labstack/echo/v4
|
go get github.com/labstack/echo/v4
|
||||||
```
|
```
|
||||||
|
Latest version of Echo supports last four Go major [releases](https://go.dev/doc/devel/release) and might work with older versions.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@ -117,10 +128,6 @@ of middlewares in this list.
|
|||||||
|
|
||||||
Please send a PR to add your own library here.
|
Please send a PR to add your own library here.
|
||||||
|
|
||||||
## Help
|
|
||||||
|
|
||||||
- [Forum](https://github.com/labstack/echo/discussions)
|
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
**Use issues for everything**
|
**Use issues for everything**
|
||||||
|
140
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
140
vendor/github.com/labstack/echo/v4/bind.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -11,23 +14,28 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
// Binder is the interface that wraps the Bind method.
|
||||||
// Binder is the interface that wraps the Bind method.
|
type Binder interface {
|
||||||
Binder interface {
|
|
||||||
Bind(i interface{}, c Context) error
|
Bind(i interface{}, c Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultBinder is the default implementation of the Binder interface.
|
// DefaultBinder is the default implementation of the Binder interface.
|
||||||
DefaultBinder struct{}
|
type DefaultBinder struct{}
|
||||||
|
|
||||||
// BindUnmarshaler is the interface used to wrap the UnmarshalParam method.
|
// BindUnmarshaler is the interface used to wrap the UnmarshalParam method.
|
||||||
// Types that don't implement this, but do implement encoding.TextUnmarshaler
|
// Types that don't implement this, but do implement encoding.TextUnmarshaler
|
||||||
// will use that interface instead.
|
// will use that interface instead.
|
||||||
BindUnmarshaler interface {
|
type BindUnmarshaler interface {
|
||||||
// UnmarshalParam decodes and assigns a value from an form or query param.
|
// UnmarshalParam decodes and assigns a value from an form or query param.
|
||||||
UnmarshalParam(param string) error
|
UnmarshalParam(param string) error
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
// bindMultipleUnmarshaler is used by binder to unmarshal multiple values from request at once to
|
||||||
|
// type implementing this interface. For example request could have multiple query fields `?a=1&a=2&b=test` in that case
|
||||||
|
// for `a` following slice `["1", "2"] will be passed to unmarshaller.
|
||||||
|
type bindMultipleUnmarshaler interface {
|
||||||
|
UnmarshalParams(params []string) error
|
||||||
|
}
|
||||||
|
|
||||||
// BindPathParams binds path params to bindable object
|
// BindPathParams binds path params to bindable object
|
||||||
func (b *DefaultBinder) BindPathParams(c Context, i interface{}) error {
|
func (b *DefaultBinder) BindPathParams(c Context, i interface{}) error {
|
||||||
@ -131,10 +139,29 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
|
|||||||
typ := reflect.TypeOf(destination).Elem()
|
typ := reflect.TypeOf(destination).Elem()
|
||||||
val := reflect.ValueOf(destination).Elem()
|
val := reflect.ValueOf(destination).Elem()
|
||||||
|
|
||||||
// Map
|
// Support binding to limited Map destinations:
|
||||||
if typ.Kind() == reflect.Map {
|
// - map[string][]string,
|
||||||
|
// - map[string]string <-- (binds first value from data slice)
|
||||||
|
// - map[string]interface{}
|
||||||
|
// You are better off binding to struct but there are user who want this map feature. Source of data for these cases are:
|
||||||
|
// params,query,header,form as these sources produce string values, most of the time slice of strings, actually.
|
||||||
|
if typ.Kind() == reflect.Map && typ.Key().Kind() == reflect.String {
|
||||||
|
k := typ.Elem().Kind()
|
||||||
|
isElemInterface := k == reflect.Interface
|
||||||
|
isElemString := k == reflect.String
|
||||||
|
isElemSliceOfStrings := k == reflect.Slice && typ.Elem().Elem().Kind() == reflect.String
|
||||||
|
if !(isElemSliceOfStrings || isElemString || isElemInterface) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if val.IsNil() {
|
||||||
|
val.Set(reflect.MakeMap(typ))
|
||||||
|
}
|
||||||
for k, v := range data {
|
for k, v := range data {
|
||||||
|
if isElemString {
|
||||||
val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v[0]))
|
val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v[0]))
|
||||||
|
} else {
|
||||||
|
val.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(v))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -161,14 +188,14 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
|
|||||||
}
|
}
|
||||||
structFieldKind := structField.Kind()
|
structFieldKind := structField.Kind()
|
||||||
inputFieldName := typeField.Tag.Get(tag)
|
inputFieldName := typeField.Tag.Get(tag)
|
||||||
if typeField.Anonymous && structField.Kind() == reflect.Struct && inputFieldName != "" {
|
if typeField.Anonymous && structFieldKind == reflect.Struct && inputFieldName != "" {
|
||||||
// if anonymous struct with query/param/form tags, report an error
|
// if anonymous struct with query/param/form tags, report an error
|
||||||
return errors.New("query/param/form tags are not allowed with anonymous struct field")
|
return errors.New("query/param/form tags are not allowed with anonymous struct field")
|
||||||
}
|
}
|
||||||
|
|
||||||
if inputFieldName == "" {
|
if inputFieldName == "" {
|
||||||
// If tag is nil, we inspect if the field is a not BindUnmarshaler struct and try to bind data into it (might contains fields with tags).
|
// If tag is nil, we inspect if the field is a not BindUnmarshaler struct and try to bind data into it (might contains fields with tags).
|
||||||
// structs that implement BindUnmarshaler are binded only when they have explicit tag
|
// structs that implement BindUnmarshaler are bound only when they have explicit tag
|
||||||
if _, ok := structField.Addr().Interface().(BindUnmarshaler); !ok && structFieldKind == reflect.Struct {
|
if _, ok := structField.Addr().Interface().(BindUnmarshaler); !ok && structFieldKind == reflect.Struct {
|
||||||
if err := b.bindData(structField.Addr().Interface(), data, tag); err != nil {
|
if err := b.bindData(structField.Addr().Interface(), data, tag); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -197,27 +224,46 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call this first, in case we're dealing with an alias to an array type
|
// NOTE: algorithm here is not particularly sophisticated. It probably does not work with absurd types like `**[]*int`
|
||||||
if ok, err := unmarshalField(typeField.Type.Kind(), inputValue[0], structField); ok {
|
// but it is smart enough to handle niche cases like `*int`,`*[]string`,`[]*int` .
|
||||||
|
|
||||||
|
// try unmarshalling first, in case we're dealing with an alias to an array type
|
||||||
|
if ok, err := unmarshalInputsToField(typeField.Type.Kind(), inputValue, structField); ok {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
numElems := len(inputValue)
|
if ok, err := unmarshalInputToField(typeField.Type.Kind(), inputValue[0], structField); ok {
|
||||||
if structFieldKind == reflect.Slice && numElems > 0 {
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// we could be dealing with pointer to slice `*[]string` so dereference it. There are wierd OpenAPI generators
|
||||||
|
// that could create struct fields like that.
|
||||||
|
if structFieldKind == reflect.Pointer {
|
||||||
|
structFieldKind = structField.Elem().Kind()
|
||||||
|
structField = structField.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if structFieldKind == reflect.Slice {
|
||||||
sliceOf := structField.Type().Elem().Kind()
|
sliceOf := structField.Type().Elem().Kind()
|
||||||
|
numElems := len(inputValue)
|
||||||
slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
|
slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
|
||||||
for j := 0; j < numElems; j++ {
|
for j := 0; j < numElems; j++ {
|
||||||
if err := setWithProperType(sliceOf, inputValue[j], slice.Index(j)); err != nil {
|
if err := setWithProperType(sliceOf, inputValue[j], slice.Index(j)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val.Field(i).Set(slice)
|
structField.Set(slice)
|
||||||
} else if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil {
|
continue
|
||||||
return err
|
}
|
||||||
|
|
||||||
|
if err := setWithProperType(structFieldKind, inputValue[0], structField); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -225,7 +271,7 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
|
|||||||
|
|
||||||
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
|
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
|
||||||
// But also call it here, in case we're dealing with an array of BindUnmarshalers
|
// But also call it here, in case we're dealing with an array of BindUnmarshalers
|
||||||
if ok, err := unmarshalField(valueKind, val, structField); ok {
|
if ok, err := unmarshalInputToField(valueKind, val, structField); ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,35 +312,41 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalField(valueKind reflect.Kind, val string, field reflect.Value) (bool, error) {
|
func unmarshalInputsToField(valueKind reflect.Kind, values []string, field reflect.Value) (bool, error) {
|
||||||
switch valueKind {
|
if valueKind == reflect.Ptr {
|
||||||
case reflect.Ptr:
|
if field.IsNil() {
|
||||||
return unmarshalFieldPtr(val, field)
|
field.Set(reflect.New(field.Type().Elem()))
|
||||||
default:
|
|
||||||
return unmarshalFieldNonPtr(val, field)
|
|
||||||
}
|
}
|
||||||
|
field = field.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldIValue := field.Addr().Interface()
|
||||||
|
unmarshaler, ok := fieldIValue.(bindMultipleUnmarshaler)
|
||||||
|
if !ok {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, unmarshaler.UnmarshalParams(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalFieldNonPtr(value string, field reflect.Value) (bool, error) {
|
func unmarshalInputToField(valueKind reflect.Kind, val string, field reflect.Value) (bool, error) {
|
||||||
fieldIValue := field.Addr().Interface()
|
if valueKind == reflect.Ptr {
|
||||||
if unmarshaler, ok := fieldIValue.(BindUnmarshaler); ok {
|
if field.IsNil() {
|
||||||
return true, unmarshaler.UnmarshalParam(value)
|
field.Set(reflect.New(field.Type().Elem()))
|
||||||
}
|
}
|
||||||
if unmarshaler, ok := fieldIValue.(encoding.TextUnmarshaler); ok {
|
field = field.Elem()
|
||||||
return true, unmarshaler.UnmarshalText([]byte(value))
|
}
|
||||||
|
|
||||||
|
fieldIValue := field.Addr().Interface()
|
||||||
|
switch unmarshaler := fieldIValue.(type) {
|
||||||
|
case BindUnmarshaler:
|
||||||
|
return true, unmarshaler.UnmarshalParam(val)
|
||||||
|
case encoding.TextUnmarshaler:
|
||||||
|
return true, unmarshaler.UnmarshalText([]byte(val))
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalFieldPtr(value string, field reflect.Value) (bool, error) {
|
|
||||||
if field.IsNil() {
|
|
||||||
// Initialize the pointer to a nil value
|
|
||||||
field.Set(reflect.New(field.Type().Elem()))
|
|
||||||
}
|
|
||||||
return unmarshalFieldNonPtr(value, field.Elem())
|
|
||||||
}
|
|
||||||
|
|
||||||
func setIntField(value string, bitSize int, field reflect.Value) error {
|
func setIntField(value string, bitSize int, field reflect.Value) error {
|
||||||
if value == "" {
|
if value == "" {
|
||||||
value = "0"
|
value = "0"
|
||||||
|
5
vendor/github.com/labstack/echo/v4/binder.go
generated
vendored
5
vendor/github.com/labstack/echo/v4/binder.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -1323,7 +1326,7 @@ func (b *ValueBinder) unixTime(sourceParam string, dest *time.Time, valueMustExi
|
|||||||
case time.Second:
|
case time.Second:
|
||||||
*dest = time.Unix(n, 0)
|
*dest = time.Unix(n, 0)
|
||||||
case time.Millisecond:
|
case time.Millisecond:
|
||||||
*dest = time.Unix(n/1e3, (n%1e3)*1e6) // TODO: time.UnixMilli(n) exists since Go1.17 switch to that when min version allows
|
*dest = time.UnixMilli(n)
|
||||||
case time.Nanosecond:
|
case time.Nanosecond:
|
||||||
*dest = time.Unix(0, n)
|
*dest = time.Unix(0, n)
|
||||||
}
|
}
|
||||||
|
65
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
65
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -13,10 +16,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
// Context represents the context of the current HTTP request. It holds request and
|
||||||
// Context represents the context of the current HTTP request. It holds request and
|
// response objects, path, path parameters, data and registered handler.
|
||||||
// response objects, path, path parameters, data and registered handler.
|
type Context interface {
|
||||||
Context interface {
|
|
||||||
// Request returns `*http.Request`.
|
// Request returns `*http.Request`.
|
||||||
Request() *http.Request
|
Request() *http.Request
|
||||||
|
|
||||||
@ -195,22 +197,35 @@ type (
|
|||||||
// with `Echo#AcquireContext()` and `Echo#ReleaseContext()`.
|
// with `Echo#AcquireContext()` and `Echo#ReleaseContext()`.
|
||||||
// See `Echo#ServeHTTP()`
|
// See `Echo#ServeHTTP()`
|
||||||
Reset(r *http.Request, w http.ResponseWriter)
|
Reset(r *http.Request, w http.ResponseWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
context struct {
|
type context struct {
|
||||||
request *http.Request
|
request *http.Request
|
||||||
response *Response
|
response *Response
|
||||||
path string
|
|
||||||
pnames []string
|
|
||||||
pvalues []string
|
|
||||||
query url.Values
|
query url.Values
|
||||||
handler HandlerFunc
|
|
||||||
store Map
|
|
||||||
echo *Echo
|
echo *Echo
|
||||||
logger Logger
|
logger Logger
|
||||||
|
|
||||||
|
store Map
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
|
||||||
)
|
// following fields are set by Router
|
||||||
|
|
||||||
|
// path is route path that Router matched. It is empty string where there is no route match.
|
||||||
|
// Route registered with RouteNotFound is considered as a match and path therefore is not empty.
|
||||||
|
path string
|
||||||
|
|
||||||
|
// pnames length is tied to param count for the matched route
|
||||||
|
pnames []string
|
||||||
|
|
||||||
|
// Usually echo.Echo is sizing pvalues but there could be user created middlewares that decide to
|
||||||
|
// overwrite parameter by calling SetParamNames + SetParamValues.
|
||||||
|
// When echo.Echo allocated that slice it length/capacity is tied to echo.Echo.maxParam value.
|
||||||
|
//
|
||||||
|
// It is important that pvalues size is always equal or bigger to pnames length.
|
||||||
|
pvalues []string
|
||||||
|
handler HandlerFunc
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ContextKeyHeaderAllow is set by Router for getting value for `Allow` header in later stages of handler call chain.
|
// ContextKeyHeaderAllow is set by Router for getting value for `Allow` header in later stages of handler call chain.
|
||||||
@ -329,13 +344,9 @@ func (c *context) SetParamNames(names ...string) {
|
|||||||
c.pnames = names
|
c.pnames = names
|
||||||
|
|
||||||
l := len(names)
|
l := len(names)
|
||||||
if *c.echo.maxParam < l {
|
|
||||||
*c.echo.maxParam = l
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.pvalues) < l {
|
if len(c.pvalues) < l {
|
||||||
// Keeping the old pvalues just for backward compatibility, but it sounds that doesn't make sense to keep them,
|
// Keeping the old pvalues just for backward compatibility, but it sounds that doesn't make sense to keep them,
|
||||||
// probably those values will be overriden in a Context#SetParamValues
|
// probably those values will be overridden in a Context#SetParamValues
|
||||||
newPvalues := make([]string, l)
|
newPvalues := make([]string, l)
|
||||||
copy(newPvalues, c.pvalues)
|
copy(newPvalues, c.pvalues)
|
||||||
c.pvalues = newPvalues
|
c.pvalues = newPvalues
|
||||||
@ -347,11 +358,11 @@ func (c *context) ParamValues() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) SetParamValues(values ...string) {
|
func (c *context) SetParamValues(values ...string) {
|
||||||
// NOTE: Don't just set c.pvalues = values, because it has to have length c.echo.maxParam at all times
|
// NOTE: Don't just set c.pvalues = values, because it has to have length c.echo.maxParam (or bigger) at all times
|
||||||
// It will brake the Router#Find code
|
// It will brake the Router#Find code
|
||||||
limit := len(values)
|
limit := len(values)
|
||||||
if limit > *c.echo.maxParam {
|
if limit > len(c.pvalues) {
|
||||||
limit = *c.echo.maxParam
|
c.pvalues = make([]string, limit)
|
||||||
}
|
}
|
||||||
for i := 0; i < limit; i++ {
|
for i := 0; i < limit; i++ {
|
||||||
c.pvalues[i] = values[i]
|
c.pvalues[i] = values[i]
|
||||||
@ -489,7 +500,7 @@ func (c *context) jsonPBlob(code int, callback string, i interface{}) (err error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) json(code int, i interface{}, indent string) error {
|
func (c *context) json(code int, i interface{}, indent string) error {
|
||||||
c.writeContentType(MIMEApplicationJSONCharsetUTF8)
|
c.writeContentType(MIMEApplicationJSON)
|
||||||
c.response.Status = code
|
c.response.Status = code
|
||||||
return c.echo.JSONSerializer.Serialize(c, i, indent)
|
return c.echo.JSONSerializer.Serialize(c, i, indent)
|
||||||
}
|
}
|
||||||
@ -507,7 +518,7 @@ func (c *context) JSONPretty(code int, i interface{}, indent string) (err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) JSONBlob(code int, b []byte) (err error) {
|
func (c *context) JSONBlob(code int, b []byte) (err error) {
|
||||||
return c.Blob(code, MIMEApplicationJSONCharsetUTF8, b)
|
return c.Blob(code, MIMEApplicationJSON, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
|
func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
|
||||||
@ -584,8 +595,10 @@ func (c *context) Inline(file, name string) error {
|
|||||||
return c.contentDisposition(file, name, "inline")
|
return c.contentDisposition(file, name, "inline")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
|
||||||
|
|
||||||
func (c *context) contentDisposition(file, name, dispositionType string) error {
|
func (c *context) contentDisposition(file, name, dispositionType string) error {
|
||||||
c.response.Header().Set(HeaderContentDisposition, fmt.Sprintf("%s; filename=%q", dispositionType, name))
|
c.response.Header().Set(HeaderContentDisposition, fmt.Sprintf(`%s; filename="%s"`, dispositionType, quoteEscaper.Replace(name)))
|
||||||
return c.File(file)
|
return c.File(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,8 +653,8 @@ func (c *context) Reset(r *http.Request, w http.ResponseWriter) {
|
|||||||
c.path = ""
|
c.path = ""
|
||||||
c.pnames = nil
|
c.pnames = nil
|
||||||
c.logger = nil
|
c.logger = nil
|
||||||
// NOTE: Don't reset because it has to have length c.echo.maxParam at all times
|
// NOTE: Don't reset because it has to have length c.echo.maxParam (or bigger) at all times
|
||||||
for i := 0; i < *c.echo.maxParam; i++ {
|
for i := 0; i < len(c.pvalues); i++ {
|
||||||
c.pvalues[i] = ""
|
c.pvalues[i] = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
vendor/github.com/labstack/echo/v4/context_fs.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/context_fs.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
101
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
101
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package echo implements high performance, minimalist Go web framework.
|
Package echo implements high performance, minimalist Go web framework.
|
||||||
|
|
||||||
@ -60,17 +63,16 @@ import (
|
|||||||
"golang.org/x/net/http2/h2c"
|
"golang.org/x/net/http2/h2c"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
// Echo is the top-level framework instance.
|
||||||
// Echo is the top-level framework instance.
|
//
|
||||||
//
|
// Goroutine safety: Do not mutate Echo instance fields after server has started. Accessing these
|
||||||
// Goroutine safety: Do not mutate Echo instance fields after server has started. Accessing these
|
// fields from handlers/middlewares and changing field values at the same time leads to data-races.
|
||||||
// fields from handlers/middlewares and changing field values at the same time leads to data-races.
|
// Adding new routes after the server has been started is also not safe!
|
||||||
// Adding new routes after the server has been started is also not safe!
|
type Echo struct {
|
||||||
Echo struct {
|
|
||||||
filesystem
|
filesystem
|
||||||
common
|
common
|
||||||
// startupMutex is mutex to lock Echo instance access during server configuration and startup. Useful for to get
|
// startupMutex is mutex to lock Echo instance access during server configuration and startup. Useful for to get
|
||||||
// listener address info (on which interface/port was listener binded) without having data races.
|
// listener address info (on which interface/port was listener bound) without having data races.
|
||||||
startupMutex sync.RWMutex
|
startupMutex sync.RWMutex
|
||||||
colorer *color.Color
|
colorer *color.Color
|
||||||
|
|
||||||
@ -104,53 +106,52 @@ type (
|
|||||||
|
|
||||||
// OnAddRouteHandler is called when Echo adds new route to specific host router.
|
// OnAddRouteHandler is called when Echo adds new route to specific host router.
|
||||||
OnAddRouteHandler func(host string, route Route, handler HandlerFunc, middleware []MiddlewareFunc)
|
OnAddRouteHandler func(host string, route Route, handler HandlerFunc, middleware []MiddlewareFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Route contains a handler and information for matching against requests.
|
// Route contains a handler and information for matching against requests.
|
||||||
Route struct {
|
type Route struct {
|
||||||
Method string `json:"method"`
|
Method string `json:"method"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPError represents an error that occurred while handling a request.
|
// HTTPError represents an error that occurred while handling a request.
|
||||||
HTTPError struct {
|
type HTTPError struct {
|
||||||
Code int `json:"-"`
|
Code int `json:"-"`
|
||||||
Message interface{} `json:"message"`
|
Message interface{} `json:"message"`
|
||||||
Internal error `json:"-"` // Stores the error returned by an external dependency
|
Internal error `json:"-"` // Stores the error returned by an external dependency
|
||||||
}
|
}
|
||||||
|
|
||||||
// MiddlewareFunc defines a function to process middleware.
|
// MiddlewareFunc defines a function to process middleware.
|
||||||
MiddlewareFunc func(next HandlerFunc) HandlerFunc
|
type MiddlewareFunc func(next HandlerFunc) HandlerFunc
|
||||||
|
|
||||||
// HandlerFunc defines a function to serve HTTP requests.
|
// HandlerFunc defines a function to serve HTTP requests.
|
||||||
HandlerFunc func(c Context) error
|
type HandlerFunc func(c Context) error
|
||||||
|
|
||||||
// HTTPErrorHandler is a centralized HTTP error handler.
|
// HTTPErrorHandler is a centralized HTTP error handler.
|
||||||
HTTPErrorHandler func(err error, c Context)
|
type HTTPErrorHandler func(err error, c Context)
|
||||||
|
|
||||||
// Validator is the interface that wraps the Validate function.
|
// Validator is the interface that wraps the Validate function.
|
||||||
Validator interface {
|
type Validator interface {
|
||||||
Validate(i interface{}) error
|
Validate(i interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONSerializer is the interface that encodes and decodes JSON to and from interfaces.
|
// JSONSerializer is the interface that encodes and decodes JSON to and from interfaces.
|
||||||
JSONSerializer interface {
|
type JSONSerializer interface {
|
||||||
Serialize(c Context, i interface{}, indent string) error
|
Serialize(c Context, i interface{}, indent string) error
|
||||||
Deserialize(c Context, i interface{}) error
|
Deserialize(c Context, i interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderer is the interface that wraps the Render function.
|
// Renderer is the interface that wraps the Render function.
|
||||||
Renderer interface {
|
type Renderer interface {
|
||||||
Render(io.Writer, string, interface{}, Context) error
|
Render(io.Writer, string, interface{}, Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map defines a generic map of type `map[string]interface{}`.
|
// Map defines a generic map of type `map[string]interface{}`.
|
||||||
Map map[string]interface{}
|
type Map map[string]interface{}
|
||||||
|
|
||||||
// Common struct for Echo & Group.
|
// Common struct for Echo & Group.
|
||||||
common struct{}
|
type common struct{}
|
||||||
)
|
|
||||||
|
|
||||||
// HTTP methods
|
// HTTP methods
|
||||||
// NOTE: Deprecated, please use the stdlib constants directly instead.
|
// NOTE: Deprecated, please use the stdlib constants directly instead.
|
||||||
@ -169,7 +170,12 @@ const (
|
|||||||
|
|
||||||
// MIME types
|
// MIME types
|
||||||
const (
|
const (
|
||||||
|
// MIMEApplicationJSON JavaScript Object Notation (JSON) https://www.rfc-editor.org/rfc/rfc8259
|
||||||
MIMEApplicationJSON = "application/json"
|
MIMEApplicationJSON = "application/json"
|
||||||
|
// Deprecated: Please use MIMEApplicationJSON instead. JSON should be encoded using UTF-8 by default.
|
||||||
|
// No "charset" parameter is defined for this registration.
|
||||||
|
// Adding one really has no effect on compliant recipients.
|
||||||
|
// See RFC 8259, section 8.1. https://datatracker.ietf.org/doc/html/rfc8259#section-8.1
|
||||||
MIMEApplicationJSONCharsetUTF8 = MIMEApplicationJSON + "; " + charsetUTF8
|
MIMEApplicationJSONCharsetUTF8 = MIMEApplicationJSON + "; " + charsetUTF8
|
||||||
MIMEApplicationJavaScript = "application/javascript"
|
MIMEApplicationJavaScript = "application/javascript"
|
||||||
MIMEApplicationJavaScriptCharsetUTF8 = MIMEApplicationJavaScript + "; " + charsetUTF8
|
MIMEApplicationJavaScriptCharsetUTF8 = MIMEApplicationJavaScript + "; " + charsetUTF8
|
||||||
@ -259,7 +265,7 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Version of Echo
|
// Version of Echo
|
||||||
Version = "4.11.2"
|
Version = "4.12.0"
|
||||||
website = "https://echo.labstack.com"
|
website = "https://echo.labstack.com"
|
||||||
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
|
||||||
banner = `
|
banner = `
|
||||||
@ -274,8 +280,7 @@ ____________________________________O/_______
|
|||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var methods = [...]string{
|
||||||
methods = [...]string{
|
|
||||||
http.MethodConnect,
|
http.MethodConnect,
|
||||||
http.MethodDelete,
|
http.MethodDelete,
|
||||||
http.MethodGet,
|
http.MethodGet,
|
||||||
@ -287,8 +292,7 @@ var (
|
|||||||
http.MethodPut,
|
http.MethodPut,
|
||||||
http.MethodTrace,
|
http.MethodTrace,
|
||||||
REPORT,
|
REPORT,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
var (
|
var (
|
||||||
@ -341,13 +345,15 @@ var (
|
|||||||
ErrInvalidListenerNetwork = errors.New("invalid listener network")
|
ErrInvalidListenerNetwork = errors.New("invalid listener network")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error handlers
|
// NotFoundHandler is the handler that router uses in case there was no matching route found. Returns an error that results
|
||||||
var (
|
// HTTP 404 status code.
|
||||||
NotFoundHandler = func(c Context) error {
|
var NotFoundHandler = func(c Context) error {
|
||||||
return ErrNotFound
|
return ErrNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodNotAllowedHandler = func(c Context) error {
|
// MethodNotAllowedHandler is the handler thar router uses in case there was no matching route found but there was
|
||||||
|
// another matching routes for that requested URL. Returns an error that results HTTP 405 Method Not Allowed status code.
|
||||||
|
var MethodNotAllowedHandler = func(c Context) error {
|
||||||
// See RFC 7231 section 7.4.1: An origin server MUST generate an Allow field in a 405 (Method Not Allowed)
|
// See RFC 7231 section 7.4.1: An origin server MUST generate an Allow field in a 405 (Method Not Allowed)
|
||||||
// response and MAY do so in any other response. For disabled resources an empty Allow header may be returned
|
// response and MAY do so in any other response. For disabled resources an empty Allow header may be returned
|
||||||
routerAllowMethods, ok := c.Get(ContextKeyHeaderAllow).(string)
|
routerAllowMethods, ok := c.Get(ContextKeyHeaderAllow).(string)
|
||||||
@ -355,8 +361,7 @@ var (
|
|||||||
c.Response().Header().Set(HeaderAllow, routerAllowMethods)
|
c.Response().Header().Set(HeaderAllow, routerAllowMethods)
|
||||||
}
|
}
|
||||||
return ErrMethodNotAllowed
|
return ErrMethodNotAllowed
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// New creates an instance of Echo.
|
// New creates an instance of Echo.
|
||||||
func New() (e *Echo) {
|
func New() (e *Echo) {
|
||||||
@ -414,7 +419,7 @@ func (e *Echo) Routers() map[string]*Router {
|
|||||||
//
|
//
|
||||||
// NOTE: In case errors happens in middleware call-chain that is returning from handler (which did not return an error).
|
// NOTE: In case errors happens in middleware call-chain that is returning from handler (which did not return an error).
|
||||||
// When handler has already sent response (ala c.JSON()) and there is error in middleware that is returning from
|
// When handler has already sent response (ala c.JSON()) and there is error in middleware that is returning from
|
||||||
// handler. Then the error that global error handler received will be ignored because we have already "commited" the
|
// handler. Then the error that global error handler received will be ignored because we have already "committed" the
|
||||||
// response and status code header has been sent to the client.
|
// response and status code header has been sent to the client.
|
||||||
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
|
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
|
||||||
|
|
||||||
|
3
vendor/github.com/labstack/echo/v4/echo_fs.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/echo_fs.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
15
vendor/github.com/labstack/echo/v4/group.go
generated
vendored
15
vendor/github.com/labstack/echo/v4/group.go
generated
vendored
@ -1,21 +1,22 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
// Group is a set of sub-routes for a specified route. It can be used for inner
|
||||||
// Group is a set of sub-routes for a specified route. It can be used for inner
|
// routes that share a common middleware or functionality that should be separate
|
||||||
// routes that share a common middleware or functionality that should be separate
|
// from the parent echo instance while still inheriting from it.
|
||||||
// from the parent echo instance while still inheriting from it.
|
type Group struct {
|
||||||
Group struct {
|
|
||||||
common
|
common
|
||||||
host string
|
host string
|
||||||
prefix string
|
prefix string
|
||||||
middleware []MiddlewareFunc
|
middleware []MiddlewareFunc
|
||||||
echo *Echo
|
echo *Echo
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// Use implements `Echo#Use()` for sub-routes within the Group.
|
// Use implements `Echo#Use()` for sub-routes within the Group.
|
||||||
func (g *Group) Use(middleware ...MiddlewareFunc) {
|
func (g *Group) Use(middleware ...MiddlewareFunc) {
|
||||||
|
3
vendor/github.com/labstack/echo/v4/group_fs.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/group_fs.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
17
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
17
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -64,7 +67,7 @@ XFF: "x" "x, a" "x, a, b"
|
|||||||
```
|
```
|
||||||
|
|
||||||
In this case, use **first _untrustable_ IP reading from right**. Never use first one reading from left, as it is
|
In this case, use **first _untrustable_ IP reading from right**. Never use first one reading from left, as it is
|
||||||
configurable by client. Here "trustable" means "you are sure the IP address belongs to your infrastructre".
|
configurable by client. Here "trustable" means "you are sure the IP address belongs to your infrastructure".
|
||||||
In above example, if `b` and `c` are trustable, the IP address of the client is `a` for both cases, never be `x`.
|
In above example, if `b` and `c` are trustable, the IP address of the client is `a` for both cases, never be `x`.
|
||||||
|
|
||||||
In Echo, use `ExtractIPFromXFFHeader(...TrustOption)`.
|
In Echo, use `ExtractIPFromXFFHeader(...TrustOption)`.
|
||||||
@ -225,15 +228,21 @@ func extractIP(req *http.Request) string {
|
|||||||
func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
||||||
checker := newIPChecker(options)
|
checker := newIPChecker(options)
|
||||||
return func(req *http.Request) string {
|
return func(req *http.Request) string {
|
||||||
|
directIP := extractIP(req)
|
||||||
realIP := req.Header.Get(HeaderXRealIP)
|
realIP := req.Header.Get(HeaderXRealIP)
|
||||||
if realIP != "" {
|
if realIP == "" {
|
||||||
|
return directIP
|
||||||
|
}
|
||||||
|
|
||||||
|
if checker.trust(net.ParseIP(directIP)) {
|
||||||
realIP = strings.TrimPrefix(realIP, "[")
|
realIP = strings.TrimPrefix(realIP, "[")
|
||||||
realIP = strings.TrimSuffix(realIP, "]")
|
realIP = strings.TrimSuffix(realIP, "]")
|
||||||
if ip := net.ParseIP(realIP); ip != nil && checker.trust(ip) {
|
if rIP := net.ParseIP(realIP); rIP != nil {
|
||||||
return realIP
|
return realIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return extractIP(req)
|
|
||||||
|
return directIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
vendor/github.com/labstack/echo/v4/json.go
generated
vendored
3
vendor/github.com/labstack/echo/v4/json.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
14
vendor/github.com/labstack/echo/v4/log.go
generated
vendored
14
vendor/github.com/labstack/echo/v4/log.go
generated
vendored
@ -1,14 +1,15 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
// Logger defines the logging interface.
|
||||||
// Logger defines the logging interface.
|
type Logger interface {
|
||||||
Logger interface {
|
|
||||||
Output() io.Writer
|
Output() io.Writer
|
||||||
SetOutput(w io.Writer)
|
SetOutput(w io.Writer)
|
||||||
Prefix() string
|
Prefix() string
|
||||||
@ -37,5 +38,4 @@ type (
|
|||||||
Panic(i ...interface{})
|
Panic(i ...interface{})
|
||||||
Panicj(j log.JSON)
|
Panicj(j log.JSON)
|
||||||
Panicf(format string, args ...interface{})
|
Panicf(format string, args ...interface{})
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
23
vendor/github.com/labstack/echo/v4/response.go
generated
vendored
23
vendor/github.com/labstack/echo/v4/response.go
generated
vendored
@ -1,16 +1,19 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
// Response wraps an http.ResponseWriter and implements its interface to be used
|
||||||
// Response wraps an http.ResponseWriter and implements its interface to be used
|
// by an HTTP handler to construct an HTTP response.
|
||||||
// by an HTTP handler to construct an HTTP response.
|
// See: https://golang.org/pkg/net/http/#ResponseWriter
|
||||||
// See: https://golang.org/pkg/net/http/#ResponseWriter
|
type Response struct {
|
||||||
Response struct {
|
|
||||||
echo *Echo
|
echo *Echo
|
||||||
beforeFuncs []func()
|
beforeFuncs []func()
|
||||||
afterFuncs []func()
|
afterFuncs []func()
|
||||||
@ -18,8 +21,7 @@ type (
|
|||||||
Status int
|
Status int
|
||||||
Size int64
|
Size int64
|
||||||
Committed bool
|
Committed bool
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// NewResponse creates a new instance of Response.
|
// NewResponse creates a new instance of Response.
|
||||||
func NewResponse(w http.ResponseWriter, e *Echo) (r *Response) {
|
func NewResponse(w http.ResponseWriter, e *Echo) (r *Response) {
|
||||||
@ -84,14 +86,17 @@ func (r *Response) Write(b []byte) (n int, err error) {
|
|||||||
// buffered data to the client.
|
// buffered data to the client.
|
||||||
// See [http.Flusher](https://golang.org/pkg/net/http/#Flusher)
|
// See [http.Flusher](https://golang.org/pkg/net/http/#Flusher)
|
||||||
func (r *Response) Flush() {
|
func (r *Response) Flush() {
|
||||||
r.Writer.(http.Flusher).Flush()
|
err := responseControllerFlush(r.Writer)
|
||||||
|
if err != nil && errors.Is(err, http.ErrNotSupported) {
|
||||||
|
panic(errors.New("response writer flushing is not supported"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hijack implements the http.Hijacker interface to allow an HTTP handler to
|
// Hijack implements the http.Hijacker interface to allow an HTTP handler to
|
||||||
// take over the connection.
|
// take over the connection.
|
||||||
// See [http.Hijacker](https://golang.org/pkg/net/http/#Hijacker)
|
// See [http.Hijacker](https://golang.org/pkg/net/http/#Hijacker)
|
||||||
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||||
return r.Writer.(http.Hijacker).Hijack()
|
return responseControllerHijack(r.Writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwrap returns the original http.ResponseWriter.
|
// Unwrap returns the original http.ResponseWriter.
|
||||||
|
44
vendor/github.com/labstack/echo/v4/responsecontroller_1.19.go
generated
vendored
Normal file
44
vendor/github.com/labstack/echo/v4/responsecontroller_1.19.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
|
//go:build !go1.20
|
||||||
|
|
||||||
|
package echo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: remove when Go 1.23 is released and we do not support 1.19 anymore
|
||||||
|
func responseControllerFlush(rw http.ResponseWriter) error {
|
||||||
|
for {
|
||||||
|
switch t := rw.(type) {
|
||||||
|
case interface{ FlushError() error }:
|
||||||
|
return t.FlushError()
|
||||||
|
case http.Flusher:
|
||||||
|
t.Flush()
|
||||||
|
return nil
|
||||||
|
case interface{ Unwrap() http.ResponseWriter }:
|
||||||
|
rw = t.Unwrap()
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("%w", http.ErrNotSupported)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove when Go 1.23 is released and we do not support 1.19 anymore
|
||||||
|
func responseControllerHijack(rw http.ResponseWriter) (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
for {
|
||||||
|
switch t := rw.(type) {
|
||||||
|
case http.Hijacker:
|
||||||
|
return t.Hijack()
|
||||||
|
case interface{ Unwrap() http.ResponseWriter }:
|
||||||
|
rw = t.Unwrap()
|
||||||
|
default:
|
||||||
|
return nil, nil, fmt.Errorf("%w", http.ErrNotSupported)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
vendor/github.com/labstack/echo/v4/responsecontroller_1.20.go
generated
vendored
Normal file
20
vendor/github.com/labstack/echo/v4/responsecontroller_1.20.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
|
//go:build go1.20
|
||||||
|
|
||||||
|
package echo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func responseControllerFlush(rw http.ResponseWriter) error {
|
||||||
|
return http.NewResponseController(rw).Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func responseControllerHijack(rw http.ResponseWriter) (net.Conn, *bufio.ReadWriter, error) {
|
||||||
|
return http.NewResponseController(rw).Hijack()
|
||||||
|
}
|
71
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
71
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -6,15 +9,15 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
// Router is the registry of all registered routes for an `Echo` instance for
|
||||||
// Router is the registry of all registered routes for an `Echo` instance for
|
// request matching and URL path parameter parsing.
|
||||||
// request matching and URL path parameter parsing.
|
type Router struct {
|
||||||
Router struct {
|
|
||||||
tree *node
|
tree *node
|
||||||
routes map[string]*Route
|
routes map[string]*Route
|
||||||
echo *Echo
|
echo *Echo
|
||||||
}
|
}
|
||||||
node struct {
|
|
||||||
|
type node struct {
|
||||||
kind kind
|
kind kind
|
||||||
label byte
|
label byte
|
||||||
prefix string
|
prefix string
|
||||||
@ -32,15 +35,18 @@ type (
|
|||||||
|
|
||||||
// notFoundHandler is handler registered with RouteNotFound method and is executed for 404 cases
|
// notFoundHandler is handler registered with RouteNotFound method and is executed for 404 cases
|
||||||
notFoundHandler *routeMethod
|
notFoundHandler *routeMethod
|
||||||
}
|
}
|
||||||
kind uint8
|
|
||||||
children []*node
|
type kind uint8
|
||||||
routeMethod struct {
|
type children []*node
|
||||||
|
|
||||||
|
type routeMethod struct {
|
||||||
ppath string
|
ppath string
|
||||||
pnames []string
|
pnames []string
|
||||||
handler HandlerFunc
|
handler HandlerFunc
|
||||||
}
|
}
|
||||||
routeMethods struct {
|
|
||||||
|
type routeMethods struct {
|
||||||
connect *routeMethod
|
connect *routeMethod
|
||||||
delete *routeMethod
|
delete *routeMethod
|
||||||
get *routeMethod
|
get *routeMethod
|
||||||
@ -54,8 +60,7 @@ type (
|
|||||||
report *routeMethod
|
report *routeMethod
|
||||||
anyOther map[string]*routeMethod
|
anyOther map[string]*routeMethod
|
||||||
allowHeader string
|
allowHeader string
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
staticKind kind = iota
|
staticKind kind = iota
|
||||||
@ -180,8 +185,18 @@ func (r *Router) Reverse(name string, params ...interface{}) string {
|
|||||||
return uri.String()
|
return uri.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalizePathSlash(path string) string {
|
||||||
|
if path == "" {
|
||||||
|
path = "/"
|
||||||
|
} else if path[0] != '/' {
|
||||||
|
path = "/" + path
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Router) add(method, path, name string, h HandlerFunc) *Route {
|
func (r *Router) add(method, path, name string, h HandlerFunc) *Route {
|
||||||
r.Add(method, path, h)
|
path = normalizePathSlash(path)
|
||||||
|
r.insert(method, path, h)
|
||||||
|
|
||||||
route := &Route{
|
route := &Route{
|
||||||
Method: method,
|
Method: method,
|
||||||
@ -194,13 +209,11 @@ func (r *Router) add(method, path, name string, h HandlerFunc) *Route {
|
|||||||
|
|
||||||
// Add registers a new route for method and path with matching handler.
|
// Add registers a new route for method and path with matching handler.
|
||||||
func (r *Router) Add(method, path string, h HandlerFunc) {
|
func (r *Router) Add(method, path string, h HandlerFunc) {
|
||||||
// Validate path
|
r.insert(method, normalizePathSlash(path), h)
|
||||||
if path == "" {
|
}
|
||||||
path = "/"
|
|
||||||
}
|
func (r *Router) insert(method, path string, h HandlerFunc) {
|
||||||
if path[0] != '/' {
|
path = normalizePathSlash(path)
|
||||||
path = "/" + path
|
|
||||||
}
|
|
||||||
pnames := []string{} // Param names
|
pnames := []string{} // Param names
|
||||||
ppath := path // Pristine path
|
ppath := path // Pristine path
|
||||||
|
|
||||||
@ -219,7 +232,7 @@ func (r *Router) Add(method, path string, h HandlerFunc) {
|
|||||||
}
|
}
|
||||||
j := i + 1
|
j := i + 1
|
||||||
|
|
||||||
r.insert(method, path[:i], staticKind, routeMethod{})
|
r.insertNode(method, path[:i], staticKind, routeMethod{})
|
||||||
for ; i < lcpIndex && path[i] != '/'; i++ {
|
for ; i < lcpIndex && path[i] != '/'; i++ {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,21 +242,21 @@ func (r *Router) Add(method, path string, h HandlerFunc) {
|
|||||||
|
|
||||||
if i == lcpIndex {
|
if i == lcpIndex {
|
||||||
// path node is last fragment of route path. ie. `/users/:id`
|
// path node is last fragment of route path. ie. `/users/:id`
|
||||||
r.insert(method, path[:i], paramKind, routeMethod{ppath, pnames, h})
|
r.insertNode(method, path[:i], paramKind, routeMethod{ppath, pnames, h})
|
||||||
} else {
|
} else {
|
||||||
r.insert(method, path[:i], paramKind, routeMethod{})
|
r.insertNode(method, path[:i], paramKind, routeMethod{})
|
||||||
}
|
}
|
||||||
} else if path[i] == '*' {
|
} else if path[i] == '*' {
|
||||||
r.insert(method, path[:i], staticKind, routeMethod{})
|
r.insertNode(method, path[:i], staticKind, routeMethod{})
|
||||||
pnames = append(pnames, "*")
|
pnames = append(pnames, "*")
|
||||||
r.insert(method, path[:i+1], anyKind, routeMethod{ppath, pnames, h})
|
r.insertNode(method, path[:i+1], anyKind, routeMethod{ppath, pnames, h})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.insert(method, path, staticKind, routeMethod{ppath, pnames, h})
|
r.insertNode(method, path, staticKind, routeMethod{ppath, pnames, h})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) insert(method, path string, t kind, rm routeMethod) {
|
func (r *Router) insertNode(method, path string, t kind, rm routeMethod) {
|
||||||
// Adjust max param
|
// Adjust max param
|
||||||
paramLen := len(rm.pnames)
|
paramLen := len(rm.pnames)
|
||||||
if *r.echo.maxParam < paramLen {
|
if *r.echo.maxParam < paramLen {
|
||||||
|
1
vendor/golang.org/x/crypto/acme/version_go112.go
generated
vendored
1
vendor/golang.org/x/crypto/acme/version_go112.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.12
|
//go:build go1.12
|
||||||
// +build go1.12
|
|
||||||
|
|
||||||
package acme
|
package acme
|
||||||
|
|
||||||
|
12
vendor/golang.org/x/net/html/token.go
generated
vendored
12
vendor/golang.org/x/net/html/token.go
generated
vendored
@ -910,9 +910,6 @@ func (z *Tokenizer) readTagAttrKey() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch c {
|
switch c {
|
||||||
case ' ', '\n', '\r', '\t', '\f', '/':
|
|
||||||
z.pendingAttr[0].end = z.raw.end - 1
|
|
||||||
return
|
|
||||||
case '=':
|
case '=':
|
||||||
if z.pendingAttr[0].start+1 == z.raw.end {
|
if z.pendingAttr[0].start+1 == z.raw.end {
|
||||||
// WHATWG 13.2.5.32, if we see an equals sign before the attribute name
|
// WHATWG 13.2.5.32, if we see an equals sign before the attribute name
|
||||||
@ -920,7 +917,9 @@ func (z *Tokenizer) readTagAttrKey() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case '>':
|
case ' ', '\n', '\r', '\t', '\f', '/', '>':
|
||||||
|
// WHATWG 13.2.5.33 Attribute name state
|
||||||
|
// We need to reconsume the char in the after attribute name state to support the / character
|
||||||
z.raw.end--
|
z.raw.end--
|
||||||
z.pendingAttr[0].end = z.raw.end
|
z.pendingAttr[0].end = z.raw.end
|
||||||
return
|
return
|
||||||
@ -939,6 +938,11 @@ func (z *Tokenizer) readTagAttrVal() {
|
|||||||
if z.err != nil {
|
if z.err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if c == '/' {
|
||||||
|
// WHATWG 13.2.5.34 After attribute name state
|
||||||
|
// U+002F SOLIDUS (/) - Switch to the self-closing start tag state.
|
||||||
|
return
|
||||||
|
}
|
||||||
if c != '=' {
|
if c != '=' {
|
||||||
z.raw.end--
|
z.raw.end--
|
||||||
return
|
return
|
||||||
|
59
vendor/golang.org/x/net/http2/databuffer.go
generated
vendored
59
vendor/golang.org/x/net/http2/databuffer.go
generated
vendored
@ -20,41 +20,44 @@ import (
|
|||||||
// TODO: Benchmark to determine if the pools are necessary. The GC may have
|
// TODO: Benchmark to determine if the pools are necessary. The GC may have
|
||||||
// improved enough that we can instead allocate chunks like this:
|
// improved enough that we can instead allocate chunks like this:
|
||||||
// make([]byte, max(16<<10, expectedBytesRemaining))
|
// make([]byte, max(16<<10, expectedBytesRemaining))
|
||||||
var (
|
var dataChunkPools = [...]sync.Pool{
|
||||||
dataChunkSizeClasses = []int{
|
{New: func() interface{} { return new([1 << 10]byte) }},
|
||||||
1 << 10,
|
{New: func() interface{} { return new([2 << 10]byte) }},
|
||||||
2 << 10,
|
{New: func() interface{} { return new([4 << 10]byte) }},
|
||||||
4 << 10,
|
{New: func() interface{} { return new([8 << 10]byte) }},
|
||||||
8 << 10,
|
{New: func() interface{} { return new([16 << 10]byte) }},
|
||||||
16 << 10,
|
}
|
||||||
}
|
|
||||||
dataChunkPools = [...]sync.Pool{
|
|
||||||
{New: func() interface{} { return make([]byte, 1<<10) }},
|
|
||||||
{New: func() interface{} { return make([]byte, 2<<10) }},
|
|
||||||
{New: func() interface{} { return make([]byte, 4<<10) }},
|
|
||||||
{New: func() interface{} { return make([]byte, 8<<10) }},
|
|
||||||
{New: func() interface{} { return make([]byte, 16<<10) }},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func getDataBufferChunk(size int64) []byte {
|
func getDataBufferChunk(size int64) []byte {
|
||||||
i := 0
|
switch {
|
||||||
for ; i < len(dataChunkSizeClasses)-1; i++ {
|
case size <= 1<<10:
|
||||||
if size <= int64(dataChunkSizeClasses[i]) {
|
return dataChunkPools[0].Get().(*[1 << 10]byte)[:]
|
||||||
break
|
case size <= 2<<10:
|
||||||
|
return dataChunkPools[1].Get().(*[2 << 10]byte)[:]
|
||||||
|
case size <= 4<<10:
|
||||||
|
return dataChunkPools[2].Get().(*[4 << 10]byte)[:]
|
||||||
|
case size <= 8<<10:
|
||||||
|
return dataChunkPools[3].Get().(*[8 << 10]byte)[:]
|
||||||
|
default:
|
||||||
|
return dataChunkPools[4].Get().(*[16 << 10]byte)[:]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return dataChunkPools[i].Get().([]byte)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func putDataBufferChunk(p []byte) {
|
func putDataBufferChunk(p []byte) {
|
||||||
for i, n := range dataChunkSizeClasses {
|
switch len(p) {
|
||||||
if len(p) == n {
|
case 1 << 10:
|
||||||
dataChunkPools[i].Put(p)
|
dataChunkPools[0].Put((*[1 << 10]byte)(p))
|
||||||
return
|
case 2 << 10:
|
||||||
}
|
dataChunkPools[1].Put((*[2 << 10]byte)(p))
|
||||||
}
|
case 4 << 10:
|
||||||
|
dataChunkPools[2].Put((*[4 << 10]byte)(p))
|
||||||
|
case 8 << 10:
|
||||||
|
dataChunkPools[3].Put((*[8 << 10]byte)(p))
|
||||||
|
case 16 << 10:
|
||||||
|
dataChunkPools[4].Put((*[16 << 10]byte)(p))
|
||||||
|
default:
|
||||||
panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
|
panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dataBuffer is an io.ReadWriter backed by a list of data chunks.
|
// dataBuffer is an io.ReadWriter backed by a list of data chunks.
|
||||||
|
42
vendor/golang.org/x/net/http2/frame.go
generated
vendored
42
vendor/golang.org/x/net/http2/frame.go
generated
vendored
@ -1510,13 +1510,12 @@ func (mh *MetaHeadersFrame) checkPseudos() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fr *Framer) maxHeaderStringLen() int {
|
func (fr *Framer) maxHeaderStringLen() int {
|
||||||
v := fr.maxHeaderListSize()
|
v := int(fr.maxHeaderListSize())
|
||||||
if uint32(int(v)) == v {
|
if v < 0 {
|
||||||
return int(v)
|
// If maxHeaderListSize overflows an int, use no limit (0).
|
||||||
}
|
|
||||||
// They had a crazy big number for MaxHeaderBytes anyway,
|
|
||||||
// so give them unlimited header lengths:
|
|
||||||
return 0
|
return 0
|
||||||
|
}
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
|
// readMetaFrame returns 0 or more CONTINUATION frames from fr and
|
||||||
@ -1565,6 +1564,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
|||||||
if size > remainSize {
|
if size > remainSize {
|
||||||
hdec.SetEmitEnabled(false)
|
hdec.SetEmitEnabled(false)
|
||||||
mh.Truncated = true
|
mh.Truncated = true
|
||||||
|
remainSize = 0
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
remainSize -= size
|
remainSize -= size
|
||||||
@ -1577,6 +1577,36 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
|
|||||||
var hc headersOrContinuation = hf
|
var hc headersOrContinuation = hf
|
||||||
for {
|
for {
|
||||||
frag := hc.HeaderBlockFragment()
|
frag := hc.HeaderBlockFragment()
|
||||||
|
|
||||||
|
// Avoid parsing large amounts of headers that we will then discard.
|
||||||
|
// If the sender exceeds the max header list size by too much,
|
||||||
|
// skip parsing the fragment and close the connection.
|
||||||
|
//
|
||||||
|
// "Too much" is either any CONTINUATION frame after we've already
|
||||||
|
// exceeded the max header list size (in which case remainSize is 0),
|
||||||
|
// or a frame whose encoded size is more than twice the remaining
|
||||||
|
// header list bytes we're willing to accept.
|
||||||
|
if int64(len(frag)) > int64(2*remainSize) {
|
||||||
|
if VerboseLogs {
|
||||||
|
log.Printf("http2: header list too large")
|
||||||
|
}
|
||||||
|
// It would be nice to send a RST_STREAM before sending the GOAWAY,
|
||||||
|
// but the structure of the server's frame writer makes this difficult.
|
||||||
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also close the connection after any CONTINUATION frame following an
|
||||||
|
// invalid header, since we stop tracking the size of the headers after
|
||||||
|
// an invalid one.
|
||||||
|
if invalid != nil {
|
||||||
|
if VerboseLogs {
|
||||||
|
log.Printf("http2: invalid header: %v", invalid)
|
||||||
|
}
|
||||||
|
// It would be nice to send a RST_STREAM before sending the GOAWAY,
|
||||||
|
// but the structure of the server's frame writer makes this difficult.
|
||||||
|
return nil, ConnectionError(ErrCodeProtocol)
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := hdec.Write(frag); err != nil {
|
if _, err := hdec.Write(frag); err != nil {
|
||||||
return nil, ConnectionError(ErrCodeCompression)
|
return nil, ConnectionError(ErrCodeCompression)
|
||||||
}
|
}
|
||||||
|
30
vendor/golang.org/x/net/http2/go111.go
generated
vendored
30
vendor/golang.org/x/net/http2/go111.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build go1.11
|
|
||||||
// +build go1.11
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http/httptrace"
|
|
||||||
"net/textproto"
|
|
||||||
)
|
|
||||||
|
|
||||||
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool {
|
|
||||||
return trace != nil && trace.WroteHeaderField != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {
|
|
||||||
if trace != nil && trace.WroteHeaderField != nil {
|
|
||||||
trace.WroteHeaderField(k, []string{v})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
|
|
||||||
if trace != nil {
|
|
||||||
return trace.Got1xxResponse
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
27
vendor/golang.org/x/net/http2/go115.go
generated
vendored
27
vendor/golang.org/x/net/http2/go115.go
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build go1.15
|
|
||||||
// +build go1.15
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
// dialTLSWithContext uses tls.Dialer, added in Go 1.15, to open a TLS
|
|
||||||
// connection.
|
|
||||||
func (t *Transport) dialTLSWithContext(ctx context.Context, network, addr string, cfg *tls.Config) (*tls.Conn, error) {
|
|
||||||
dialer := &tls.Dialer{
|
|
||||||
Config: cfg,
|
|
||||||
}
|
|
||||||
cn, err := dialer.DialContext(ctx, network, addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
tlsCn := cn.(*tls.Conn) // DialContext comment promises this will always succeed
|
|
||||||
return tlsCn, nil
|
|
||||||
}
|
|
17
vendor/golang.org/x/net/http2/go118.go
generated
vendored
17
vendor/golang.org/x/net/http2/go118.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build go1.18
|
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
func tlsUnderlyingConn(tc *tls.Conn) net.Conn {
|
|
||||||
return tc.NetConn()
|
|
||||||
}
|
|
21
vendor/golang.org/x/net/http2/not_go111.go
generated
vendored
21
vendor/golang.org/x/net/http2/not_go111.go
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !go1.11
|
|
||||||
// +build !go1.11
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http/httptrace"
|
|
||||||
"net/textproto"
|
|
||||||
)
|
|
||||||
|
|
||||||
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool { return false }
|
|
||||||
|
|
||||||
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {}
|
|
||||||
|
|
||||||
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
31
vendor/golang.org/x/net/http2/not_go115.go
generated
vendored
31
vendor/golang.org/x/net/http2/not_go115.go
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !go1.15
|
|
||||||
// +build !go1.15
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
// dialTLSWithContext opens a TLS connection.
|
|
||||||
func (t *Transport) dialTLSWithContext(ctx context.Context, network, addr string, cfg *tls.Config) (*tls.Conn, error) {
|
|
||||||
cn, err := tls.Dial(network, addr, cfg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := cn.Handshake(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if cfg.InsecureSkipVerify {
|
|
||||||
return cn, nil
|
|
||||||
}
|
|
||||||
if err := cn.VerifyHostname(cfg.ServerName); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return cn, nil
|
|
||||||
}
|
|
17
vendor/golang.org/x/net/http2/not_go118.go
generated
vendored
17
vendor/golang.org/x/net/http2/not_go118.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !go1.18
|
|
||||||
// +build !go1.18
|
|
||||||
|
|
||||||
package http2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
func tlsUnderlyingConn(tc *tls.Conn) net.Conn {
|
|
||||||
return nil
|
|
||||||
}
|
|
11
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
11
vendor/golang.org/x/net/http2/pipe.go
generated
vendored
@ -77,7 +77,10 @@ func (p *pipe) Read(d []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var errClosedPipeWrite = errors.New("write on closed buffer")
|
var (
|
||||||
|
errClosedPipeWrite = errors.New("write on closed buffer")
|
||||||
|
errUninitializedPipeWrite = errors.New("write on uninitialized buffer")
|
||||||
|
)
|
||||||
|
|
||||||
// Write copies bytes from p into the buffer and wakes a reader.
|
// Write copies bytes from p into the buffer and wakes a reader.
|
||||||
// It is an error to write more data than the buffer can hold.
|
// It is an error to write more data than the buffer can hold.
|
||||||
@ -91,6 +94,12 @@ func (p *pipe) Write(d []byte) (n int, err error) {
|
|||||||
if p.err != nil || p.breakErr != nil {
|
if p.err != nil || p.breakErr != nil {
|
||||||
return 0, errClosedPipeWrite
|
return 0, errClosedPipeWrite
|
||||||
}
|
}
|
||||||
|
// pipe.setBuffer is never invoked, leaving the buffer uninitialized.
|
||||||
|
// We shouldn't try to write to an uninitialized pipe,
|
||||||
|
// but returning an error is better than panicking.
|
||||||
|
if p.b == nil {
|
||||||
|
return 0, errUninitializedPipeWrite
|
||||||
|
}
|
||||||
return p.b.Write(d)
|
return p.b.Write(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
vendor/golang.org/x/net/http2/server.go
generated
vendored
35
vendor/golang.org/x/net/http2/server.go
generated
vendored
@ -124,6 +124,7 @@ type Server struct {
|
|||||||
// IdleTimeout specifies how long until idle clients should be
|
// IdleTimeout specifies how long until idle clients should be
|
||||||
// closed with a GOAWAY frame. PING frames are not considered
|
// closed with a GOAWAY frame. PING frames are not considered
|
||||||
// activity for the purposes of IdleTimeout.
|
// activity for the purposes of IdleTimeout.
|
||||||
|
// If zero or negative, there is no timeout.
|
||||||
IdleTimeout time.Duration
|
IdleTimeout time.Duration
|
||||||
|
|
||||||
// MaxUploadBufferPerConnection is the size of the initial flow
|
// MaxUploadBufferPerConnection is the size of the initial flow
|
||||||
@ -434,7 +435,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
|||||||
// passes the connection off to us with the deadline already set.
|
// passes the connection off to us with the deadline already set.
|
||||||
// Write deadlines are set per stream in serverConn.newStream.
|
// Write deadlines are set per stream in serverConn.newStream.
|
||||||
// Disarm the net.Conn write deadline here.
|
// Disarm the net.Conn write deadline here.
|
||||||
if sc.hs.WriteTimeout != 0 {
|
if sc.hs.WriteTimeout > 0 {
|
||||||
sc.conn.SetWriteDeadline(time.Time{})
|
sc.conn.SetWriteDeadline(time.Time{})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -924,7 +925,7 @@ func (sc *serverConn) serve() {
|
|||||||
sc.setConnState(http.StateActive)
|
sc.setConnState(http.StateActive)
|
||||||
sc.setConnState(http.StateIdle)
|
sc.setConnState(http.StateIdle)
|
||||||
|
|
||||||
if sc.srv.IdleTimeout != 0 {
|
if sc.srv.IdleTimeout > 0 {
|
||||||
sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
|
sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
|
||||||
defer sc.idleTimer.Stop()
|
defer sc.idleTimer.Stop()
|
||||||
}
|
}
|
||||||
@ -1637,7 +1638,7 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
|||||||
delete(sc.streams, st.id)
|
delete(sc.streams, st.id)
|
||||||
if len(sc.streams) == 0 {
|
if len(sc.streams) == 0 {
|
||||||
sc.setConnState(http.StateIdle)
|
sc.setConnState(http.StateIdle)
|
||||||
if sc.srv.IdleTimeout != 0 {
|
if sc.srv.IdleTimeout > 0 {
|
||||||
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
sc.idleTimer.Reset(sc.srv.IdleTimeout)
|
||||||
}
|
}
|
||||||
if h1ServerKeepAlivesDisabled(sc.hs) {
|
if h1ServerKeepAlivesDisabled(sc.hs) {
|
||||||
@ -2017,7 +2018,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||||||
// similar to how the http1 server works. Here it's
|
// similar to how the http1 server works. Here it's
|
||||||
// technically more like the http1 Server's ReadHeaderTimeout
|
// technically more like the http1 Server's ReadHeaderTimeout
|
||||||
// (in Go 1.8), though. That's a more sane option anyway.
|
// (in Go 1.8), though. That's a more sane option anyway.
|
||||||
if sc.hs.ReadTimeout != 0 {
|
if sc.hs.ReadTimeout > 0 {
|
||||||
sc.conn.SetReadDeadline(time.Time{})
|
sc.conn.SetReadDeadline(time.Time{})
|
||||||
st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
|
st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
|
||||||
}
|
}
|
||||||
@ -2038,7 +2039,7 @@ func (sc *serverConn) upgradeRequest(req *http.Request) {
|
|||||||
|
|
||||||
// Disable any read deadline set by the net/http package
|
// Disable any read deadline set by the net/http package
|
||||||
// prior to the upgrade.
|
// prior to the upgrade.
|
||||||
if sc.hs.ReadTimeout != 0 {
|
if sc.hs.ReadTimeout > 0 {
|
||||||
sc.conn.SetReadDeadline(time.Time{})
|
sc.conn.SetReadDeadline(time.Time{})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2116,7 +2117,7 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
|
|||||||
st.flow.conn = &sc.flow // link to conn-level counter
|
st.flow.conn = &sc.flow // link to conn-level counter
|
||||||
st.flow.add(sc.initialStreamSendWindowSize)
|
st.flow.add(sc.initialStreamSendWindowSize)
|
||||||
st.inflow.init(sc.srv.initialStreamRecvWindowSize())
|
st.inflow.init(sc.srv.initialStreamRecvWindowSize())
|
||||||
if sc.hs.WriteTimeout != 0 {
|
if sc.hs.WriteTimeout > 0 {
|
||||||
st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
|
st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2549,7 +2550,6 @@ type responseWriterState struct {
|
|||||||
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
|
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
|
||||||
sentHeader bool // have we sent the header frame?
|
sentHeader bool // have we sent the header frame?
|
||||||
handlerDone bool // handler has finished
|
handlerDone bool // handler has finished
|
||||||
dirty bool // a Write failed; don't reuse this responseWriterState
|
|
||||||
|
|
||||||
sentContentLen int64 // non-zero if handler set a Content-Length header
|
sentContentLen int64 // non-zero if handler set a Content-Length header
|
||||||
wroteBytes int64
|
wroteBytes int64
|
||||||
@ -2669,7 +2669,6 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
date: date,
|
date: date,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rws.dirty = true
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if endStream {
|
if endStream {
|
||||||
@ -2690,7 +2689,6 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
if len(p) > 0 || endStream {
|
if len(p) > 0 || endStream {
|
||||||
// only send a 0 byte DATA frame if we're ending the stream.
|
// only send a 0 byte DATA frame if we're ending the stream.
|
||||||
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
|
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
|
||||||
rws.dirty = true
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2702,9 +2700,6 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
trailers: rws.trailers,
|
trailers: rws.trailers,
|
||||||
endStream: true,
|
endStream: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
rws.dirty = true
|
|
||||||
}
|
|
||||||
return len(p), err
|
return len(p), err
|
||||||
}
|
}
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
@ -2920,14 +2915,12 @@ func (rws *responseWriterState) writeHeader(code int) {
|
|||||||
h.Del("Transfer-Encoding")
|
h.Del("Transfer-Encoding")
|
||||||
}
|
}
|
||||||
|
|
||||||
if rws.conn.writeHeaders(rws.stream, &writeResHeaders{
|
rws.conn.writeHeaders(rws.stream, &writeResHeaders{
|
||||||
streamID: rws.stream.id,
|
streamID: rws.stream.id,
|
||||||
httpResCode: code,
|
httpResCode: code,
|
||||||
h: h,
|
h: h,
|
||||||
endStream: rws.handlerDone && !rws.hasTrailers(),
|
endStream: rws.handlerDone && !rws.hasTrailers(),
|
||||||
}) != nil {
|
})
|
||||||
rws.dirty = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -2992,19 +2985,10 @@ func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int,
|
|||||||
|
|
||||||
func (w *responseWriter) handlerDone() {
|
func (w *responseWriter) handlerDone() {
|
||||||
rws := w.rws
|
rws := w.rws
|
||||||
dirty := rws.dirty
|
|
||||||
rws.handlerDone = true
|
rws.handlerDone = true
|
||||||
w.Flush()
|
w.Flush()
|
||||||
w.rws = nil
|
w.rws = nil
|
||||||
if !dirty {
|
|
||||||
// Only recycle the pool if all prior Write calls to
|
|
||||||
// the serverConn goroutine completed successfully. If
|
|
||||||
// they returned earlier due to resets from the peer
|
|
||||||
// there might still be write goroutines outstanding
|
|
||||||
// from the serverConn referencing the rws memory. See
|
|
||||||
// issue 20704.
|
|
||||||
responseWriterStatePool.Put(rws)
|
responseWriterStatePool.Put(rws)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push errors.
|
// Push errors.
|
||||||
@ -3187,6 +3171,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) {
|
|||||||
panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err))
|
panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sc.curHandlers++
|
||||||
go sc.runHandler(rw, req, sc.handler.ServeHTTP)
|
go sc.runHandler(rw, req, sc.handler.ServeHTTP)
|
||||||
return promisedID, nil
|
return promisedID, nil
|
||||||
}
|
}
|
||||||
|
331
vendor/golang.org/x/net/http2/testsync.go
generated
vendored
Normal file
331
vendor/golang.org/x/net/http2/testsync.go
generated
vendored
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
package http2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// testSyncHooks coordinates goroutines in tests.
|
||||||
|
//
|
||||||
|
// For example, a call to ClientConn.RoundTrip involves several goroutines, including:
|
||||||
|
// - the goroutine running RoundTrip;
|
||||||
|
// - the clientStream.doRequest goroutine, which writes the request; and
|
||||||
|
// - the clientStream.readLoop goroutine, which reads the response.
|
||||||
|
//
|
||||||
|
// Using testSyncHooks, a test can start a RoundTrip and identify when all these goroutines
|
||||||
|
// are blocked waiting for some condition such as reading the Request.Body or waiting for
|
||||||
|
// flow control to become available.
|
||||||
|
//
|
||||||
|
// The testSyncHooks also manage timers and synthetic time in tests.
|
||||||
|
// This permits us to, for example, start a request and cause it to time out waiting for
|
||||||
|
// response headers without resorting to time.Sleep calls.
|
||||||
|
type testSyncHooks struct {
|
||||||
|
// active/inactive act as a mutex and condition variable.
|
||||||
|
//
|
||||||
|
// - neither chan contains a value: testSyncHooks is locked.
|
||||||
|
// - active contains a value: unlocked, and at least one goroutine is not blocked
|
||||||
|
// - inactive contains a value: unlocked, and all goroutines are blocked
|
||||||
|
active chan struct{}
|
||||||
|
inactive chan struct{}
|
||||||
|
|
||||||
|
// goroutine counts
|
||||||
|
total int // total goroutines
|
||||||
|
condwait map[*sync.Cond]int // blocked in sync.Cond.Wait
|
||||||
|
blocked []*testBlockedGoroutine // otherwise blocked
|
||||||
|
|
||||||
|
// fake time
|
||||||
|
now time.Time
|
||||||
|
timers []*fakeTimer
|
||||||
|
|
||||||
|
// Transport testing: Report various events.
|
||||||
|
newclientconn func(*ClientConn)
|
||||||
|
newstream func(*clientStream)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testBlockedGoroutine is a blocked goroutine.
|
||||||
|
type testBlockedGoroutine struct {
|
||||||
|
f func() bool // blocked until f returns true
|
||||||
|
ch chan struct{} // closed when unblocked
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestSyncHooks() *testSyncHooks {
|
||||||
|
h := &testSyncHooks{
|
||||||
|
active: make(chan struct{}, 1),
|
||||||
|
inactive: make(chan struct{}, 1),
|
||||||
|
condwait: map[*sync.Cond]int{},
|
||||||
|
}
|
||||||
|
h.inactive <- struct{}{}
|
||||||
|
h.now = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// lock acquires the testSyncHooks mutex.
|
||||||
|
func (h *testSyncHooks) lock() {
|
||||||
|
select {
|
||||||
|
case <-h.active:
|
||||||
|
case <-h.inactive:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// waitInactive waits for all goroutines to become inactive.
|
||||||
|
func (h *testSyncHooks) waitInactive() {
|
||||||
|
for {
|
||||||
|
<-h.inactive
|
||||||
|
if !h.unlock() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unlock releases the testSyncHooks mutex.
|
||||||
|
// It reports whether any goroutines are active.
|
||||||
|
func (h *testSyncHooks) unlock() (active bool) {
|
||||||
|
// Look for a blocked goroutine which can be unblocked.
|
||||||
|
blocked := h.blocked[:0]
|
||||||
|
unblocked := false
|
||||||
|
for _, b := range h.blocked {
|
||||||
|
if !unblocked && b.f() {
|
||||||
|
unblocked = true
|
||||||
|
close(b.ch)
|
||||||
|
} else {
|
||||||
|
blocked = append(blocked, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h.blocked = blocked
|
||||||
|
|
||||||
|
// Count goroutines blocked on condition variables.
|
||||||
|
condwait := 0
|
||||||
|
for _, count := range h.condwait {
|
||||||
|
condwait += count
|
||||||
|
}
|
||||||
|
|
||||||
|
if h.total > condwait+len(blocked) {
|
||||||
|
h.active <- struct{}{}
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
h.inactive <- struct{}{}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// goRun starts a new goroutine.
|
||||||
|
func (h *testSyncHooks) goRun(f func()) {
|
||||||
|
h.lock()
|
||||||
|
h.total++
|
||||||
|
h.unlock()
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
h.lock()
|
||||||
|
h.total--
|
||||||
|
h.unlock()
|
||||||
|
}()
|
||||||
|
f()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// blockUntil indicates that a goroutine is blocked waiting for some condition to become true.
|
||||||
|
// It waits until f returns true before proceeding.
|
||||||
|
//
|
||||||
|
// Example usage:
|
||||||
|
//
|
||||||
|
// h.blockUntil(func() bool {
|
||||||
|
// // Is the context done yet?
|
||||||
|
// select {
|
||||||
|
// case <-ctx.Done():
|
||||||
|
// default:
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// return true
|
||||||
|
// })
|
||||||
|
// // Wait for the context to become done.
|
||||||
|
// <-ctx.Done()
|
||||||
|
//
|
||||||
|
// The function f passed to blockUntil must be non-blocking and idempotent.
|
||||||
|
func (h *testSyncHooks) blockUntil(f func() bool) {
|
||||||
|
if f() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch := make(chan struct{})
|
||||||
|
h.lock()
|
||||||
|
h.blocked = append(h.blocked, &testBlockedGoroutine{
|
||||||
|
f: f,
|
||||||
|
ch: ch,
|
||||||
|
})
|
||||||
|
h.unlock()
|
||||||
|
<-ch
|
||||||
|
}
|
||||||
|
|
||||||
|
// broadcast is sync.Cond.Broadcast.
|
||||||
|
func (h *testSyncHooks) condBroadcast(cond *sync.Cond) {
|
||||||
|
h.lock()
|
||||||
|
delete(h.condwait, cond)
|
||||||
|
h.unlock()
|
||||||
|
cond.Broadcast()
|
||||||
|
}
|
||||||
|
|
||||||
|
// broadcast is sync.Cond.Wait.
|
||||||
|
func (h *testSyncHooks) condWait(cond *sync.Cond) {
|
||||||
|
h.lock()
|
||||||
|
h.condwait[cond]++
|
||||||
|
h.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTimer creates a new fake timer.
|
||||||
|
func (h *testSyncHooks) newTimer(d time.Duration) timer {
|
||||||
|
h.lock()
|
||||||
|
defer h.unlock()
|
||||||
|
t := &fakeTimer{
|
||||||
|
hooks: h,
|
||||||
|
when: h.now.Add(d),
|
||||||
|
c: make(chan time.Time),
|
||||||
|
}
|
||||||
|
h.timers = append(h.timers, t)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// afterFunc creates a new fake AfterFunc timer.
|
||||||
|
func (h *testSyncHooks) afterFunc(d time.Duration, f func()) timer {
|
||||||
|
h.lock()
|
||||||
|
defer h.unlock()
|
||||||
|
t := &fakeTimer{
|
||||||
|
hooks: h,
|
||||||
|
when: h.now.Add(d),
|
||||||
|
f: f,
|
||||||
|
}
|
||||||
|
h.timers = append(h.timers, t)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *testSyncHooks) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
t := h.afterFunc(d, cancel)
|
||||||
|
return ctx, func() {
|
||||||
|
t.Stop()
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *testSyncHooks) timeUntilEvent() time.Duration {
|
||||||
|
h.lock()
|
||||||
|
defer h.unlock()
|
||||||
|
var next time.Time
|
||||||
|
for _, t := range h.timers {
|
||||||
|
if next.IsZero() || t.when.Before(next) {
|
||||||
|
next = t.when
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d := next.Sub(h.now); d > 0 {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance advances time and causes synthetic timers to fire.
|
||||||
|
func (h *testSyncHooks) advance(d time.Duration) {
|
||||||
|
h.lock()
|
||||||
|
defer h.unlock()
|
||||||
|
h.now = h.now.Add(d)
|
||||||
|
timers := h.timers[:0]
|
||||||
|
for _, t := range h.timers {
|
||||||
|
t := t // remove after go.mod depends on go1.22
|
||||||
|
t.mu.Lock()
|
||||||
|
switch {
|
||||||
|
case t.when.After(h.now):
|
||||||
|
timers = append(timers, t)
|
||||||
|
case t.when.IsZero():
|
||||||
|
// stopped timer
|
||||||
|
default:
|
||||||
|
t.when = time.Time{}
|
||||||
|
if t.c != nil {
|
||||||
|
close(t.c)
|
||||||
|
}
|
||||||
|
if t.f != nil {
|
||||||
|
h.total++
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
h.lock()
|
||||||
|
h.total--
|
||||||
|
h.unlock()
|
||||||
|
}()
|
||||||
|
t.f()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.mu.Unlock()
|
||||||
|
}
|
||||||
|
h.timers = timers
|
||||||
|
}
|
||||||
|
|
||||||
|
// A timer wraps a time.Timer, or a synthetic equivalent in tests.
|
||||||
|
// Unlike time.Timer, timer is single-use: The timer channel is closed when the timer expires.
|
||||||
|
type timer interface {
|
||||||
|
C() <-chan time.Time
|
||||||
|
Stop() bool
|
||||||
|
Reset(d time.Duration) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeTimer implements timer using real time.
|
||||||
|
type timeTimer struct {
|
||||||
|
t *time.Timer
|
||||||
|
c chan time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTimeTimer creates a new timer using real time.
|
||||||
|
func newTimeTimer(d time.Duration) timer {
|
||||||
|
ch := make(chan time.Time)
|
||||||
|
t := time.AfterFunc(d, func() {
|
||||||
|
close(ch)
|
||||||
|
})
|
||||||
|
return &timeTimer{t, ch}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTimeAfterFunc creates an AfterFunc timer using real time.
|
||||||
|
func newTimeAfterFunc(d time.Duration, f func()) timer {
|
||||||
|
return &timeTimer{
|
||||||
|
t: time.AfterFunc(d, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t timeTimer) C() <-chan time.Time { return t.c }
|
||||||
|
func (t timeTimer) Stop() bool { return t.t.Stop() }
|
||||||
|
func (t timeTimer) Reset(d time.Duration) bool { return t.t.Reset(d) }
|
||||||
|
|
||||||
|
// fakeTimer implements timer using fake time.
|
||||||
|
type fakeTimer struct {
|
||||||
|
hooks *testSyncHooks
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
when time.Time // when the timer will fire
|
||||||
|
c chan time.Time // closed when the timer fires; mutually exclusive with f
|
||||||
|
f func() // called when the timer fires; mutually exclusive with c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *fakeTimer) C() <-chan time.Time { return t.c }
|
||||||
|
|
||||||
|
func (t *fakeTimer) Stop() bool {
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
stopped := t.when.IsZero()
|
||||||
|
t.when = time.Time{}
|
||||||
|
return stopped
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *fakeTimer) Reset(d time.Duration) bool {
|
||||||
|
if t.c != nil || t.f == nil {
|
||||||
|
panic("fakeTimer only supports Reset on AfterFunc timers")
|
||||||
|
}
|
||||||
|
t.mu.Lock()
|
||||||
|
defer t.mu.Unlock()
|
||||||
|
t.hooks.lock()
|
||||||
|
defer t.hooks.unlock()
|
||||||
|
active := !t.when.IsZero()
|
||||||
|
t.when = t.hooks.now.Add(d)
|
||||||
|
if !active {
|
||||||
|
t.hooks.timers = append(t.hooks.timers, t)
|
||||||
|
}
|
||||||
|
return active
|
||||||
|
}
|
338
vendor/golang.org/x/net/http2/transport.go
generated
vendored
338
vendor/golang.org/x/net/http2/transport.go
generated
vendored
@ -147,6 +147,12 @@ type Transport struct {
|
|||||||
// waiting for their turn.
|
// waiting for their turn.
|
||||||
StrictMaxConcurrentStreams bool
|
StrictMaxConcurrentStreams bool
|
||||||
|
|
||||||
|
// IdleConnTimeout is the maximum amount of time an idle
|
||||||
|
// (keep-alive) connection will remain idle before closing
|
||||||
|
// itself.
|
||||||
|
// Zero means no limit.
|
||||||
|
IdleConnTimeout time.Duration
|
||||||
|
|
||||||
// ReadIdleTimeout is the timeout after which a health check using ping
|
// ReadIdleTimeout is the timeout after which a health check using ping
|
||||||
// frame will be carried out if no frame is received on the connection.
|
// frame will be carried out if no frame is received on the connection.
|
||||||
// Note that a ping response will is considered a received frame, so if
|
// Note that a ping response will is considered a received frame, so if
|
||||||
@ -178,6 +184,8 @@ type Transport struct {
|
|||||||
|
|
||||||
connPoolOnce sync.Once
|
connPoolOnce sync.Once
|
||||||
connPoolOrDef ClientConnPool // non-nil version of ConnPool
|
connPoolOrDef ClientConnPool // non-nil version of ConnPool
|
||||||
|
|
||||||
|
syncHooks *testSyncHooks
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) maxHeaderListSize() uint32 {
|
func (t *Transport) maxHeaderListSize() uint32 {
|
||||||
@ -302,7 +310,7 @@ type ClientConn struct {
|
|||||||
readerErr error // set before readerDone is closed
|
readerErr error // set before readerDone is closed
|
||||||
|
|
||||||
idleTimeout time.Duration // or 0 for never
|
idleTimeout time.Duration // or 0 for never
|
||||||
idleTimer *time.Timer
|
idleTimer timer
|
||||||
|
|
||||||
mu sync.Mutex // guards following
|
mu sync.Mutex // guards following
|
||||||
cond *sync.Cond // hold mu; broadcast on flow/closed changes
|
cond *sync.Cond // hold mu; broadcast on flow/closed changes
|
||||||
@ -344,6 +352,60 @@ type ClientConn struct {
|
|||||||
werr error // first write error that has occurred
|
werr error // first write error that has occurred
|
||||||
hbuf bytes.Buffer // HPACK encoder writes into this
|
hbuf bytes.Buffer // HPACK encoder writes into this
|
||||||
henc *hpack.Encoder
|
henc *hpack.Encoder
|
||||||
|
|
||||||
|
syncHooks *testSyncHooks // can be nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hook points used for testing.
|
||||||
|
// Outside of tests, cc.syncHooks is nil and these all have minimal implementations.
|
||||||
|
// Inside tests, see the testSyncHooks function docs.
|
||||||
|
|
||||||
|
// goRun starts a new goroutine.
|
||||||
|
func (cc *ClientConn) goRun(f func()) {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.goRun(f)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go f()
|
||||||
|
}
|
||||||
|
|
||||||
|
// condBroadcast is cc.cond.Broadcast.
|
||||||
|
func (cc *ClientConn) condBroadcast() {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.condBroadcast(cc.cond)
|
||||||
|
}
|
||||||
|
cc.cond.Broadcast()
|
||||||
|
}
|
||||||
|
|
||||||
|
// condWait is cc.cond.Wait.
|
||||||
|
func (cc *ClientConn) condWait() {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.condWait(cc.cond)
|
||||||
|
}
|
||||||
|
cc.cond.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// newTimer creates a new time.Timer, or a synthetic timer in tests.
|
||||||
|
func (cc *ClientConn) newTimer(d time.Duration) timer {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
return cc.syncHooks.newTimer(d)
|
||||||
|
}
|
||||||
|
return newTimeTimer(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
|
||||||
|
func (cc *ClientConn) afterFunc(d time.Duration, f func()) timer {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
return cc.syncHooks.afterFunc(d, f)
|
||||||
|
}
|
||||||
|
return newTimeAfterFunc(d, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ClientConn) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
return cc.syncHooks.contextWithTimeout(ctx, d)
|
||||||
|
}
|
||||||
|
return context.WithTimeout(ctx, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// clientStream is the state for a single HTTP/2 stream. One of these
|
// clientStream is the state for a single HTTP/2 stream. One of these
|
||||||
@ -425,7 +487,7 @@ func (cs *clientStream) abortStreamLocked(err error) {
|
|||||||
// TODO(dneil): Clean up tests where cs.cc.cond is nil.
|
// TODO(dneil): Clean up tests where cs.cc.cond is nil.
|
||||||
if cs.cc.cond != nil {
|
if cs.cc.cond != nil {
|
||||||
// Wake up writeRequestBody if it is waiting on flow control.
|
// Wake up writeRequestBody if it is waiting on flow control.
|
||||||
cs.cc.cond.Broadcast()
|
cs.cc.condBroadcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +497,7 @@ func (cs *clientStream) abortRequestBodyWrite() {
|
|||||||
defer cc.mu.Unlock()
|
defer cc.mu.Unlock()
|
||||||
if cs.reqBody != nil && cs.reqBodyClosed == nil {
|
if cs.reqBody != nil && cs.reqBodyClosed == nil {
|
||||||
cs.closeReqBodyLocked()
|
cs.closeReqBodyLocked()
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,10 +507,10 @@ func (cs *clientStream) closeReqBodyLocked() {
|
|||||||
}
|
}
|
||||||
cs.reqBodyClosed = make(chan struct{})
|
cs.reqBodyClosed = make(chan struct{})
|
||||||
reqBodyClosed := cs.reqBodyClosed
|
reqBodyClosed := cs.reqBodyClosed
|
||||||
go func() {
|
cs.cc.goRun(func() {
|
||||||
cs.reqBody.Close()
|
cs.reqBody.Close()
|
||||||
close(reqBodyClosed)
|
close(reqBodyClosed)
|
||||||
}()
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type stickyErrWriter struct {
|
type stickyErrWriter struct {
|
||||||
@ -537,15 +599,6 @@ func authorityAddr(scheme string, authority string) (addr string) {
|
|||||||
return net.JoinHostPort(host, port)
|
return net.JoinHostPort(host, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
var retryBackoffHook func(time.Duration) *time.Timer
|
|
||||||
|
|
||||||
func backoffNewTimer(d time.Duration) *time.Timer {
|
|
||||||
if retryBackoffHook != nil {
|
|
||||||
return retryBackoffHook(d)
|
|
||||||
}
|
|
||||||
return time.NewTimer(d)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoundTripOpt is like RoundTrip, but takes options.
|
// RoundTripOpt is like RoundTrip, but takes options.
|
||||||
func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
|
func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
|
||||||
if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
|
if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
|
||||||
@ -573,13 +626,27 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
|
|||||||
backoff := float64(uint(1) << (uint(retry) - 1))
|
backoff := float64(uint(1) << (uint(retry) - 1))
|
||||||
backoff += backoff * (0.1 * mathrand.Float64())
|
backoff += backoff * (0.1 * mathrand.Float64())
|
||||||
d := time.Second * time.Duration(backoff)
|
d := time.Second * time.Duration(backoff)
|
||||||
timer := backoffNewTimer(d)
|
var tm timer
|
||||||
|
if t.syncHooks != nil {
|
||||||
|
tm = t.syncHooks.newTimer(d)
|
||||||
|
t.syncHooks.blockUntil(func() bool {
|
||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-tm.C():
|
||||||
|
case <-req.Context().Done():
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
tm = newTimeTimer(d)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-tm.C():
|
||||||
t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
|
t.vlogf("RoundTrip retrying after failure: %v", roundTripErr)
|
||||||
continue
|
continue
|
||||||
case <-req.Context().Done():
|
case <-req.Context().Done():
|
||||||
timer.Stop()
|
tm.Stop()
|
||||||
err = req.Context().Err()
|
err = req.Context().Err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -658,6 +725,9 @@ func canRetryError(err error) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error) {
|
func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error) {
|
||||||
|
if t.syncHooks != nil {
|
||||||
|
return t.newClientConn(nil, singleUse, t.syncHooks)
|
||||||
|
}
|
||||||
host, _, err := net.SplitHostPort(addr)
|
host, _, err := net.SplitHostPort(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -666,7 +736,7 @@ func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse b
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return t.newClientConn(tconn, singleUse)
|
return t.newClientConn(tconn, singleUse, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) newTLSConfig(host string) *tls.Config {
|
func (t *Transport) newTLSConfig(host string) *tls.Config {
|
||||||
@ -732,10 +802,10 @@ func (t *Transport) maxEncoderHeaderTableSize() uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
|
func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
|
||||||
return t.newClientConn(c, t.disableKeepAlives())
|
return t.newClientConn(c, t.disableKeepAlives(), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
|
func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHooks) (*ClientConn, error) {
|
||||||
cc := &ClientConn{
|
cc := &ClientConn{
|
||||||
t: t,
|
t: t,
|
||||||
tconn: c,
|
tconn: c,
|
||||||
@ -750,10 +820,15 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
|
|||||||
wantSettingsAck: true,
|
wantSettingsAck: true,
|
||||||
pings: make(map[[8]byte]chan struct{}),
|
pings: make(map[[8]byte]chan struct{}),
|
||||||
reqHeaderMu: make(chan struct{}, 1),
|
reqHeaderMu: make(chan struct{}, 1),
|
||||||
|
syncHooks: hooks,
|
||||||
|
}
|
||||||
|
if hooks != nil {
|
||||||
|
hooks.newclientconn(cc)
|
||||||
|
c = cc.tconn
|
||||||
}
|
}
|
||||||
if d := t.idleConnTimeout(); d != 0 {
|
if d := t.idleConnTimeout(); d != 0 {
|
||||||
cc.idleTimeout = d
|
cc.idleTimeout = d
|
||||||
cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout)
|
cc.idleTimer = cc.afterFunc(d, cc.onIdleTimeout)
|
||||||
}
|
}
|
||||||
if VerboseLogs {
|
if VerboseLogs {
|
||||||
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
|
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
|
||||||
@ -818,7 +893,7 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
|
|||||||
return nil, cc.werr
|
return nil, cc.werr
|
||||||
}
|
}
|
||||||
|
|
||||||
go cc.readLoop()
|
cc.goRun(cc.readLoop)
|
||||||
return cc, nil
|
return cc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -826,7 +901,7 @@ func (cc *ClientConn) healthCheck() {
|
|||||||
pingTimeout := cc.t.pingTimeout()
|
pingTimeout := cc.t.pingTimeout()
|
||||||
// We don't need to periodically ping in the health check, because the readLoop of ClientConn will
|
// We don't need to periodically ping in the health check, because the readLoop of ClientConn will
|
||||||
// trigger the healthCheck again if there is no frame received.
|
// trigger the healthCheck again if there is no frame received.
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), pingTimeout)
|
ctx, cancel := cc.contextWithTimeout(context.Background(), pingTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
cc.vlogf("http2: Transport sending health check")
|
cc.vlogf("http2: Transport sending health check")
|
||||||
err := cc.Ping(ctx)
|
err := cc.Ping(ctx)
|
||||||
@ -1018,7 +1093,7 @@ func (cc *ClientConn) forceCloseConn() {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if nc := tlsUnderlyingConn(tc); nc != nil {
|
if nc := tc.NetConn(); nc != nil {
|
||||||
nc.Close()
|
nc.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1056,7 +1131,7 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
|
|||||||
// Wait for all in-flight streams to complete or connection to close
|
// Wait for all in-flight streams to complete or connection to close
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
cancelled := false // guarded by cc.mu
|
cancelled := false // guarded by cc.mu
|
||||||
go func() {
|
cc.goRun(func() {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
defer cc.mu.Unlock()
|
defer cc.mu.Unlock()
|
||||||
for {
|
for {
|
||||||
@ -1068,9 +1143,9 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
|
|||||||
if cancelled {
|
if cancelled {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
cc.cond.Wait()
|
cc.condWait()
|
||||||
}
|
}
|
||||||
}()
|
})
|
||||||
shutdownEnterWaitStateHook()
|
shutdownEnterWaitStateHook()
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
@ -1080,7 +1155,7 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
|
|||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
// Free the goroutine above
|
// Free the goroutine above
|
||||||
cancelled = true
|
cancelled = true
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
@ -1118,7 +1193,7 @@ func (cc *ClientConn) closeForError(err error) {
|
|||||||
for _, cs := range cc.streams {
|
for _, cs := range cc.streams {
|
||||||
cs.abortStreamLocked(err)
|
cs.abortStreamLocked(err)
|
||||||
}
|
}
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
cc.closeConn()
|
cc.closeConn()
|
||||||
}
|
}
|
||||||
@ -1215,6 +1290,10 @@ func (cc *ClientConn) decrStreamReservationsLocked() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
return cc.roundTrip(req, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) (*http.Response, error) {
|
||||||
ctx := req.Context()
|
ctx := req.Context()
|
||||||
cs := &clientStream{
|
cs := &clientStream{
|
||||||
cc: cc,
|
cc: cc,
|
||||||
@ -1229,9 +1308,23 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||||||
respHeaderRecv: make(chan struct{}),
|
respHeaderRecv: make(chan struct{}),
|
||||||
donec: make(chan struct{}),
|
donec: make(chan struct{}),
|
||||||
}
|
}
|
||||||
go cs.doRequest(req)
|
cc.goRun(func() {
|
||||||
|
cs.doRequest(req)
|
||||||
|
})
|
||||||
|
|
||||||
waitDone := func() error {
|
waitDone := func() error {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.blockUntil(func() bool {
|
||||||
|
select {
|
||||||
|
case <-cs.donec:
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-cs.reqCancel:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-cs.donec:
|
case <-cs.donec:
|
||||||
return nil
|
return nil
|
||||||
@ -1292,7 +1385,24 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamf != nil {
|
||||||
|
streamf(cs)
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.blockUntil(func() bool {
|
||||||
|
select {
|
||||||
|
case <-cs.respHeaderRecv:
|
||||||
|
case <-cs.abort:
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-cs.reqCancel:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-cs.respHeaderRecv:
|
case <-cs.respHeaderRecv:
|
||||||
return handleResponseHeaders()
|
return handleResponseHeaders()
|
||||||
@ -1348,6 +1458,21 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
|
|||||||
if cc.reqHeaderMu == nil {
|
if cc.reqHeaderMu == nil {
|
||||||
panic("RoundTrip on uninitialized ClientConn") // for tests
|
panic("RoundTrip on uninitialized ClientConn") // for tests
|
||||||
}
|
}
|
||||||
|
var newStreamHook func(*clientStream)
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
newStreamHook = cc.syncHooks.newstream
|
||||||
|
cc.syncHooks.blockUntil(func() bool {
|
||||||
|
select {
|
||||||
|
case cc.reqHeaderMu <- struct{}{}:
|
||||||
|
<-cc.reqHeaderMu
|
||||||
|
case <-cs.reqCancel:
|
||||||
|
case <-ctx.Done():
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case cc.reqHeaderMu <- struct{}{}:
|
case cc.reqHeaderMu <- struct{}{}:
|
||||||
case <-cs.reqCancel:
|
case <-cs.reqCancel:
|
||||||
@ -1372,6 +1497,10 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
|
|||||||
}
|
}
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
|
||||||
|
if newStreamHook != nil {
|
||||||
|
newStreamHook(cs)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
|
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
|
||||||
if !cc.t.disableCompression() &&
|
if !cc.t.disableCompression() &&
|
||||||
req.Header.Get("Accept-Encoding") == "" &&
|
req.Header.Get("Accept-Encoding") == "" &&
|
||||||
@ -1452,15 +1581,30 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) {
|
|||||||
var respHeaderTimer <-chan time.Time
|
var respHeaderTimer <-chan time.Time
|
||||||
var respHeaderRecv chan struct{}
|
var respHeaderRecv chan struct{}
|
||||||
if d := cc.responseHeaderTimeout(); d != 0 {
|
if d := cc.responseHeaderTimeout(); d != 0 {
|
||||||
timer := time.NewTimer(d)
|
timer := cc.newTimer(d)
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
respHeaderTimer = timer.C
|
respHeaderTimer = timer.C()
|
||||||
respHeaderRecv = cs.respHeaderRecv
|
respHeaderRecv = cs.respHeaderRecv
|
||||||
}
|
}
|
||||||
// Wait until the peer half-closes its end of the stream,
|
// Wait until the peer half-closes its end of the stream,
|
||||||
// or until the request is aborted (via context, error, or otherwise),
|
// or until the request is aborted (via context, error, or otherwise),
|
||||||
// whichever comes first.
|
// whichever comes first.
|
||||||
for {
|
for {
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.blockUntil(func() bool {
|
||||||
|
select {
|
||||||
|
case <-cs.peerClosed:
|
||||||
|
case <-respHeaderTimer:
|
||||||
|
case <-respHeaderRecv:
|
||||||
|
case <-cs.abort:
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-cs.reqCancel:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-cs.peerClosed:
|
case <-cs.peerClosed:
|
||||||
return nil
|
return nil
|
||||||
@ -1609,7 +1753,7 @@ func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cc.pendingRequests++
|
cc.pendingRequests++
|
||||||
cc.cond.Wait()
|
cc.condWait()
|
||||||
cc.pendingRequests--
|
cc.pendingRequests--
|
||||||
select {
|
select {
|
||||||
case <-cs.abort:
|
case <-cs.abort:
|
||||||
@ -1871,10 +2015,26 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error)
|
|||||||
cs.flow.take(take)
|
cs.flow.take(take)
|
||||||
return take, nil
|
return take, nil
|
||||||
}
|
}
|
||||||
cc.cond.Wait()
|
cc.condWait()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateHeaders(hdrs http.Header) string {
|
||||||
|
for k, vv := range hdrs {
|
||||||
|
if !httpguts.ValidHeaderFieldName(k) {
|
||||||
|
return fmt.Sprintf("name %q", k)
|
||||||
|
}
|
||||||
|
for _, v := range vv {
|
||||||
|
if !httpguts.ValidHeaderFieldValue(v) {
|
||||||
|
// Don't include the value in the error,
|
||||||
|
// because it may be sensitive.
|
||||||
|
return fmt.Sprintf("value for header %q", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
var errNilRequestURL = errors.New("http2: Request.URI is nil")
|
var errNilRequestURL = errors.New("http2: Request.URI is nil")
|
||||||
|
|
||||||
// requires cc.wmu be held.
|
// requires cc.wmu be held.
|
||||||
@ -1912,19 +2072,14 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for any invalid headers and return an error before we
|
// Check for any invalid headers+trailers and return an error before we
|
||||||
// potentially pollute our hpack state. (We want to be able to
|
// potentially pollute our hpack state. (We want to be able to
|
||||||
// continue to reuse the hpack encoder for future requests)
|
// continue to reuse the hpack encoder for future requests)
|
||||||
for k, vv := range req.Header {
|
if err := validateHeaders(req.Header); err != "" {
|
||||||
if !httpguts.ValidHeaderFieldName(k) {
|
return nil, fmt.Errorf("invalid HTTP header %s", err)
|
||||||
return nil, fmt.Errorf("invalid HTTP header name %q", k)
|
|
||||||
}
|
|
||||||
for _, v := range vv {
|
|
||||||
if !httpguts.ValidHeaderFieldValue(v) {
|
|
||||||
// Don't include the value in the error, because it may be sensitive.
|
|
||||||
return nil, fmt.Errorf("invalid HTTP header value for header %q", k)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if err := validateHeaders(req.Trailer); err != "" {
|
||||||
|
return nil, fmt.Errorf("invalid HTTP trailer %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
enumerateHeaders := func(f func(name, value string)) {
|
enumerateHeaders := func(f func(name, value string)) {
|
||||||
@ -2143,7 +2298,7 @@ func (cc *ClientConn) forgetStreamID(id uint32) {
|
|||||||
}
|
}
|
||||||
// Wake up writeRequestBody via clientStream.awaitFlowControl and
|
// Wake up writeRequestBody via clientStream.awaitFlowControl and
|
||||||
// wake up RoundTrip if there is a pending request.
|
// wake up RoundTrip if there is a pending request.
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
|
|
||||||
closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() || cc.goAway != nil
|
closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() || cc.goAway != nil
|
||||||
if closeOnIdle && cc.streamsReserved == 0 && len(cc.streams) == 0 {
|
if closeOnIdle && cc.streamsReserved == 0 && len(cc.streams) == 0 {
|
||||||
@ -2231,7 +2386,7 @@ func (rl *clientConnReadLoop) cleanup() {
|
|||||||
cs.abortStreamLocked(err)
|
cs.abortStreamLocked(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2266,10 +2421,9 @@ func (rl *clientConnReadLoop) run() error {
|
|||||||
cc := rl.cc
|
cc := rl.cc
|
||||||
gotSettings := false
|
gotSettings := false
|
||||||
readIdleTimeout := cc.t.ReadIdleTimeout
|
readIdleTimeout := cc.t.ReadIdleTimeout
|
||||||
var t *time.Timer
|
var t timer
|
||||||
if readIdleTimeout != 0 {
|
if readIdleTimeout != 0 {
|
||||||
t = time.AfterFunc(readIdleTimeout, cc.healthCheck)
|
t = cc.afterFunc(readIdleTimeout, cc.healthCheck)
|
||||||
defer t.Stop()
|
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
f, err := cc.fr.ReadFrame()
|
f, err := cc.fr.ReadFrame()
|
||||||
@ -2684,7 +2838,7 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
|||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !cs.firstByte {
|
if !cs.pastHeaders {
|
||||||
cc.logf("protocol error: received DATA before a HEADERS frame")
|
cc.logf("protocol error: received DATA before a HEADERS frame")
|
||||||
rl.endStreamError(cs, StreamError{
|
rl.endStreamError(cs, StreamError{
|
||||||
StreamID: f.StreamID,
|
StreamID: f.StreamID,
|
||||||
@ -2867,7 +3021,7 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
|
|||||||
for _, cs := range cc.streams {
|
for _, cs := range cc.streams {
|
||||||
cs.flow.add(delta)
|
cs.flow.add(delta)
|
||||||
}
|
}
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
|
|
||||||
cc.initialWindowSize = s.Val
|
cc.initialWindowSize = s.Val
|
||||||
case SettingHeaderTableSize:
|
case SettingHeaderTableSize:
|
||||||
@ -2911,9 +3065,18 @@ func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error {
|
|||||||
fl = &cs.flow
|
fl = &cs.flow
|
||||||
}
|
}
|
||||||
if !fl.add(int32(f.Increment)) {
|
if !fl.add(int32(f.Increment)) {
|
||||||
|
// For stream, the sender sends RST_STREAM with an error code of FLOW_CONTROL_ERROR
|
||||||
|
if cs != nil {
|
||||||
|
rl.endStreamError(cs, StreamError{
|
||||||
|
StreamID: f.StreamID,
|
||||||
|
Code: ErrCodeFlowControl,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return ConnectionError(ErrCodeFlowControl)
|
return ConnectionError(ErrCodeFlowControl)
|
||||||
}
|
}
|
||||||
cc.cond.Broadcast()
|
cc.condBroadcast()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2955,24 +3118,38 @@ func (cc *ClientConn) Ping(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
}
|
}
|
||||||
errc := make(chan error, 1)
|
var pingError error
|
||||||
go func() {
|
errc := make(chan struct{})
|
||||||
|
cc.goRun(func() {
|
||||||
cc.wmu.Lock()
|
cc.wmu.Lock()
|
||||||
defer cc.wmu.Unlock()
|
defer cc.wmu.Unlock()
|
||||||
if err := cc.fr.WritePing(false, p); err != nil {
|
if pingError = cc.fr.WritePing(false, p); pingError != nil {
|
||||||
errc <- err
|
close(errc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := cc.bw.Flush(); err != nil {
|
if pingError = cc.bw.Flush(); pingError != nil {
|
||||||
errc <- err
|
close(errc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}()
|
})
|
||||||
|
if cc.syncHooks != nil {
|
||||||
|
cc.syncHooks.blockUntil(func() bool {
|
||||||
|
select {
|
||||||
|
case <-c:
|
||||||
|
case <-errc:
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-cc.readerDone:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-c:
|
case <-c:
|
||||||
return nil
|
return nil
|
||||||
case err := <-errc:
|
case <-errc:
|
||||||
return err
|
return pingError
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case <-cc.readerDone:
|
case <-cc.readerDone:
|
||||||
@ -3141,9 +3318,17 @@ func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) idleConnTimeout() time.Duration {
|
func (t *Transport) idleConnTimeout() time.Duration {
|
||||||
|
// to keep things backwards compatible, we use non-zero values of
|
||||||
|
// IdleConnTimeout, followed by using the IdleConnTimeout on the underlying
|
||||||
|
// http1 transport, followed by 0
|
||||||
|
if t.IdleConnTimeout != 0 {
|
||||||
|
return t.IdleConnTimeout
|
||||||
|
}
|
||||||
|
|
||||||
if t.t1 != nil {
|
if t.t1 != nil {
|
||||||
return t.t1.IdleConnTimeout
|
return t.t1.IdleConnTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3201,3 +3386,34 @@ func traceFirstResponseByte(trace *httptrace.ClientTrace) {
|
|||||||
trace.GotFirstResponseByte()
|
trace.GotFirstResponseByte()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool {
|
||||||
|
return trace != nil && trace.WroteHeaderField != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {
|
||||||
|
if trace != nil && trace.WroteHeaderField != nil {
|
||||||
|
trace.WroteHeaderField(k, []string{v})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
|
||||||
|
if trace != nil {
|
||||||
|
return trace.Got1xxResponse
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// dialTLSWithContext uses tls.Dialer, added in Go 1.15, to open a TLS
|
||||||
|
// connection.
|
||||||
|
func (t *Transport) dialTLSWithContext(ctx context.Context, network, addr string, cfg *tls.Config) (*tls.Conn, error) {
|
||||||
|
dialer := &tls.Dialer{
|
||||||
|
Config: cfg,
|
||||||
|
}
|
||||||
|
cn, err := dialer.DialContext(ctx, network, addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tlsCn := cn.(*tls.Conn) // DialContext comment promises this will always succeed
|
||||||
|
return tlsCn, nil
|
||||||
|
}
|
||||||
|
1
vendor/golang.org/x/net/idna/go118.go
generated
vendored
1
vendor/golang.org/x/net/idna/go118.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.18
|
//go:build go1.18
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/idna10.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/idna10.0.0.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.10
|
//go:build go1.10
|
||||||
// +build go1.10
|
|
||||||
|
|
||||||
// Package idna implements IDNA2008 using the compatibility processing
|
// Package idna implements IDNA2008 using the compatibility processing
|
||||||
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
||||||
|
1
vendor/golang.org/x/net/idna/idna9.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/idna9.0.0.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !go1.10
|
//go:build !go1.10
|
||||||
// +build !go1.10
|
|
||||||
|
|
||||||
// Package idna implements IDNA2008 using the compatibility processing
|
// Package idna implements IDNA2008 using the compatibility processing
|
||||||
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
||||||
|
1
vendor/golang.org/x/net/idna/pre_go118.go
generated
vendored
1
vendor/golang.org/x/net/idna/pre_go118.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !go1.18
|
//go:build !go1.18
|
||||||
// +build !go1.18
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables10.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables10.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build go1.10 && !go1.13
|
//go:build go1.10 && !go1.13
|
||||||
// +build go1.10,!go1.13
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables11.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables11.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build go1.13 && !go1.14
|
//go:build go1.13 && !go1.14
|
||||||
// +build go1.13,!go1.14
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables12.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables12.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build go1.14 && !go1.16
|
//go:build go1.14 && !go1.16
|
||||||
// +build go1.14,!go1.16
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables13.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables13.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build go1.16 && !go1.21
|
//go:build go1.16 && !go1.21
|
||||||
// +build go1.16,!go1.21
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables15.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables15.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build go1.21
|
//go:build go1.21
|
||||||
// +build go1.21
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/tables9.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/tables9.0.0.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build !go1.10
|
//go:build !go1.10
|
||||||
// +build !go1.10
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/trie12.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/trie12.0.0.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !go1.16
|
//go:build !go1.16
|
||||||
// +build !go1.16
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/net/idna/trie13.0.0.go
generated
vendored
1
vendor/golang.org/x/net/idna/trie13.0.0.go
generated
vendored
@ -5,7 +5,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build go1.16
|
//go:build go1.16
|
||||||
// +build go1.16
|
|
||||||
|
|
||||||
package idna
|
package idna
|
||||||
|
|
||||||
|
4
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
4
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
@ -2,9 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
|
||||||
// +build go1.9
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
@ -3,8 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (freebsd || netbsd || openbsd) && gc
|
//go:build (freebsd || netbsd || openbsd) && gc
|
||||||
// +build freebsd netbsd openbsd
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
@ -3,8 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc
|
//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc
|
||||||
// +build darwin dragonfly freebsd netbsd openbsd
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
@ -3,8 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (freebsd || netbsd || openbsd) && gc
|
//go:build (freebsd || netbsd || openbsd) && gc
|
||||||
// +build freebsd netbsd openbsd
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/sys/unix/asm_bsd_arm64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_arm64.s
generated
vendored
@ -3,8 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
// +build darwin freebsd netbsd openbsd
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s
generated
vendored
@ -3,8 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
// +build darwin freebsd netbsd openbsd
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_bsd_riscv64.s
generated
vendored
@ -3,8 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
// +build darwin freebsd netbsd openbsd
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
@ -3,9 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && arm64 && gc
|
//go:build linux && arm64 && gc
|
||||||
// +build linux
|
|
||||||
// +build arm64
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_loong64.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_loong64.s
generated
vendored
@ -3,9 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && loong64 && gc
|
//go:build linux && loong64 && gc
|
||||||
// +build linux
|
|
||||||
// +build loong64
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
@ -3,9 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && (mips64 || mips64le) && gc
|
//go:build linux && (mips64 || mips64le) && gc
|
||||||
// +build linux
|
|
||||||
// +build mips64 mips64le
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
generated
vendored
@ -3,9 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && (mips || mipsle) && gc
|
//go:build linux && (mips || mipsle) && gc
|
||||||
// +build linux
|
|
||||||
// +build mips mipsle
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
generated
vendored
@ -3,9 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && (ppc64 || ppc64le) && gc
|
//go:build linux && (ppc64 || ppc64le) && gc
|
||||||
// +build linux
|
|
||||||
// +build ppc64 ppc64le
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
generated
vendored
2
vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
generated
vendored
@ -3,8 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build riscv64 && gc
|
//go:build riscv64 && gc
|
||||||
// +build riscv64
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
generated
vendored
@ -3,9 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux && s390x && gc
|
//go:build linux && s390x && gc
|
||||||
// +build linux
|
|
||||||
// +build s390x
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
generated
vendored
1
vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gc
|
//go:build gc
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/sys/unix/asm_zos_s390x.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_zos_s390x.s
generated
vendored
@ -3,9 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build zos && s390x && gc
|
//go:build zos && s390x && gc
|
||||||
// +build zos
|
|
||||||
// +build s390x
|
|
||||||
// +build gc
|
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/cap_freebsd.go
generated
vendored
1
vendor/golang.org/x/sys/unix/cap_freebsd.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build freebsd
|
//go:build freebsd
|
||||||
// +build freebsd
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/constants.go
generated
vendored
1
vendor/golang.org/x/sys/unix/constants.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/dev_aix_ppc.go
generated
vendored
1
vendor/golang.org/x/sys/unix/dev_aix_ppc.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix && ppc
|
//go:build aix && ppc
|
||||||
// +build aix,ppc
|
|
||||||
|
|
||||||
// Functions to access/create device major and minor numbers matching the
|
// Functions to access/create device major and minor numbers matching the
|
||||||
// encoding used by AIX.
|
// encoding used by AIX.
|
||||||
|
1
vendor/golang.org/x/sys/unix/dev_aix_ppc64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/dev_aix_ppc64.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix && ppc64
|
//go:build aix && ppc64
|
||||||
// +build aix,ppc64
|
|
||||||
|
|
||||||
// Functions to access/create device major and minor numbers matching the
|
// Functions to access/create device major and minor numbers matching the
|
||||||
// encoding used AIX.
|
// encoding used AIX.
|
||||||
|
1
vendor/golang.org/x/sys/unix/dev_zos.go
generated
vendored
1
vendor/golang.org/x/sys/unix/dev_zos.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build zos && s390x
|
//go:build zos && s390x
|
||||||
// +build zos,s390x
|
|
||||||
|
|
||||||
// Functions to access/create device major and minor numbers matching the
|
// Functions to access/create device major and minor numbers matching the
|
||||||
// encoding used by z/OS.
|
// encoding used by z/OS.
|
||||||
|
1
vendor/golang.org/x/sys/unix/dirent.go
generated
vendored
1
vendor/golang.org/x/sys/unix/dirent.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/endian_big.go
generated
vendored
1
vendor/golang.org/x/sys/unix/endian_big.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
//
|
//
|
||||||
//go:build armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64
|
//go:build armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64
|
||||||
// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/endian_little.go
generated
vendored
1
vendor/golang.org/x/sys/unix/endian_little.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
//
|
//
|
||||||
//go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh
|
//go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || loong64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh
|
||||||
// +build 386 amd64 amd64p32 alpha arm arm64 loong64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/env_unix.go
generated
vendored
1
vendor/golang.org/x/sys/unix/env_unix.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
|
||||||
|
|
||||||
// Unix environment variables.
|
// Unix environment variables.
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/epoll_zos.go
generated
vendored
1
vendor/golang.org/x/sys/unix/epoll_zos.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build zos && s390x
|
//go:build zos && s390x
|
||||||
// +build zos,s390x
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/sys/unix/fcntl.go
generated
vendored
3
vendor/golang.org/x/sys/unix/fcntl.go
generated
vendored
@ -2,8 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build dragonfly || freebsd || linux || netbsd || openbsd
|
//go:build dragonfly || freebsd || linux || netbsd
|
||||||
// +build dragonfly freebsd linux netbsd openbsd
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go
generated
vendored
1
vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) || (linux && ppc)
|
//go:build (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) || (linux && ppc)
|
||||||
// +build linux,386 linux,arm linux,mips linux,mipsle linux,ppc
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/fdset.go
generated
vendored
1
vendor/golang.org/x/sys/unix/fdset.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/fstatfs_zos.go
generated
vendored
1
vendor/golang.org/x/sys/unix/fstatfs_zos.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build zos && s390x
|
//go:build zos && s390x
|
||||||
// +build zos,s390x
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
1
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gccgo && !aix && !hurd
|
//go:build gccgo && !aix && !hurd
|
||||||
// +build gccgo,!aix,!hurd
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
1
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gccgo && !aix && !hurd
|
//go:build gccgo && !aix && !hurd
|
||||||
// +build gccgo,!aix,!hurd
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
1
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build gccgo && linux && amd64
|
//go:build gccgo && linux && amd64
|
||||||
// +build gccgo,linux,amd64
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/ifreq_linux.go
generated
vendored
1
vendor/golang.org/x/sys/unix/ifreq_linux.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build linux
|
//go:build linux
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
5
vendor/golang.org/x/sys/unix/ioctl_linux.go
generated
vendored
5
vendor/golang.org/x/sys/unix/ioctl_linux.go
generated
vendored
@ -231,3 +231,8 @@ func IoctlLoopGetStatus64(fd int) (*LoopInfo64, error) {
|
|||||||
func IoctlLoopSetStatus64(fd int, value *LoopInfo64) error {
|
func IoctlLoopSetStatus64(fd int, value *LoopInfo64) error {
|
||||||
return ioctlPtr(fd, LOOP_SET_STATUS64, unsafe.Pointer(value))
|
return ioctlPtr(fd, LOOP_SET_STATUS64, unsafe.Pointer(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IoctlLoopConfigure configures all loop device parameters in a single step
|
||||||
|
func IoctlLoopConfigure(fd int, value *LoopConfig) error {
|
||||||
|
return ioctlPtr(fd, LOOP_CONFIGURE, unsafe.Pointer(value))
|
||||||
|
}
|
||||||
|
1
vendor/golang.org/x/sys/unix/ioctl_signed.go
generated
vendored
1
vendor/golang.org/x/sys/unix/ioctl_signed.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || solaris
|
//go:build aix || solaris
|
||||||
// +build aix solaris
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/ioctl_unsigned.go
generated
vendored
1
vendor/golang.org/x/sys/unix/ioctl_unsigned.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd
|
//go:build darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd
|
||||||
// +build darwin dragonfly freebsd hurd linux netbsd openbsd
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
1
vendor/golang.org/x/sys/unix/ioctl_zos.go
generated
vendored
1
vendor/golang.org/x/sys/unix/ioctl_zos.go
generated
vendored
@ -3,7 +3,6 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build zos && s390x
|
//go:build zos && s390x
|
||||||
// +build zos,s390x
|
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
43
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
43
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
@ -248,6 +248,7 @@ struct ltchars {
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <linux/netfilter/nfnetlink.h>
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
#include <linux/netfilter/nf_tables.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/net_namespace.h>
|
#include <linux/net_namespace.h>
|
||||||
#include <linux/nfc.h>
|
#include <linux/nfc.h>
|
||||||
@ -283,10 +284,6 @@ struct ltchars {
|
|||||||
#include <asm/termbits.h>
|
#include <asm/termbits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MSG_FASTOPEN
|
|
||||||
#define MSG_FASTOPEN 0x20000000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PTRACE_GETREGS
|
#ifndef PTRACE_GETREGS
|
||||||
#define PTRACE_GETREGS 0xc
|
#define PTRACE_GETREGS 0xc
|
||||||
#endif
|
#endif
|
||||||
@ -295,14 +292,6 @@ struct ltchars {
|
|||||||
#define PTRACE_SETREGS 0xd
|
#define PTRACE_SETREGS 0xd
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SOL_NETLINK
|
|
||||||
#define SOL_NETLINK 270
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SOL_SMC
|
|
||||||
#define SOL_SMC 286
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SOL_BLUETOOTH
|
#ifdef SOL_BLUETOOTH
|
||||||
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
|
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
|
||||||
// but it is already in bluetooth_linux.go
|
// but it is already in bluetooth_linux.go
|
||||||
@ -319,10 +308,23 @@ struct ltchars {
|
|||||||
#undef TIPC_WAIT_FOREVER
|
#undef TIPC_WAIT_FOREVER
|
||||||
#define TIPC_WAIT_FOREVER 0xffffffff
|
#define TIPC_WAIT_FOREVER 0xffffffff
|
||||||
|
|
||||||
// Copied from linux/l2tp.h
|
// Copied from linux/netfilter/nf_nat.h
|
||||||
// Including linux/l2tp.h here causes conflicts between linux/in.h
|
// Including linux/netfilter/nf_nat.h here causes conflicts between linux/in.h
|
||||||
// and netinet/in.h included via net/route.h above.
|
// and netinet/in.h.
|
||||||
#define IPPROTO_L2TP 115
|
#define NF_NAT_RANGE_MAP_IPS (1 << 0)
|
||||||
|
#define NF_NAT_RANGE_PROTO_SPECIFIED (1 << 1)
|
||||||
|
#define NF_NAT_RANGE_PROTO_RANDOM (1 << 2)
|
||||||
|
#define NF_NAT_RANGE_PERSISTENT (1 << 3)
|
||||||
|
#define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4)
|
||||||
|
#define NF_NAT_RANGE_PROTO_OFFSET (1 << 5)
|
||||||
|
#define NF_NAT_RANGE_NETMAP (1 << 6)
|
||||||
|
#define NF_NAT_RANGE_PROTO_RANDOM_ALL \
|
||||||
|
(NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
|
||||||
|
#define NF_NAT_RANGE_MASK \
|
||||||
|
(NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | \
|
||||||
|
NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | \
|
||||||
|
NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET | \
|
||||||
|
NF_NAT_RANGE_NETMAP)
|
||||||
|
|
||||||
// Copied from linux/hid.h.
|
// Copied from linux/hid.h.
|
||||||
// Keep in sync with the size of the referenced fields.
|
// Keep in sync with the size of the referenced fields.
|
||||||
@ -519,6 +521,7 @@ ccflags="$@"
|
|||||||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
||||||
$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
|
$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
|
||||||
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
|
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
|
||||||
|
$2 == "LOOP_CONFIGURE" ||
|
||||||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
|
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
|
||||||
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
|
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
|
||||||
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
|
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
|
||||||
@ -560,7 +563,7 @@ ccflags="$@"
|
|||||||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
||||||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
|
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
|
||||||
$2 ~ /^CLONE_[A-Z_]+/ ||
|
$2 ~ /^CLONE_[A-Z_]+/ ||
|
||||||
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+)$/ &&
|
$2 !~ /^(BPF_TIMEVAL|BPF_FIB_LOOKUP_[A-Z]+|BPF_F_LINK)$/ &&
|
||||||
$2 ~ /^(BPF|DLT)_/ ||
|
$2 ~ /^(BPF|DLT)_/ ||
|
||||||
$2 ~ /^AUDIT_/ ||
|
$2 ~ /^AUDIT_/ ||
|
||||||
$2 ~ /^(CLOCK|TIMER)_/ ||
|
$2 ~ /^(CLOCK|TIMER)_/ ||
|
||||||
@ -581,7 +584,7 @@ ccflags="$@"
|
|||||||
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
|
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
|
||||||
$2 ~ /^KEYCTL_/ ||
|
$2 ~ /^KEYCTL_/ ||
|
||||||
$2 ~ /^PERF_/ ||
|
$2 ~ /^PERF_/ ||
|
||||||
$2 ~ /^SECCOMP_MODE_/ ||
|
$2 ~ /^SECCOMP_/ ||
|
||||||
$2 ~ /^SEEK_/ ||
|
$2 ~ /^SEEK_/ ||
|
||||||
$2 ~ /^SCHED_/ ||
|
$2 ~ /^SCHED_/ ||
|
||||||
$2 ~ /^SPLICE_/ ||
|
$2 ~ /^SPLICE_/ ||
|
||||||
@ -602,6 +605,9 @@ ccflags="$@"
|
|||||||
$2 ~ /^FSOPT_/ ||
|
$2 ~ /^FSOPT_/ ||
|
||||||
$2 ~ /^WDIO[CFS]_/ ||
|
$2 ~ /^WDIO[CFS]_/ ||
|
||||||
$2 ~ /^NFN/ ||
|
$2 ~ /^NFN/ ||
|
||||||
|
$2 !~ /^NFT_META_IIFTYPE/ &&
|
||||||
|
$2 ~ /^NFT_/ ||
|
||||||
|
$2 ~ /^NF_NAT_/ ||
|
||||||
$2 ~ /^XDP_/ ||
|
$2 ~ /^XDP_/ ||
|
||||||
$2 ~ /^RWF_/ ||
|
$2 ~ /^RWF_/ ||
|
||||||
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
||||||
@ -663,7 +669,6 @@ echo '// mkerrors.sh' "$@"
|
|||||||
echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
|
echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
|
||||||
echo
|
echo
|
||||||
echo "//go:build ${GOARCH} && ${GOOS}"
|
echo "//go:build ${GOARCH} && ${GOOS}"
|
||||||
echo "// +build ${GOARCH},${GOOS}"
|
|
||||||
echo
|
echo
|
||||||
go tool cgo -godefs -- "$@" _const.go >_error.out
|
go tool cgo -godefs -- "$@" _const.go >_error.out
|
||||||
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
|
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user