This commit is contained in:
parent
e92d332269
commit
589c6a5861
26
go.mod
26
go.mod
@ -3,30 +3,30 @@ module git.paulbsd.com/paulbsd/ipbl
|
|||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/labstack/echo/v4 v4.7.2
|
github.com/labstack/echo/v4 v4.10.0
|
||||||
github.com/lib/pq v1.10.6
|
github.com/lib/pq v1.10.7
|
||||||
gopkg.in/ini.v1 v1.66.6
|
gopkg.in/ini.v1 v1.67.0
|
||||||
gopkg.in/zeromq/goczmq.v4 v4.1.0
|
gopkg.in/zeromq/goczmq.v4 v4.1.0
|
||||||
xorm.io/xorm v1.3.1
|
xorm.io/xorm v1.3.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/goccy/go-json v0.9.10 // indirect
|
github.com/goccy/go-json v0.10.0 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/labstack/gommon v0.3.1 // indirect
|
github.com/labstack/gommon v0.4.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.17 // 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
|
||||||
github.com/onsi/ginkgo v1.16.4 // indirect
|
github.com/onsi/ginkgo v1.16.4 // indirect
|
||||||
github.com/onsi/gomega v1.14.0 // indirect
|
github.com/onsi/gomega v1.14.0 // indirect
|
||||||
github.com/syndtr/goleveldb v1.0.0 // indirect
|
github.com/syndtr/goleveldb v1.0.0 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.1 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
|
golang.org/x/crypto v0.5.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect
|
golang.org/x/net v0.5.0 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
golang.org/x/sys v0.4.0 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.6.0 // indirect
|
||||||
xorm.io/builder v0.3.12 // indirect
|
xorm.io/builder v0.3.12 // indirect
|
||||||
)
|
)
|
||||||
|
133
go.sum
133
go.sum
@ -75,25 +75,15 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC
|
|||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/goccy/go-json v0.7.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
|
||||||
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/goccy/go-json v0.9.4 h1:L8MLKG2mvVXiQu07qB6hmfqeSYQdOnqPot2GhsIwIaI=
|
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
|
||||||
github.com/goccy/go-json v0.9.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/goccy/go-json v0.9.5 h1:ooSMW526ZjK+EaL5elrSyN2EzIfi/3V0m4+HJEDYLik=
|
|
||||||
github.com/goccy/go-json v0.9.5/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
|
||||||
github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM=
|
|
||||||
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
|
||||||
github.com/goccy/go-json v0.9.8 h1:DxXB6MLd6yyel7CLph8EwNIonUtVZd3Ue5iRcL4DQCE=
|
|
||||||
github.com/goccy/go-json v0.9.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
|
||||||
github.com/goccy/go-json v0.9.10 h1:hCeNmprSNLB8B8vQKWl6DpuH0t60oEs+TAk9a7CScKc=
|
|
||||||
github.com/goccy/go-json v0.9.10/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
|
||||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
@ -125,6 +115,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
@ -210,7 +201,6 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22
|
|||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
@ -226,23 +216,17 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/labstack/echo/v4 v4.6.3 h1:VhPuIZYxsbPmo4m9KAkMU/el2442eB7EBFFhNTTT9ac=
|
github.com/labstack/echo/v4 v4.10.0 h1:5CiyngihEO4HXsz3vVsJn7f8xAlWwRr3aY6Ih280ZKA=
|
||||||
github.com/labstack/echo/v4 v4.6.3/go.mod h1:Hk5OiHj0kDqmFq7aHe7eDqI7CUhuCrfpupQtLGGLm7A=
|
github.com/labstack/echo/v4 v4.10.0/go.mod h1:S/T/5fy/GigaXnHTkh0ZGe4LpkkQysvRjFMSUTkDRNQ=
|
||||||
github.com/labstack/echo/v4 v4.7.0 h1:8wHgZhoE9OT1NSLw6sfrX7ZGpWMtO5Zlfr68+BIo180=
|
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||||
github.com/labstack/echo/v4 v4.7.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
|
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||||
github.com/labstack/echo/v4 v4.7.2 h1:Kv2/p8OaQ+M6Ex4eGimg9b9e6icoxA42JSlOR3msKtI=
|
|
||||||
github.com/labstack/echo/v4 v4.7.2/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
|
|
||||||
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
|
|
||||||
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
|
||||||
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=
|
||||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
|
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||||
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
|
|
||||||
github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|
||||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||||
@ -251,8 +235,8 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea
|
|||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
@ -260,12 +244,11 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
|||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
|
||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||||
|
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
|
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
|
||||||
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
@ -381,8 +364,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
@ -390,8 +373,9 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb
|
|||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
|
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||||
|
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||||
@ -427,17 +411,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
|
||||||
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU=
|
|
||||||
golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
|
||||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
|
|
||||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
|
||||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
|
|
||||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
|
||||||
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=
|
||||||
@ -446,8 +421,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
|||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -468,18 +443,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
|
|||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
|
||||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93 h1:MYimHLfoXEpOhqd/zgoA/uoXzHB86AEky4LAx5ij9xA=
|
|
||||||
golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.0.0-20220630215102-69896b714898 h1:K7wO6V1IrczY9QOQ2WkVpw4JQSwCd52UsxVEirZUfiw=
|
|
||||||
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0=
|
|
||||||
golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
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=
|
||||||
@ -518,7 +483,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -526,32 +490,20 @@ golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
|
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng=
|
|
||||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
|
|
||||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8=
|
|
||||||
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
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/time v0.0.0-20201208040808-7e3f01d25324/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=
|
||||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -569,14 +521,13 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn
|
|||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE=
|
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
@ -612,10 +563,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
|||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||||
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
|
|
||||||
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
@ -628,8 +577,8 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/zeromq/goczmq.v4 v4.1.0 h1:CE+FE81mGVs2aSlnbfLuS1oAwdcVywyMM2AC1g33imI=
|
gopkg.in/zeromq/goczmq.v4 v4.1.0 h1:CE+FE81mGVs2aSlnbfLuS1oAwdcVywyMM2AC1g33imI=
|
||||||
gopkg.in/zeromq/goczmq.v4 v4.1.0/go.mod h1:h4IlfePEYMpFdywGr5gAwKhBBj+hiBl/nF4VoSE4k+0=
|
gopkg.in/zeromq/goczmq.v4 v4.1.0/go.mod h1:h4IlfePEYMpFdywGr5gAwKhBBj+hiBl/nF4VoSE4k+0=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
@ -638,7 +587,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
|
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
|
||||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||||
modernc.org/cc/v3 v3.33.6 h1:r63dgSzVzRxUpAJFPQWHy1QeZeY1ydNENUDaBx1GqYc=
|
|
||||||
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||||
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||||
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||||
@ -654,7 +602,6 @@ modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g
|
|||||||
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||||
modernc.org/cc/v3 v3.35.18 h1:rMZhRcWrba0y3nVmdiQ7kxAgOOSq2m2f2VzjHLgEs6U=
|
modernc.org/cc/v3 v3.35.18 h1:rMZhRcWrba0y3nVmdiQ7kxAgOOSq2m2f2VzjHLgEs6U=
|
||||||
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||||
modernc.org/ccgo/v3 v3.9.5 h1:dEuUSf8WN51rDkprFuAqjfchKEzN0WttP/Py3enBwjk=
|
|
||||||
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
|
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
|
||||||
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
|
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
|
||||||
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
|
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
|
||||||
@ -693,9 +640,7 @@ modernc.org/ccgo/v3 v3.12.82 h1:wudcnJyjLj1aQQCXF3IM9Gz2X6UNjw+afIghzdtn0v8=
|
|||||||
modernc.org/ccgo/v3 v3.12.82/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
|
modernc.org/ccgo/v3 v3.12.82/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
|
||||||
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||||
modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
|
||||||
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||||
modernc.org/libc v1.9.11 h1:QUxZMs48Ahg2F7SN41aERvMfGLY2HU/ADnB9DC4Yts8=
|
|
||||||
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
|
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
|
||||||
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
|
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
|
||||||
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M=
|
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M=
|
||||||
@ -733,38 +678,26 @@ modernc.org/libc v1.11.87 h1:PzIzOqtlzMDDcCzJ5cUP6h/Ku6Fa9iyflP2ccTY64aE=
|
|||||||
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
|
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
|
||||||
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||||
modernc.org/mathutil v1.4.0 h1:GCjoRaBew8ECCKINQA2nYjzvufFW9YiEuuB+rQ9bn2E=
|
|
||||||
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||||
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
|
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
|
||||||
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||||
modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM=
|
|
||||||
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
|
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
|
||||||
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
|
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
|
||||||
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
|
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
|
||||||
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
|
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
|
||||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||||
modernc.org/sqlite v1.11.2 h1:ShWQpeD3ag/bmx6TqidBlIWonWmQaSQKls3aenCbt+w=
|
|
||||||
modernc.org/sqlite v1.11.2/go.mod h1:+mhs/P1ONd+6G7hcAs6irwDi/bjTQ7nLW6LHRBsEa3A=
|
|
||||||
modernc.org/sqlite v1.14.2 h1:ohsW2+e+Qe2To1W6GNezzKGwjXwSax6R+CrhRxVaFbE=
|
modernc.org/sqlite v1.14.2 h1:ohsW2+e+Qe2To1W6GNezzKGwjXwSax6R+CrhRxVaFbE=
|
||||||
modernc.org/sqlite v1.14.2/go.mod h1:yqfn85u8wVOE6ub5UT8VI9JjhrwBUUCNyTACN0h6Sx8=
|
modernc.org/sqlite v1.14.2/go.mod h1:yqfn85u8wVOE6ub5UT8VI9JjhrwBUUCNyTACN0h6Sx8=
|
||||||
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
|
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
|
||||||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
|
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
|
||||||
modernc.org/tcl v1.5.5/go.mod h1:ADkaTUuwukkrlhqwERyq0SM8OvyXo7+TjFz7yAF56EI=
|
|
||||||
modernc.org/tcl v1.8.13/go.mod h1:V+q/Ef0IJaNUSECieLU4o+8IScapxnMyFV6i/7uQlAY=
|
modernc.org/tcl v1.8.13/go.mod h1:V+q/Ef0IJaNUSECieLU4o+8IScapxnMyFV6i/7uQlAY=
|
||||||
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
|
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
|
||||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
|
||||||
modernc.org/z v1.2.19/go.mod h1:+ZpP0pc4zz97eukOzW3xagV/lS82IpPN9NGG5pNF9vY=
|
modernc.org/z v1.2.19/go.mod h1:+ZpP0pc4zz97eukOzW3xagV/lS82IpPN9NGG5pNF9vY=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||||
xorm.io/builder v0.3.9 h1:Sd65/LdWyO7LR8+Cbd+e7mm3sK/7U9k0jS3999IDHMc=
|
|
||||||
xorm.io/builder v0.3.9/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
|
||||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||||
xorm.io/builder v0.3.11 h1:naLkJitGyYW7ZZdncsh/JW+HF4HshmvTHTyUyPwJS00=
|
|
||||||
xorm.io/builder v0.3.11/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
|
||||||
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
|
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
|
||||||
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||||
xorm.io/xorm v1.2.5 h1:tqN7OhN8P9xi52qBb76I8m5maAJMz/SSbgK2RGPCPbo=
|
xorm.io/xorm v1.3.2 h1:uTRRKF2jYzbZ5nsofXVUx6ncMaek+SHjWYtCXyZo1oM=
|
||||||
xorm.io/xorm v1.2.5/go.mod h1:fTG8tSjk6O1BYxwuohZUK+S1glnRycsCF05L1qQyEU0=
|
xorm.io/xorm v1.3.2/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw=
|
||||||
xorm.io/xorm v1.3.1 h1:z5egKrDoOLqZFhMjcGF4FBHiTmE5/feQoHclfhNidfM=
|
|
||||||
xorm.io/xorm v1.3.1/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw=
|
|
||||||
|
7
vendor/github.com/goccy/go-json/CHANGELOG.md
generated
vendored
7
vendor/github.com/goccy/go-json/CHANGELOG.md
generated
vendored
@ -1,3 +1,10 @@
|
|||||||
|
# v0.9.11 - 2022/08/18
|
||||||
|
|
||||||
|
### Fix bugs
|
||||||
|
|
||||||
|
* Fix unexpected behavior when buffer ends with backslash ( #383 )
|
||||||
|
* Fix stream decoding of escaped character ( #387 )
|
||||||
|
|
||||||
# v0.9.10 - 2022/07/15
|
# v0.9.10 - 2022/07/15
|
||||||
|
|
||||||
### Fix bugs
|
### Fix bugs
|
||||||
|
4
vendor/github.com/goccy/go-json/Makefile
generated
vendored
4
vendor/github.com/goccy/go-json/Makefile
generated
vendored
@ -22,7 +22,7 @@ cover-html: cover
|
|||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: golangci-lint
|
lint: golangci-lint
|
||||||
golangci-lint run
|
$(BIN_DIR)/golangci-lint run
|
||||||
|
|
||||||
golangci-lint: | $(BIN_DIR)
|
golangci-lint: | $(BIN_DIR)
|
||||||
@{ \
|
@{ \
|
||||||
@ -30,7 +30,7 @@ golangci-lint: | $(BIN_DIR)
|
|||||||
GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \
|
GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \
|
||||||
cd $$GOLANGCI_LINT_TMP_DIR; \
|
cd $$GOLANGCI_LINT_TMP_DIR; \
|
||||||
go mod init tmp; \
|
go mod init tmp; \
|
||||||
GOBIN=$(BIN_DIR) go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.36.0; \
|
GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.48.0; \
|
||||||
rm -rf $$GOLANGCI_LINT_TMP_DIR; \
|
rm -rf $$GOLANGCI_LINT_TMP_DIR; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/goccy/go-json/README.md
generated
vendored
2
vendor/github.com/goccy/go-json/README.md
generated
vendored
@ -184,7 +184,7 @@ func Marshal(v interface{}) ([]byte, error) {
|
|||||||
`json.Marshal` and `json.Unmarshal` receive `interface{}` value and they perform type determination dynamically to process.
|
`json.Marshal` and `json.Unmarshal` receive `interface{}` value and they perform type determination dynamically to process.
|
||||||
In normal case, you need to use the `reflect` library to determine the type dynamically, but since `reflect.Type` is defined as `interface`, when you call the method of `reflect.Type`, The reflect's argument is escaped.
|
In normal case, you need to use the `reflect` library to determine the type dynamically, but since `reflect.Type` is defined as `interface`, when you call the method of `reflect.Type`, The reflect's argument is escaped.
|
||||||
|
|
||||||
Therefore, the arguments for `Marshal` and `Unmarshal` are always escape to the heap.
|
Therefore, the arguments for `Marshal` and `Unmarshal` are always escaped to the heap.
|
||||||
However, `go-json` can use the feature of `reflect.Type` while avoiding escaping.
|
However, `go-json` can use the feature of `reflect.Type` while avoiding escaping.
|
||||||
|
|
||||||
`reflect.Type` is defined as `interface`, but in reality `reflect.Type` is implemented only by the structure `rtype` defined in the `reflect` package.
|
`reflect.Type` is defined as `interface`, but in reality `reflect.Type` is implemented only by the structure `rtype` defined in the `reflect` package.
|
||||||
|
31
vendor/github.com/goccy/go-json/decode.go
generated
vendored
31
vendor/github.com/goccy/go-json/decode.go
generated
vendored
@ -83,6 +83,37 @@ func unmarshalContext(ctx context.Context, data []byte, v interface{}, optFuncs
|
|||||||
return validateEndBuf(src, cursor)
|
return validateEndBuf(src, cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
pathDecoder = decoder.NewPathDecoder()
|
||||||
|
)
|
||||||
|
|
||||||
|
func extractFromPath(path *Path, data []byte, optFuncs ...DecodeOptionFunc) ([][]byte, error) {
|
||||||
|
if path.path.RootSelectorOnly {
|
||||||
|
return [][]byte{data}, nil
|
||||||
|
}
|
||||||
|
src := make([]byte, len(data)+1) // append nul byte to the end
|
||||||
|
copy(src, data)
|
||||||
|
|
||||||
|
ctx := decoder.TakeRuntimeContext()
|
||||||
|
ctx.Buf = src
|
||||||
|
ctx.Option.Flags = 0
|
||||||
|
ctx.Option.Flags |= decoder.PathOption
|
||||||
|
ctx.Option.Path = path.path
|
||||||
|
for _, optFunc := range optFuncs {
|
||||||
|
optFunc(ctx.Option)
|
||||||
|
}
|
||||||
|
paths, cursor, err := pathDecoder.DecodePath(ctx, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
decoder.ReleaseRuntimeContext(ctx)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
decoder.ReleaseRuntimeContext(ctx)
|
||||||
|
if err := validateEndBuf(src, cursor); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return paths, nil
|
||||||
|
}
|
||||||
|
|
||||||
func unmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
func unmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
||||||
src := make([]byte, len(data)+1) // append nul byte to the end
|
src := make([]byte, len(data)+1) // append nul byte to the end
|
||||||
copy(src, data)
|
copy(src, data)
|
||||||
|
2
vendor/github.com/goccy/go-json/error.go
generated
vendored
2
vendor/github.com/goccy/go-json/error.go
generated
vendored
@ -37,3 +37,5 @@ type UnmarshalTypeError = errors.UnmarshalTypeError
|
|||||||
type UnsupportedTypeError = errors.UnsupportedTypeError
|
type UnsupportedTypeError = errors.UnsupportedTypeError
|
||||||
|
|
||||||
type UnsupportedValueError = errors.UnsupportedValueError
|
type UnsupportedValueError = errors.UnsupportedValueError
|
||||||
|
|
||||||
|
type PathError = errors.PathError
|
||||||
|
4
vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go
generated
vendored
4
vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go
generated
vendored
@ -35,3 +35,7 @@ func (d *anonymousFieldDecoder) Decode(ctx *RuntimeContext, cursor, depth int64,
|
|||||||
p = *(*unsafe.Pointer)(p)
|
p = *(*unsafe.Pointer)(p)
|
||||||
return d.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+d.offset))
|
return d.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+d.offset))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *anonymousFieldDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return d.dec.DecodePath(ctx, cursor, depth)
|
||||||
|
}
|
||||||
|
5
vendor/github.com/goccy/go-json/internal/decoder/array.go
generated
vendored
5
vendor/github.com/goccy/go-json/internal/decoder/array.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package decoder
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/errors"
|
"github.com/goccy/go-json/internal/errors"
|
||||||
@ -167,3 +168,7 @@ func (d *arrayDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *arrayDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: array decoder does not support decode path")
|
||||||
|
}
|
||||||
|
438
vendor/github.com/goccy/go-json/internal/decoder/assign.go
generated
vendored
Normal file
438
vendor/github.com/goccy/go-json/internal/decoder/assign.go
generated
vendored
Normal file
@ -0,0 +1,438 @@
|
|||||||
|
package decoder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
nilValue = reflect.ValueOf(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
func AssignValue(src, dst reflect.Value) error {
|
||||||
|
if dst.Type().Kind() != reflect.Ptr {
|
||||||
|
return fmt.Errorf("invalid dst type. required pointer type: %T", dst.Type())
|
||||||
|
}
|
||||||
|
casted, err := castValue(dst.Elem().Type(), src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dst.Elem().Set(casted)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func castValue(t reflect.Type, v reflect.Value) (reflect.Value, error) {
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Int:
|
||||||
|
vv, err := castInt(v)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(int(vv.Int())), nil
|
||||||
|
case reflect.Int8:
|
||||||
|
vv, err := castInt(v)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(int8(vv.Int())), nil
|
||||||
|
case reflect.Int16:
|
||||||
|
vv, err := castInt(v)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(int16(vv.Int())), nil
|
||||||
|
case reflect.Int32:
|
||||||
|
vv, err := castInt(v)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(int32(vv.Int())), nil
|
||||||
|
case reflect.Int64:
|
||||||
|
return castInt(v)
|
||||||
|
case reflect.Uint:
|
||||||
|
vv, err := castUint(v)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(uint(vv.Uint())), nil
|
||||||
|
case reflect.Uint8:
|
||||||
|
vv, err := castUint(v)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(uint8(vv.Uint())), nil
|
||||||
|
case reflect.Uint16:
|
||||||
|
vv, err := castUint(v)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(uint16(vv.Uint())), nil
|
||||||
|
case reflect.Uint32:
|
||||||
|
vv, err := castUint(v)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(uint32(vv.Uint())), nil
|
||||||
|
case reflect.Uint64:
|
||||||
|
return castUint(v)
|
||||||
|
case reflect.Uintptr:
|
||||||
|
vv, err := castUint(v)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(uintptr(vv.Uint())), nil
|
||||||
|
case reflect.String:
|
||||||
|
return castString(v)
|
||||||
|
case reflect.Bool:
|
||||||
|
return castBool(v)
|
||||||
|
case reflect.Float32:
|
||||||
|
vv, err := castFloat(v)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(float32(vv.Float())), nil
|
||||||
|
case reflect.Float64:
|
||||||
|
return castFloat(v)
|
||||||
|
case reflect.Array:
|
||||||
|
return castArray(t, v)
|
||||||
|
case reflect.Slice:
|
||||||
|
return castSlice(t, v)
|
||||||
|
case reflect.Map:
|
||||||
|
return castMap(t, v)
|
||||||
|
case reflect.Struct:
|
||||||
|
return castStruct(t, v)
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func castInt(v reflect.Value) (reflect.Value, error) {
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return v, nil
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return reflect.ValueOf(int64(v.Uint())), nil
|
||||||
|
case reflect.String:
|
||||||
|
i64, err := strconv.ParseInt(v.String(), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(i64), nil
|
||||||
|
case reflect.Bool:
|
||||||
|
if v.Bool() {
|
||||||
|
return reflect.ValueOf(int64(1)), nil
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(int64(0)), nil
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return reflect.ValueOf(int64(v.Float())), nil
|
||||||
|
case reflect.Array:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castInt(v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to int64 from empty array")
|
||||||
|
case reflect.Slice:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castInt(v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to int64 from empty slice")
|
||||||
|
case reflect.Interface:
|
||||||
|
return castInt(reflect.ValueOf(v.Interface()))
|
||||||
|
case reflect.Map:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to int64 from map")
|
||||||
|
case reflect.Struct:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to int64 from struct")
|
||||||
|
case reflect.Ptr:
|
||||||
|
return castInt(v.Elem())
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to int64 from %s", v.Type().Kind())
|
||||||
|
}
|
||||||
|
|
||||||
|
func castUint(v reflect.Value) (reflect.Value, error) {
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return reflect.ValueOf(uint64(v.Int())), nil
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return v, nil
|
||||||
|
case reflect.String:
|
||||||
|
u64, err := strconv.ParseUint(v.String(), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(u64), nil
|
||||||
|
case reflect.Bool:
|
||||||
|
if v.Bool() {
|
||||||
|
return reflect.ValueOf(uint64(1)), nil
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(uint64(0)), nil
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return reflect.ValueOf(uint64(v.Float())), nil
|
||||||
|
case reflect.Array:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castUint(v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to uint64 from empty array")
|
||||||
|
case reflect.Slice:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castUint(v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to uint64 from empty slice")
|
||||||
|
case reflect.Interface:
|
||||||
|
return castUint(reflect.ValueOf(v.Interface()))
|
||||||
|
case reflect.Map:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to uint64 from map")
|
||||||
|
case reflect.Struct:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to uint64 from struct")
|
||||||
|
case reflect.Ptr:
|
||||||
|
return castUint(v.Elem())
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to uint64 from %s", v.Type().Kind())
|
||||||
|
}
|
||||||
|
|
||||||
|
func castString(v reflect.Value) (reflect.Value, error) {
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return reflect.ValueOf(fmt.Sprint(v.Int())), nil
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return reflect.ValueOf(fmt.Sprint(v.Uint())), nil
|
||||||
|
case reflect.String:
|
||||||
|
return v, nil
|
||||||
|
case reflect.Bool:
|
||||||
|
if v.Bool() {
|
||||||
|
return reflect.ValueOf("true"), nil
|
||||||
|
}
|
||||||
|
return reflect.ValueOf("false"), nil
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return reflect.ValueOf(fmt.Sprint(v.Float())), nil
|
||||||
|
case reflect.Array:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castString(v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to string from empty array")
|
||||||
|
case reflect.Slice:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castString(v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to string from empty slice")
|
||||||
|
case reflect.Interface:
|
||||||
|
return castString(reflect.ValueOf(v.Interface()))
|
||||||
|
case reflect.Map:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to string from map")
|
||||||
|
case reflect.Struct:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to string from struct")
|
||||||
|
case reflect.Ptr:
|
||||||
|
return castString(v.Elem())
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to string from %s", v.Type().Kind())
|
||||||
|
}
|
||||||
|
|
||||||
|
func castBool(v reflect.Value) (reflect.Value, error) {
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
switch v.Int() {
|
||||||
|
case 0:
|
||||||
|
return reflect.ValueOf(false), nil
|
||||||
|
case 1:
|
||||||
|
return reflect.ValueOf(true), nil
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to bool from %d", v.Int())
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
switch v.Uint() {
|
||||||
|
case 0:
|
||||||
|
return reflect.ValueOf(false), nil
|
||||||
|
case 1:
|
||||||
|
return reflect.ValueOf(true), nil
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to bool from %d", v.Uint())
|
||||||
|
case reflect.String:
|
||||||
|
b, err := strconv.ParseBool(v.String())
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(b), nil
|
||||||
|
case reflect.Bool:
|
||||||
|
return v, nil
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
switch v.Float() {
|
||||||
|
case 0:
|
||||||
|
return reflect.ValueOf(false), nil
|
||||||
|
case 1:
|
||||||
|
return reflect.ValueOf(true), nil
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to bool from %f", v.Float())
|
||||||
|
case reflect.Array:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castBool(v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to string from empty array")
|
||||||
|
case reflect.Slice:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castBool(v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to string from empty slice")
|
||||||
|
case reflect.Interface:
|
||||||
|
return castBool(reflect.ValueOf(v.Interface()))
|
||||||
|
case reflect.Map:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to string from map")
|
||||||
|
case reflect.Struct:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to string from struct")
|
||||||
|
case reflect.Ptr:
|
||||||
|
return castBool(v.Elem())
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to bool from %s", v.Type().Kind())
|
||||||
|
}
|
||||||
|
|
||||||
|
func castFloat(v reflect.Value) (reflect.Value, error) {
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return reflect.ValueOf(float64(v.Int())), nil
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return reflect.ValueOf(float64(v.Uint())), nil
|
||||||
|
case reflect.String:
|
||||||
|
f64, err := strconv.ParseFloat(v.String(), 64)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(f64), nil
|
||||||
|
case reflect.Bool:
|
||||||
|
if v.Bool() {
|
||||||
|
return reflect.ValueOf(float64(1)), nil
|
||||||
|
}
|
||||||
|
return reflect.ValueOf(float64(0)), nil
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return v, nil
|
||||||
|
case reflect.Array:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castFloat(v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to float64 from empty array")
|
||||||
|
case reflect.Slice:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castFloat(v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to float64 from empty slice")
|
||||||
|
case reflect.Interface:
|
||||||
|
return castFloat(reflect.ValueOf(v.Interface()))
|
||||||
|
case reflect.Map:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to float64 from map")
|
||||||
|
case reflect.Struct:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to float64 from struct")
|
||||||
|
case reflect.Ptr:
|
||||||
|
return castFloat(v.Elem())
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to float64 from %s", v.Type().Kind())
|
||||||
|
}
|
||||||
|
|
||||||
|
func castArray(t reflect.Type, v reflect.Value) (reflect.Value, error) {
|
||||||
|
kind := v.Type().Kind()
|
||||||
|
if kind == reflect.Interface {
|
||||||
|
return castArray(t, reflect.ValueOf(v.Interface()))
|
||||||
|
}
|
||||||
|
if kind != reflect.Slice && kind != reflect.Array {
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to array from %s", kind)
|
||||||
|
}
|
||||||
|
if t.Elem() == v.Type().Elem() {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
if t.Len() != v.Len() {
|
||||||
|
return nilValue, fmt.Errorf("failed to cast [%d]array from slice of %d length", t.Len(), v.Len())
|
||||||
|
}
|
||||||
|
ret := reflect.New(t).Elem()
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
vv, err := castValue(t.Elem(), v.Index(i))
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
ret.Index(i).Set(vv)
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func castSlice(t reflect.Type, v reflect.Value) (reflect.Value, error) {
|
||||||
|
kind := v.Type().Kind()
|
||||||
|
if kind == reflect.Interface {
|
||||||
|
return castSlice(t, reflect.ValueOf(v.Interface()))
|
||||||
|
}
|
||||||
|
if kind != reflect.Slice && kind != reflect.Array {
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to slice from %s", kind)
|
||||||
|
}
|
||||||
|
if t.Elem() == v.Type().Elem() {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
ret := reflect.MakeSlice(t, v.Len(), v.Len())
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
vv, err := castValue(t.Elem(), v.Index(i))
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
ret.Index(i).Set(vv)
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func castMap(t reflect.Type, v reflect.Value) (reflect.Value, error) {
|
||||||
|
ret := reflect.MakeMap(t)
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
iter := v.MapRange()
|
||||||
|
for iter.Next() {
|
||||||
|
key, err := castValue(t.Key(), iter.Key())
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
value, err := castValue(t.Elem(), iter.Value())
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
ret.SetMapIndex(key, value)
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
return castMap(t, reflect.ValueOf(v.Interface()))
|
||||||
|
case reflect.Slice:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castMap(t, v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to map from empty slice")
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to map from %s", v.Type().Kind())
|
||||||
|
}
|
||||||
|
|
||||||
|
func castStruct(t reflect.Type, v reflect.Value) (reflect.Value, error) {
|
||||||
|
ret := reflect.New(t).Elem()
|
||||||
|
switch v.Type().Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
iter := v.MapRange()
|
||||||
|
for iter.Next() {
|
||||||
|
key := iter.Key()
|
||||||
|
k, err := castString(key)
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
fieldName := k.String()
|
||||||
|
field, ok := t.FieldByName(fieldName)
|
||||||
|
if ok {
|
||||||
|
value, err := castValue(field.Type, iter.Value())
|
||||||
|
if err != nil {
|
||||||
|
return nilValue, err
|
||||||
|
}
|
||||||
|
ret.FieldByName(fieldName).Set(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
case reflect.Struct:
|
||||||
|
for i := 0; i < v.Type().NumField(); i++ {
|
||||||
|
name := v.Type().Field(i).Name
|
||||||
|
ret.FieldByName(name).Set(v.FieldByName(name))
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
return castStruct(t, reflect.ValueOf(v.Interface()))
|
||||||
|
case reflect.Slice:
|
||||||
|
if v.Len() > 0 {
|
||||||
|
return castStruct(t, v.Index(0))
|
||||||
|
}
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to struct from empty slice")
|
||||||
|
default:
|
||||||
|
return nilValue, fmt.Errorf("failed to cast to struct from %s", v.Type().Kind())
|
||||||
|
}
|
||||||
|
}
|
5
vendor/github.com/goccy/go-json/internal/decoder/bool.go
generated
vendored
5
vendor/github.com/goccy/go-json/internal/decoder/bool.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package decoder
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/errors"
|
"github.com/goccy/go-json/internal/errors"
|
||||||
@ -76,3 +77,7 @@ func (d *boolDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.
|
|||||||
}
|
}
|
||||||
return 0, errors.ErrUnexpectedEndOfJSON("bool", cursor)
|
return 0, errors.ErrUnexpectedEndOfJSON("bool", cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *boolDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: bool decoder does not support decode path")
|
||||||
|
}
|
||||||
|
5
vendor/github.com/goccy/go-json/internal/decoder/bytes.go
generated
vendored
5
vendor/github.com/goccy/go-json/internal/decoder/bytes.go
generated
vendored
@ -2,6 +2,7 @@ package decoder
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/errors"
|
"github.com/goccy/go-json/internal/errors"
|
||||||
@ -78,6 +79,10 @@ func (d *bytesDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe
|
|||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *bytesDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: []byte decoder does not support decode path")
|
||||||
|
}
|
||||||
|
|
||||||
func (d *bytesDecoder) decodeStreamBinary(s *Stream, depth int64, p unsafe.Pointer) ([]byte, error) {
|
func (d *bytesDecoder) decodeStreamBinary(s *Stream, depth int64, p unsafe.Pointer) ([]byte, error) {
|
||||||
c := s.skipWhiteSpace()
|
c := s.skipWhiteSpace()
|
||||||
if c == '[' {
|
if c == '[' {
|
||||||
|
12
vendor/github.com/goccy/go-json/internal/decoder/float.go
generated
vendored
12
vendor/github.com/goccy/go-json/internal/decoder/float.go
generated
vendored
@ -156,3 +156,15 @@ func (d *floatDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe
|
|||||||
d.op(p, f64)
|
d.op(p, f64)
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *floatDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
buf := ctx.Buf
|
||||||
|
bytes, c, err := d.decodeByte(buf, cursor)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
if bytes == nil {
|
||||||
|
return [][]byte{nullbytes}, c, nil
|
||||||
|
}
|
||||||
|
return [][]byte{bytes}, c, nil
|
||||||
|
}
|
||||||
|
5
vendor/github.com/goccy/go-json/internal/decoder/func.go
generated
vendored
5
vendor/github.com/goccy/go-json/internal/decoder/func.go
generated
vendored
@ -2,6 +2,7 @@ package decoder
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/errors"
|
"github.com/goccy/go-json/internal/errors"
|
||||||
@ -139,3 +140,7 @@ func (d *funcDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.
|
|||||||
}
|
}
|
||||||
return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
|
return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *funcDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: func decoder does not support decode path")
|
||||||
|
}
|
||||||
|
4
vendor/github.com/goccy/go-json/internal/decoder/int.go
generated
vendored
4
vendor/github.com/goccy/go-json/internal/decoder/int.go
generated
vendored
@ -240,3 +240,7 @@ func (d *intDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.P
|
|||||||
d.op(p, i64)
|
d.op(p, i64)
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *intDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: int decoder does not support decode path")
|
||||||
|
}
|
||||||
|
70
vendor/github.com/goccy/go-json/internal/decoder/interface.go
generated
vendored
70
vendor/github.com/goccy/go-json/internal/decoder/interface.go
generated
vendored
@ -94,6 +94,7 @@ func (d *interfaceDecoder) numDecoder(s *Stream) Decoder {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem())
|
emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem())
|
||||||
|
EmptyInterfaceType = emptyInterfaceType
|
||||||
interfaceMapType = runtime.Type2RType(
|
interfaceMapType = runtime.Type2RType(
|
||||||
reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
|
reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
|
||||||
)
|
)
|
||||||
@ -456,3 +457,72 @@ func (d *interfaceDecoder) decodeEmptyInterface(ctx *RuntimeContext, cursor, dep
|
|||||||
}
|
}
|
||||||
return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
|
return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPathDecoder() Decoder {
|
||||||
|
ifaceDecoder := &interfaceDecoder{
|
||||||
|
typ: emptyInterfaceType,
|
||||||
|
structName: "",
|
||||||
|
fieldName: "",
|
||||||
|
floatDecoder: newFloatDecoder("", "", func(p unsafe.Pointer, v float64) {
|
||||||
|
*(*interface{})(p) = v
|
||||||
|
}),
|
||||||
|
numberDecoder: newNumberDecoder("", "", func(p unsafe.Pointer, v json.Number) {
|
||||||
|
*(*interface{})(p) = v
|
||||||
|
}),
|
||||||
|
stringDecoder: newStringDecoder("", ""),
|
||||||
|
}
|
||||||
|
ifaceDecoder.sliceDecoder = newSliceDecoder(
|
||||||
|
ifaceDecoder,
|
||||||
|
emptyInterfaceType,
|
||||||
|
emptyInterfaceType.Size(),
|
||||||
|
"", "",
|
||||||
|
)
|
||||||
|
ifaceDecoder.mapDecoder = newMapDecoder(
|
||||||
|
interfaceMapType,
|
||||||
|
stringType,
|
||||||
|
ifaceDecoder.stringDecoder,
|
||||||
|
interfaceMapType.Elem(),
|
||||||
|
ifaceDecoder,
|
||||||
|
"", "",
|
||||||
|
)
|
||||||
|
return ifaceDecoder
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
truebytes = []byte("true")
|
||||||
|
falsebytes = []byte("false")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *interfaceDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
buf := ctx.Buf
|
||||||
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
|
switch buf[cursor] {
|
||||||
|
case '{':
|
||||||
|
return d.mapDecoder.DecodePath(ctx, cursor, depth)
|
||||||
|
case '[':
|
||||||
|
return d.sliceDecoder.DecodePath(ctx, cursor, depth)
|
||||||
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
|
return d.floatDecoder.DecodePath(ctx, cursor, depth)
|
||||||
|
case '"':
|
||||||
|
return d.stringDecoder.DecodePath(ctx, cursor, depth)
|
||||||
|
case 't':
|
||||||
|
if err := validateTrue(buf, cursor); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
cursor += 4
|
||||||
|
return [][]byte{truebytes}, cursor, nil
|
||||||
|
case 'f':
|
||||||
|
if err := validateFalse(buf, cursor); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
cursor += 5
|
||||||
|
return [][]byte{falsebytes}, cursor, nil
|
||||||
|
case 'n':
|
||||||
|
if err := validateNull(buf, cursor); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
cursor += 4
|
||||||
|
return [][]byte{nullbytes}, cursor, nil
|
||||||
|
}
|
||||||
|
return nil, cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
|
||||||
|
}
|
||||||
|
10
vendor/github.com/goccy/go-json/internal/decoder/invalid.go
generated
vendored
10
vendor/github.com/goccy/go-json/internal/decoder/invalid.go
generated
vendored
@ -43,3 +43,13 @@ func (d *invalidDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsa
|
|||||||
Field: d.fieldName,
|
Field: d.fieldName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *invalidDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, &errors.UnmarshalTypeError{
|
||||||
|
Value: "object",
|
||||||
|
Type: runtime.RType2Type(d.typ),
|
||||||
|
Offset: cursor,
|
||||||
|
Struct: d.structName,
|
||||||
|
Field: d.fieldName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
93
vendor/github.com/goccy/go-json/internal/decoder/map.go
generated
vendored
93
vendor/github.com/goccy/go-json/internal/decoder/map.go
generated
vendored
@ -185,3 +185,96 @@ func (d *mapDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.P
|
|||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *mapDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
buf := ctx.Buf
|
||||||
|
depth++
|
||||||
|
if depth > maxDecodeNestingDepth {
|
||||||
|
return nil, 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
|
buflen := int64(len(buf))
|
||||||
|
if buflen < 2 {
|
||||||
|
return nil, 0, errors.ErrExpected("{} for map", cursor)
|
||||||
|
}
|
||||||
|
switch buf[cursor] {
|
||||||
|
case 'n':
|
||||||
|
if err := validateNull(buf, cursor); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
cursor += 4
|
||||||
|
return [][]byte{nullbytes}, cursor, nil
|
||||||
|
case '{':
|
||||||
|
default:
|
||||||
|
return nil, 0, errors.ErrExpected("{ character for map value", cursor)
|
||||||
|
}
|
||||||
|
cursor++
|
||||||
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
|
if buf[cursor] == '}' {
|
||||||
|
cursor++
|
||||||
|
return nil, cursor, nil
|
||||||
|
}
|
||||||
|
keyDecoder, ok := d.keyDecoder.(*stringDecoder)
|
||||||
|
if !ok {
|
||||||
|
return nil, 0, &errors.UnmarshalTypeError{
|
||||||
|
Value: "string",
|
||||||
|
Type: reflect.TypeOf(""),
|
||||||
|
Offset: cursor,
|
||||||
|
Struct: d.structName,
|
||||||
|
Field: d.fieldName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret := [][]byte{}
|
||||||
|
for {
|
||||||
|
key, keyCursor, err := keyDecoder.decodeByte(buf, cursor)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
cursor = skipWhiteSpace(buf, keyCursor)
|
||||||
|
if buf[cursor] != ':' {
|
||||||
|
return nil, 0, errors.ErrExpected("colon after object key", cursor)
|
||||||
|
}
|
||||||
|
cursor++
|
||||||
|
child, found, err := ctx.Option.Path.Field(string(key))
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
if child != nil {
|
||||||
|
oldPath := ctx.Option.Path.node
|
||||||
|
ctx.Option.Path.node = child
|
||||||
|
paths, c, err := d.valueDecoder.DecodePath(ctx, cursor, depth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
ctx.Option.Path.node = oldPath
|
||||||
|
ret = append(ret, paths...)
|
||||||
|
cursor = c
|
||||||
|
} else {
|
||||||
|
start := cursor
|
||||||
|
end, err := skipValue(buf, cursor, depth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
ret = append(ret, buf[start:end])
|
||||||
|
cursor = end
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c, err := skipValue(buf, cursor, depth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
cursor = c
|
||||||
|
}
|
||||||
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
|
if buf[cursor] == '}' {
|
||||||
|
cursor++
|
||||||
|
return ret, cursor, nil
|
||||||
|
}
|
||||||
|
if buf[cursor] != ',' {
|
||||||
|
return nil, 0, errors.ErrExpected("comma after object value", cursor)
|
||||||
|
}
|
||||||
|
cursor++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
11
vendor/github.com/goccy/go-json/internal/decoder/number.go
generated
vendored
11
vendor/github.com/goccy/go-json/internal/decoder/number.go
generated
vendored
@ -51,6 +51,17 @@ func (d *numberDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsaf
|
|||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *numberDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
bytes, c, err := d.decodeByte(ctx.Buf, cursor)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
if bytes == nil {
|
||||||
|
return [][]byte{nullbytes}, c, nil
|
||||||
|
}
|
||||||
|
return [][]byte{bytes}, c, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
|
||||||
start := s.cursor
|
start := s.cursor
|
||||||
for {
|
for {
|
||||||
|
2
vendor/github.com/goccy/go-json/internal/decoder/option.go
generated
vendored
2
vendor/github.com/goccy/go-json/internal/decoder/option.go
generated
vendored
@ -7,9 +7,11 @@ type OptionFlags uint8
|
|||||||
const (
|
const (
|
||||||
FirstWinOption OptionFlags = 1 << iota
|
FirstWinOption OptionFlags = 1 << iota
|
||||||
ContextOption
|
ContextOption
|
||||||
|
PathOption
|
||||||
)
|
)
|
||||||
|
|
||||||
type Option struct {
|
type Option struct {
|
||||||
Flags OptionFlags
|
Flags OptionFlags
|
||||||
Context context.Context
|
Context context.Context
|
||||||
|
Path *Path
|
||||||
}
|
}
|
||||||
|
670
vendor/github.com/goccy/go-json/internal/decoder/path.go
generated
vendored
Normal file
670
vendor/github.com/goccy/go-json/internal/decoder/path.go
generated
vendored
Normal file
@ -0,0 +1,670 @@
|
|||||||
|
package decoder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/errors"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PathString string
|
||||||
|
|
||||||
|
func (s PathString) Build() (*Path, error) {
|
||||||
|
builder := new(PathBuilder)
|
||||||
|
return builder.Build([]rune(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathBuilder struct {
|
||||||
|
root PathNode
|
||||||
|
node PathNode
|
||||||
|
singleQuotePathSelector bool
|
||||||
|
doubleQuotePathSelector bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) Build(buf []rune) (*Path, error) {
|
||||||
|
node, err := b.build(buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Path{
|
||||||
|
node: node,
|
||||||
|
RootSelectorOnly: node == nil,
|
||||||
|
SingleQuotePathSelector: b.singleQuotePathSelector,
|
||||||
|
DoubleQuotePathSelector: b.doubleQuotePathSelector,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) build(buf []rune) (PathNode, error) {
|
||||||
|
if len(buf) == 0 {
|
||||||
|
return nil, errors.ErrEmptyPath()
|
||||||
|
}
|
||||||
|
if buf[0] != '$' {
|
||||||
|
return nil, errors.ErrInvalidPath("JSON Path must start with a $ character")
|
||||||
|
}
|
||||||
|
if len(buf) == 1 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
buf = buf[1:]
|
||||||
|
offset, err := b.buildNext(buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(buf) > offset {
|
||||||
|
return nil, errors.ErrInvalidPath("remain invalid path %q", buf[offset:])
|
||||||
|
}
|
||||||
|
return b.root, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) buildNextCharIfExists(buf []rune, cursor int) (int, error) {
|
||||||
|
if len(buf) > cursor {
|
||||||
|
offset, err := b.buildNext(buf[cursor:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return cursor + 1 + offset, nil
|
||||||
|
}
|
||||||
|
return cursor, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) buildNext(buf []rune) (int, error) {
|
||||||
|
switch buf[0] {
|
||||||
|
case '.':
|
||||||
|
if len(buf) == 1 {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with dot character")
|
||||||
|
}
|
||||||
|
offset, err := b.buildSelector(buf[1:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return offset + 1, nil
|
||||||
|
case '[':
|
||||||
|
if len(buf) == 1 {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character")
|
||||||
|
}
|
||||||
|
offset, err := b.buildIndex(buf[1:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return offset + 1, nil
|
||||||
|
default:
|
||||||
|
return 0, errors.ErrInvalidPath("expect dot or left bracket character. but found %c character", buf[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) buildSelector(buf []rune) (int, error) {
|
||||||
|
switch buf[0] {
|
||||||
|
case '.':
|
||||||
|
if len(buf) == 1 {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with double dot character")
|
||||||
|
}
|
||||||
|
offset, err := b.buildPathRecursive(buf[1:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return 1 + offset, nil
|
||||||
|
case '[', ']', '$', '*':
|
||||||
|
return 0, errors.ErrInvalidPath("found invalid path character %c after dot", buf[0])
|
||||||
|
}
|
||||||
|
for cursor := 0; cursor < len(buf); cursor++ {
|
||||||
|
switch buf[cursor] {
|
||||||
|
case '$', '*', ']':
|
||||||
|
return 0, errors.ErrInvalidPath("found %c character in field selector context", buf[cursor])
|
||||||
|
case '.':
|
||||||
|
if cursor+1 >= len(buf) {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with dot character")
|
||||||
|
}
|
||||||
|
selector := buf[:cursor]
|
||||||
|
b.addSelectorNode(string(selector))
|
||||||
|
offset, err := b.buildSelector(buf[cursor+1:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return cursor + 1 + offset, nil
|
||||||
|
case '[':
|
||||||
|
if cursor+1 >= len(buf) {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character")
|
||||||
|
}
|
||||||
|
selector := buf[:cursor]
|
||||||
|
b.addSelectorNode(string(selector))
|
||||||
|
offset, err := b.buildIndex(buf[cursor+1:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return cursor + 1 + offset, nil
|
||||||
|
case '"':
|
||||||
|
if cursor+1 >= len(buf) {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with double quote character")
|
||||||
|
}
|
||||||
|
offset, err := b.buildQuoteSelector(buf[cursor+1:], DoubleQuotePathSelector)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return cursor + 1 + offset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.addSelectorNode(string(buf))
|
||||||
|
return len(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) buildQuoteSelector(buf []rune, sel QuotePathSelector) (int, error) {
|
||||||
|
switch buf[0] {
|
||||||
|
case '[', ']', '$', '.', '*', '\'', '"':
|
||||||
|
return 0, errors.ErrInvalidPath("found invalid path character %c after quote", buf[0])
|
||||||
|
}
|
||||||
|
for cursor := 0; cursor < len(buf); cursor++ {
|
||||||
|
switch buf[cursor] {
|
||||||
|
case '\'':
|
||||||
|
if sel != SingleQuotePathSelector {
|
||||||
|
return 0, errors.ErrInvalidPath("found double quote character in field selector with single quote context")
|
||||||
|
}
|
||||||
|
if len(buf) <= cursor+1 {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with single quote character in field selector context")
|
||||||
|
}
|
||||||
|
if buf[cursor+1] != ']' {
|
||||||
|
return 0, errors.ErrInvalidPath("expect right bracket for field selector with single quote but found %c", buf[cursor+1])
|
||||||
|
}
|
||||||
|
selector := buf[:cursor]
|
||||||
|
b.addSelectorNode(string(selector))
|
||||||
|
b.singleQuotePathSelector = true
|
||||||
|
return b.buildNextCharIfExists(buf, cursor+2)
|
||||||
|
case '"':
|
||||||
|
if sel != DoubleQuotePathSelector {
|
||||||
|
return 0, errors.ErrInvalidPath("found single quote character in field selector with double quote context")
|
||||||
|
}
|
||||||
|
selector := buf[:cursor]
|
||||||
|
b.addSelectorNode(string(selector))
|
||||||
|
b.doubleQuotePathSelector = true
|
||||||
|
return b.buildNextCharIfExists(buf, cursor+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, errors.ErrInvalidPath("couldn't find quote character in selector quote path context")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) buildPathRecursive(buf []rune) (int, error) {
|
||||||
|
switch buf[0] {
|
||||||
|
case '.', '[', ']', '$', '*':
|
||||||
|
return 0, errors.ErrInvalidPath("found invalid path character %c after double dot", buf[0])
|
||||||
|
}
|
||||||
|
for cursor := 0; cursor < len(buf); cursor++ {
|
||||||
|
switch buf[cursor] {
|
||||||
|
case '$', '*', ']':
|
||||||
|
return 0, errors.ErrInvalidPath("found %c character in field selector context", buf[cursor])
|
||||||
|
case '.':
|
||||||
|
if cursor+1 >= len(buf) {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with dot character")
|
||||||
|
}
|
||||||
|
selector := buf[:cursor]
|
||||||
|
b.addRecursiveNode(string(selector))
|
||||||
|
offset, err := b.buildSelector(buf[cursor+1:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return cursor + 1 + offset, nil
|
||||||
|
case '[':
|
||||||
|
if cursor+1 >= len(buf) {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with left bracket character")
|
||||||
|
}
|
||||||
|
selector := buf[:cursor]
|
||||||
|
b.addRecursiveNode(string(selector))
|
||||||
|
offset, err := b.buildIndex(buf[cursor+1:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return cursor + 1 + offset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.addRecursiveNode(string(buf))
|
||||||
|
return len(buf), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) buildIndex(buf []rune) (int, error) {
|
||||||
|
switch buf[0] {
|
||||||
|
case '.', '[', ']', '$':
|
||||||
|
return 0, errors.ErrInvalidPath("found invalid path character %c after left bracket", buf[0])
|
||||||
|
case '\'':
|
||||||
|
if len(buf) == 1 {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with single quote character")
|
||||||
|
}
|
||||||
|
offset, err := b.buildQuoteSelector(buf[1:], SingleQuotePathSelector)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return 1 + offset, nil
|
||||||
|
case '*':
|
||||||
|
if len(buf) == 1 {
|
||||||
|
return 0, errors.ErrInvalidPath("JSON Path ends with star character")
|
||||||
|
}
|
||||||
|
if buf[1] != ']' {
|
||||||
|
return 0, errors.ErrInvalidPath("expect right bracket character for index all path but found %c character", buf[1])
|
||||||
|
}
|
||||||
|
b.addIndexAllNode()
|
||||||
|
offset := len("*]")
|
||||||
|
if len(buf) > 2 {
|
||||||
|
buildOffset, err := b.buildNext(buf[2:])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return offset + buildOffset, nil
|
||||||
|
}
|
||||||
|
return offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for cursor := 0; cursor < len(buf); cursor++ {
|
||||||
|
switch buf[cursor] {
|
||||||
|
case ']':
|
||||||
|
index, err := strconv.ParseInt(string(buf[:cursor]), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.ErrInvalidPath("%q is unexpected index path", buf[:cursor])
|
||||||
|
}
|
||||||
|
b.addIndexNode(int(index))
|
||||||
|
return b.buildNextCharIfExists(buf, cursor+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, errors.ErrInvalidPath("couldn't find right bracket character in index path context")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) addIndexAllNode() {
|
||||||
|
node := newPathIndexAllNode()
|
||||||
|
if b.root == nil {
|
||||||
|
b.root = node
|
||||||
|
b.node = node
|
||||||
|
} else {
|
||||||
|
b.node = b.node.chain(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) addRecursiveNode(selector string) {
|
||||||
|
node := newPathRecursiveNode(selector)
|
||||||
|
if b.root == nil {
|
||||||
|
b.root = node
|
||||||
|
b.node = node
|
||||||
|
} else {
|
||||||
|
b.node = b.node.chain(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) addSelectorNode(name string) {
|
||||||
|
node := newPathSelectorNode(name)
|
||||||
|
if b.root == nil {
|
||||||
|
b.root = node
|
||||||
|
b.node = node
|
||||||
|
} else {
|
||||||
|
b.node = b.node.chain(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *PathBuilder) addIndexNode(idx int) {
|
||||||
|
node := newPathIndexNode(idx)
|
||||||
|
if b.root == nil {
|
||||||
|
b.root = node
|
||||||
|
b.node = node
|
||||||
|
} else {
|
||||||
|
b.node = b.node.chain(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type QuotePathSelector int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SingleQuotePathSelector QuotePathSelector = 1
|
||||||
|
DoubleQuotePathSelector QuotePathSelector = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type Path struct {
|
||||||
|
node PathNode
|
||||||
|
RootSelectorOnly bool
|
||||||
|
SingleQuotePathSelector bool
|
||||||
|
DoubleQuotePathSelector bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) Field(sel string) (PathNode, bool, error) {
|
||||||
|
if p.node == nil {
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
|
return p.node.Field(sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) Get(src, dst reflect.Value) error {
|
||||||
|
if p.node == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return p.node.Get(src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) String() string {
|
||||||
|
if p.node == nil {
|
||||||
|
return "$"
|
||||||
|
}
|
||||||
|
return p.node.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathNode interface {
|
||||||
|
fmt.Stringer
|
||||||
|
Index(idx int) (PathNode, bool, error)
|
||||||
|
Field(fieldName string) (PathNode, bool, error)
|
||||||
|
Get(src, dst reflect.Value) error
|
||||||
|
chain(PathNode) PathNode
|
||||||
|
target() bool
|
||||||
|
single() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasePathNode struct {
|
||||||
|
child PathNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *BasePathNode) chain(node PathNode) PathNode {
|
||||||
|
n.child = node
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *BasePathNode) target() bool {
|
||||||
|
return n.child == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *BasePathNode) single() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathSelectorNode struct {
|
||||||
|
*BasePathNode
|
||||||
|
selector string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPathSelectorNode(selector string) *PathSelectorNode {
|
||||||
|
return &PathSelectorNode{
|
||||||
|
BasePathNode: &BasePathNode{},
|
||||||
|
selector: selector,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathSelectorNode) Index(idx int) (PathNode, bool, error) {
|
||||||
|
return nil, false, &errors.PathError{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathSelectorNode) Field(fieldName string) (PathNode, bool, error) {
|
||||||
|
if n.selector == fieldName {
|
||||||
|
return n.child, true, nil
|
||||||
|
}
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathSelectorNode) Get(src, dst reflect.Value) error {
|
||||||
|
switch src.Type().Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
iter := src.MapRange()
|
||||||
|
for iter.Next() {
|
||||||
|
key, ok := iter.Key().Interface().(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid map key type %T", src.Type().Key())
|
||||||
|
}
|
||||||
|
child, found, err := n.Field(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
if child != nil {
|
||||||
|
return child.Get(iter.Value(), dst)
|
||||||
|
}
|
||||||
|
return AssignValue(iter.Value(), dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
typ := src.Type()
|
||||||
|
for i := 0; i < typ.Len(); i++ {
|
||||||
|
tag := runtime.StructTagFromField(typ.Field(i))
|
||||||
|
child, found, err := n.Field(tag.Key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
if child != nil {
|
||||||
|
return child.Get(src.Field(i), dst)
|
||||||
|
}
|
||||||
|
return AssignValue(src.Field(i), dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Ptr:
|
||||||
|
return n.Get(src.Elem(), dst)
|
||||||
|
case reflect.Interface:
|
||||||
|
return n.Get(reflect.ValueOf(src.Interface()), dst)
|
||||||
|
case reflect.Float64, reflect.String, reflect.Bool:
|
||||||
|
return AssignValue(src, dst)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to get %s value from %s", n.selector, src.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathSelectorNode) String() string {
|
||||||
|
s := fmt.Sprintf(".%s", n.selector)
|
||||||
|
if n.child != nil {
|
||||||
|
s += n.child.String()
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathIndexNode struct {
|
||||||
|
*BasePathNode
|
||||||
|
selector int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPathIndexNode(selector int) *PathIndexNode {
|
||||||
|
return &PathIndexNode{
|
||||||
|
BasePathNode: &BasePathNode{},
|
||||||
|
selector: selector,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathIndexNode) Index(idx int) (PathNode, bool, error) {
|
||||||
|
if n.selector == idx {
|
||||||
|
return n.child, true, nil
|
||||||
|
}
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathIndexNode) Field(fieldName string) (PathNode, bool, error) {
|
||||||
|
return nil, false, &errors.PathError{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathIndexNode) Get(src, dst reflect.Value) error {
|
||||||
|
switch src.Type().Kind() {
|
||||||
|
case reflect.Array, reflect.Slice:
|
||||||
|
if src.Len() > n.selector {
|
||||||
|
if n.child != nil {
|
||||||
|
return n.child.Get(src.Index(n.selector), dst)
|
||||||
|
}
|
||||||
|
return AssignValue(src.Index(n.selector), dst)
|
||||||
|
}
|
||||||
|
case reflect.Ptr:
|
||||||
|
return n.Get(src.Elem(), dst)
|
||||||
|
case reflect.Interface:
|
||||||
|
return n.Get(reflect.ValueOf(src.Interface()), dst)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to get [%d] value from %s", n.selector, src.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathIndexNode) String() string {
|
||||||
|
s := fmt.Sprintf("[%d]", n.selector)
|
||||||
|
if n.child != nil {
|
||||||
|
s += n.child.String()
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathIndexAllNode struct {
|
||||||
|
*BasePathNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPathIndexAllNode() *PathIndexAllNode {
|
||||||
|
return &PathIndexAllNode{
|
||||||
|
BasePathNode: &BasePathNode{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathIndexAllNode) Index(idx int) (PathNode, bool, error) {
|
||||||
|
return n.child, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathIndexAllNode) Field(fieldName string) (PathNode, bool, error) {
|
||||||
|
return nil, false, &errors.PathError{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathIndexAllNode) Get(src, dst reflect.Value) error {
|
||||||
|
switch src.Type().Kind() {
|
||||||
|
case reflect.Array, reflect.Slice:
|
||||||
|
var arr []interface{}
|
||||||
|
for i := 0; i < src.Len(); i++ {
|
||||||
|
var v interface{}
|
||||||
|
rv := reflect.ValueOf(&v)
|
||||||
|
if n.child != nil {
|
||||||
|
if err := n.child.Get(src.Index(i), rv); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := AssignValue(src.Index(i), rv); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr = append(arr, v)
|
||||||
|
}
|
||||||
|
if err := AssignValue(reflect.ValueOf(arr), dst); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case reflect.Ptr:
|
||||||
|
return n.Get(src.Elem(), dst)
|
||||||
|
case reflect.Interface:
|
||||||
|
return n.Get(reflect.ValueOf(src.Interface()), dst)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to get all value from %s", src.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathIndexAllNode) String() string {
|
||||||
|
s := "[*]"
|
||||||
|
if n.child != nil {
|
||||||
|
s += n.child.String()
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathRecursiveNode struct {
|
||||||
|
*BasePathNode
|
||||||
|
selector string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPathRecursiveNode(selector string) *PathRecursiveNode {
|
||||||
|
node := newPathSelectorNode(selector)
|
||||||
|
return &PathRecursiveNode{
|
||||||
|
BasePathNode: &BasePathNode{
|
||||||
|
child: node,
|
||||||
|
},
|
||||||
|
selector: selector,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathRecursiveNode) Field(fieldName string) (PathNode, bool, error) {
|
||||||
|
if n.selector == fieldName {
|
||||||
|
return n.child, true, nil
|
||||||
|
}
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathRecursiveNode) Index(_ int) (PathNode, bool, error) {
|
||||||
|
return n, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func valueToSliceValue(v interface{}) []interface{} {
|
||||||
|
rv := reflect.ValueOf(v)
|
||||||
|
ret := []interface{}{}
|
||||||
|
if rv.Type().Kind() == reflect.Slice || rv.Type().Kind() == reflect.Array {
|
||||||
|
for i := 0; i < rv.Len(); i++ {
|
||||||
|
ret = append(ret, rv.Index(i).Interface())
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
return []interface{}{v}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathRecursiveNode) Get(src, dst reflect.Value) error {
|
||||||
|
if n.child == nil {
|
||||||
|
return fmt.Errorf("failed to get by recursive path ..%s", n.selector)
|
||||||
|
}
|
||||||
|
var arr []interface{}
|
||||||
|
switch src.Type().Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
iter := src.MapRange()
|
||||||
|
for iter.Next() {
|
||||||
|
key, ok := iter.Key().Interface().(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("invalid map key type %T", src.Type().Key())
|
||||||
|
}
|
||||||
|
child, found, err := n.Field(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
var v interface{}
|
||||||
|
rv := reflect.ValueOf(&v)
|
||||||
|
_ = child.Get(iter.Value(), rv)
|
||||||
|
arr = append(arr, valueToSliceValue(v)...)
|
||||||
|
} else {
|
||||||
|
var v interface{}
|
||||||
|
rv := reflect.ValueOf(&v)
|
||||||
|
_ = n.Get(iter.Value(), rv)
|
||||||
|
if v != nil {
|
||||||
|
arr = append(arr, valueToSliceValue(v)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = AssignValue(reflect.ValueOf(arr), dst)
|
||||||
|
return nil
|
||||||
|
case reflect.Struct:
|
||||||
|
typ := src.Type()
|
||||||
|
for i := 0; i < typ.Len(); i++ {
|
||||||
|
tag := runtime.StructTagFromField(typ.Field(i))
|
||||||
|
child, found, err := n.Field(tag.Key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
var v interface{}
|
||||||
|
rv := reflect.ValueOf(&v)
|
||||||
|
_ = child.Get(src.Field(i), rv)
|
||||||
|
arr = append(arr, valueToSliceValue(v)...)
|
||||||
|
} else {
|
||||||
|
var v interface{}
|
||||||
|
rv := reflect.ValueOf(&v)
|
||||||
|
_ = n.Get(src.Field(i), rv)
|
||||||
|
if v != nil {
|
||||||
|
arr = append(arr, valueToSliceValue(v)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = AssignValue(reflect.ValueOf(arr), dst)
|
||||||
|
return nil
|
||||||
|
case reflect.Array, reflect.Slice:
|
||||||
|
for i := 0; i < src.Len(); i++ {
|
||||||
|
var v interface{}
|
||||||
|
rv := reflect.ValueOf(&v)
|
||||||
|
_ = n.Get(src.Index(i), rv)
|
||||||
|
if v != nil {
|
||||||
|
arr = append(arr, valueToSliceValue(v)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = AssignValue(reflect.ValueOf(arr), dst)
|
||||||
|
return nil
|
||||||
|
case reflect.Ptr:
|
||||||
|
return n.Get(src.Elem(), dst)
|
||||||
|
case reflect.Interface:
|
||||||
|
return n.Get(reflect.ValueOf(src.Interface()), dst)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to get %s value from %s", n.selector, src.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *PathRecursiveNode) String() string {
|
||||||
|
s := fmt.Sprintf("..%s", n.selector)
|
||||||
|
if n.child != nil {
|
||||||
|
s += n.child.String()
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
9
vendor/github.com/goccy/go-json/internal/decoder/ptr.go
generated
vendored
9
vendor/github.com/goccy/go-json/internal/decoder/ptr.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package decoder
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/runtime"
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
@ -34,6 +35,10 @@ func (d *ptrDecoder) contentDecoder() Decoder {
|
|||||||
//go:linkname unsafe_New reflect.unsafe_New
|
//go:linkname unsafe_New reflect.unsafe_New
|
||||||
func unsafe_New(*runtime.Type) unsafe.Pointer
|
func unsafe_New(*runtime.Type) unsafe.Pointer
|
||||||
|
|
||||||
|
func UnsafeNew(t *runtime.Type) unsafe.Pointer {
|
||||||
|
return unsafe_New(t)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
|
||||||
if s.skipWhiteSpace() == nul {
|
if s.skipWhiteSpace() == nul {
|
||||||
s.read()
|
s.read()
|
||||||
@ -85,3 +90,7 @@ func (d *ptrDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.P
|
|||||||
cursor = c
|
cursor = c
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *ptrDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: ptr decoder does not support decode path")
|
||||||
|
}
|
||||||
|
79
vendor/github.com/goccy/go-json/internal/decoder/slice.go
generated
vendored
79
vendor/github.com/goccy/go-json/internal/decoder/slice.go
generated
vendored
@ -299,3 +299,82 @@ func (d *sliceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *sliceDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
buf := ctx.Buf
|
||||||
|
depth++
|
||||||
|
if depth > maxDecodeNestingDepth {
|
||||||
|
return nil, 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := [][]byte{}
|
||||||
|
for {
|
||||||
|
switch buf[cursor] {
|
||||||
|
case ' ', '\n', '\t', '\r':
|
||||||
|
cursor++
|
||||||
|
continue
|
||||||
|
case 'n':
|
||||||
|
if err := validateNull(buf, cursor); err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
cursor += 4
|
||||||
|
return [][]byte{nullbytes}, cursor, nil
|
||||||
|
case '[':
|
||||||
|
cursor++
|
||||||
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
|
if buf[cursor] == ']' {
|
||||||
|
cursor++
|
||||||
|
return ret, cursor, nil
|
||||||
|
}
|
||||||
|
idx := 0
|
||||||
|
for {
|
||||||
|
child, found, err := ctx.Option.Path.node.Index(idx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
if child != nil {
|
||||||
|
oldPath := ctx.Option.Path.node
|
||||||
|
ctx.Option.Path.node = child
|
||||||
|
paths, c, err := d.valueDecoder.DecodePath(ctx, cursor, depth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
ctx.Option.Path.node = oldPath
|
||||||
|
ret = append(ret, paths...)
|
||||||
|
cursor = c
|
||||||
|
} else {
|
||||||
|
start := cursor
|
||||||
|
end, err := skipValue(buf, cursor, depth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
ret = append(ret, buf[start:end])
|
||||||
|
cursor = end
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c, err := skipValue(buf, cursor, depth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
cursor = c
|
||||||
|
}
|
||||||
|
cursor = skipWhiteSpace(buf, cursor)
|
||||||
|
switch buf[cursor] {
|
||||||
|
case ']':
|
||||||
|
cursor++
|
||||||
|
return ret, cursor, nil
|
||||||
|
case ',':
|
||||||
|
idx++
|
||||||
|
default:
|
||||||
|
return nil, 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor)
|
||||||
|
}
|
||||||
|
cursor++
|
||||||
|
}
|
||||||
|
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
|
return nil, 0, d.errNumber(cursor)
|
||||||
|
default:
|
||||||
|
return nil, 0, errors.ErrUnexpectedEndOfJSON("slice", cursor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
6
vendor/github.com/goccy/go-json/internal/decoder/stream.go
generated
vendored
6
vendor/github.com/goccy/go-json/internal/decoder/stream.go
generated
vendored
@ -280,7 +280,7 @@ func (s *Stream) skipObject(depth int64) error {
|
|||||||
if char(p, cursor) == nul {
|
if char(p, cursor) == nul {
|
||||||
s.cursor = cursor
|
s.cursor = cursor
|
||||||
if s.read() {
|
if s.read() {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
@ -343,7 +343,7 @@ func (s *Stream) skipArray(depth int64) error {
|
|||||||
if char(p, cursor) == nul {
|
if char(p, cursor) == nul {
|
||||||
s.cursor = cursor
|
s.cursor = cursor
|
||||||
if s.read() {
|
if s.read() {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
|
||||||
@ -401,7 +401,7 @@ func (s *Stream) skipValue(depth int64) error {
|
|||||||
if char(p, cursor) == nul {
|
if char(p, cursor) == nul {
|
||||||
s.cursor = cursor
|
s.cursor = cursor
|
||||||
if s.read() {
|
if s.read() {
|
||||||
_, cursor, p = s.statForRetry()
|
_, cursor, p = s.stat()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
|
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
|
||||||
|
12
vendor/github.com/goccy/go-json/internal/decoder/string.go
generated
vendored
12
vendor/github.com/goccy/go-json/internal/decoder/string.go
generated
vendored
@ -60,6 +60,17 @@ func (d *stringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsaf
|
|||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *stringDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
bytes, c, err := d.decodeByte(ctx.Buf, cursor)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
if bytes == nil {
|
||||||
|
return [][]byte{nullbytes}, c, nil
|
||||||
|
}
|
||||||
|
return [][]byte{bytes}, c, nil
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hexToInt = [256]int{
|
hexToInt = [256]int{
|
||||||
'0': 0,
|
'0': 0,
|
||||||
@ -171,6 +182,7 @@ RETRY:
|
|||||||
if !s.read() {
|
if !s.read() {
|
||||||
return nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
return nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
|
||||||
}
|
}
|
||||||
|
p = s.bufptr()
|
||||||
goto RETRY
|
goto RETRY
|
||||||
default:
|
default:
|
||||||
return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
|
||||||
|
4
vendor/github.com/goccy/go-json/internal/decoder/struct.go
generated
vendored
4
vendor/github.com/goccy/go-json/internal/decoder/struct.go
generated
vendored
@ -817,3 +817,7 @@ func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsaf
|
|||||||
cursor++
|
cursor++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *structDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: struct decoder does not support decode path")
|
||||||
|
}
|
||||||
|
1
vendor/github.com/goccy/go-json/internal/decoder/type.go
generated
vendored
1
vendor/github.com/goccy/go-json/internal/decoder/type.go
generated
vendored
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
type Decoder interface {
|
type Decoder interface {
|
||||||
Decode(*RuntimeContext, int64, int64, unsafe.Pointer) (int64, error)
|
Decode(*RuntimeContext, int64, int64, unsafe.Pointer) (int64, error)
|
||||||
|
DecodePath(*RuntimeContext, int64, int64) ([][]byte, int64, error)
|
||||||
DecodeStream(*Stream, int64, unsafe.Pointer) error
|
DecodeStream(*Stream, int64, unsafe.Pointer) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
vendor/github.com/goccy/go-json/internal/decoder/uint.go
generated
vendored
4
vendor/github.com/goccy/go-json/internal/decoder/uint.go
generated
vendored
@ -188,3 +188,7 @@ func (d *uintDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.
|
|||||||
d.op(p, u64)
|
d.op(p, u64)
|
||||||
return cursor, nil
|
return cursor, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *uintDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: uint decoder does not support decode path")
|
||||||
|
}
|
||||||
|
5
vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go
generated
vendored
5
vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go
generated
vendored
@ -3,6 +3,7 @@ package decoder
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/errors"
|
"github.com/goccy/go-json/internal/errors"
|
||||||
@ -97,3 +98,7 @@ func (d *unmarshalJSONDecoder) Decode(ctx *RuntimeContext, cursor, depth int64,
|
|||||||
}
|
}
|
||||||
return end, nil
|
return end, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *unmarshalJSONDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: unmarshal json decoder does not support decode path")
|
||||||
|
}
|
||||||
|
5
vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go
generated
vendored
5
vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go
generated
vendored
@ -3,6 +3,7 @@ package decoder
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding"
|
"encoding"
|
||||||
|
"fmt"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
@ -142,6 +143,10 @@ func (d *unmarshalTextDecoder) Decode(ctx *RuntimeContext, cursor, depth int64,
|
|||||||
return end, nil
|
return end, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *unmarshalTextDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: unmarshal text decoder does not support decode path")
|
||||||
|
}
|
||||||
|
|
||||||
func unquoteBytes(s []byte) (t []byte, ok bool) {
|
func unquoteBytes(s []byte) (t []byte, ok bool) {
|
||||||
length := len(s)
|
length := len(s)
|
||||||
if length < 2 || s[0] != '"' || s[length-1] != '"' {
|
if length < 2 || s[0] != '"' || s[length-1] != '"' {
|
||||||
|
5
vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go
generated
vendored
5
vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package decoder
|
package decoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@ -66,3 +67,7 @@ func (d *wrappedStringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64,
|
|||||||
ctx.Buf = oldBuf
|
ctx.Buf = oldBuf
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *wrappedStringDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) {
|
||||||
|
return nil, 0, fmt.Errorf("json: wrapped string decoder does not support decode path")
|
||||||
|
}
|
||||||
|
2
vendor/github.com/goccy/go-json/internal/encoder/compiler.go
generated
vendored
2
vendor/github.com/goccy/go-json/internal/encoder/compiler.go
generated
vendored
@ -506,8 +506,6 @@ func (c *Compiler) listElemCode(typ *runtime.Type) (Code, error) {
|
|||||||
|
|
||||||
func (c *Compiler) mapKeyCode(typ *runtime.Type) (Code, error) {
|
func (c *Compiler) mapKeyCode(typ *runtime.Type) (Code, error) {
|
||||||
switch {
|
switch {
|
||||||
case c.implementsMarshalJSON(typ):
|
|
||||||
return c.marshalJSONCode(typ)
|
|
||||||
case c.implementsMarshalText(typ):
|
case c.implementsMarshalText(typ):
|
||||||
return c.marshalTextCode(typ)
|
return c.marshalTextCode(typ)
|
||||||
}
|
}
|
||||||
|
19
vendor/github.com/goccy/go-json/internal/errors/error.go
generated
vendored
19
vendor/github.com/goccy/go-json/internal/errors/error.go
generated
vendored
@ -162,3 +162,22 @@ func ErrInvalidBeginningOfValue(c byte, cursor int64) *SyntaxError {
|
|||||||
Offset: cursor,
|
Offset: cursor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PathError struct {
|
||||||
|
msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *PathError) Error() string {
|
||||||
|
return fmt.Sprintf("json: invalid path format: %s", e.msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ErrInvalidPath(msg string, args ...interface{}) *PathError {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return &PathError{msg: fmt.Sprintf(msg, args...)}
|
||||||
|
}
|
||||||
|
return &PathError{msg: msg}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ErrEmptyPath() *PathError {
|
||||||
|
return &PathError{msg: "path is empty"}
|
||||||
|
}
|
||||||
|
84
vendor/github.com/goccy/go-json/path.go
generated
vendored
Normal file
84
vendor/github.com/goccy/go-json/path.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package json
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/goccy/go-json/internal/decoder"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreatePath creates JSON Path.
|
||||||
|
//
|
||||||
|
// JSON Path rule
|
||||||
|
// $ : root object or element. The JSON Path format must start with this operator, which refers to the outermost level of the JSON-formatted string.
|
||||||
|
// . : child operator. You can identify child values using dot-notation.
|
||||||
|
// .. : recursive descent.
|
||||||
|
// [] : subscript operator. If the JSON object is an array, you can use brackets to specify the array index.
|
||||||
|
// [*] : all objects/elements for array.
|
||||||
|
//
|
||||||
|
// Reserved words must be properly escaped when included in Path.
|
||||||
|
//
|
||||||
|
// Escape Rule
|
||||||
|
// single quote style escape: e.g.) `$['a.b'].c`
|
||||||
|
// double quote style escape: e.g.) `$."a.b".c`
|
||||||
|
func CreatePath(p string) (*Path, error) {
|
||||||
|
path, err := decoder.PathString(p).Build()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Path{path: path}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path represents JSON Path.
|
||||||
|
type Path struct {
|
||||||
|
path *decoder.Path
|
||||||
|
}
|
||||||
|
|
||||||
|
// RootSelectorOnly whether only the root selector ($) is used.
|
||||||
|
func (p *Path) RootSelectorOnly() bool {
|
||||||
|
return p.path.RootSelectorOnly
|
||||||
|
}
|
||||||
|
|
||||||
|
// UsedSingleQuotePathSelector whether single quote-based escaping was done when building the JSON Path.
|
||||||
|
func (p *Path) UsedSingleQuotePathSelector() bool {
|
||||||
|
return p.path.SingleQuotePathSelector
|
||||||
|
}
|
||||||
|
|
||||||
|
// UsedSingleQuotePathSelector whether double quote-based escaping was done when building the JSON Path.
|
||||||
|
func (p *Path) UsedDoubleQuotePathSelector() bool {
|
||||||
|
return p.path.DoubleQuotePathSelector
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract extracts a specific JSON string.
|
||||||
|
func (p *Path) Extract(data []byte, optFuncs ...DecodeOptionFunc) ([][]byte, error) {
|
||||||
|
return extractFromPath(p, data, optFuncs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PathString returns original JSON Path string.
|
||||||
|
func (p *Path) PathString() string {
|
||||||
|
return p.path.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal extract and decode the value of the part corresponding to JSON Path from the input data.
|
||||||
|
func (p *Path) Unmarshal(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
|
||||||
|
contents, err := extractFromPath(p, data, optFuncs...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
results := make([]interface{}, 0, len(contents))
|
||||||
|
for _, content := range contents {
|
||||||
|
var result interface{}
|
||||||
|
if err := Unmarshal(content, &result); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
results = append(results, result)
|
||||||
|
}
|
||||||
|
if err := decoder.AssignValue(reflect.ValueOf(results), reflect.ValueOf(v)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get extract and substitute the value of the part corresponding to JSON Path from the input value.
|
||||||
|
func (p *Path) Get(src, dst interface{}) error {
|
||||||
|
return p.path.Get(reflect.ValueOf(src), reflect.ValueOf(dst))
|
||||||
|
}
|
94
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
94
vendor/github.com/labstack/echo/v4/CHANGELOG.md
generated
vendored
@ -1,5 +1,99 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v4.10.0 - 2022-12-27
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
|
||||||
|
* We are deprecating JWT middleware in this repository. Please use https://github.com/labstack/echo-jwt instead.
|
||||||
|
|
||||||
|
JWT middleware is moved to separate repository to allow us to bump/upgrade version of JWT implementation (`github.com/golang-jwt/jwt`) we are using
|
||||||
|
which we can not do in Echo core because this would break backwards compatibility guarantees we try to maintain.
|
||||||
|
|
||||||
|
* This minor version bumps minimum Go version to 1.17 (from 1.16) due `golang.org/x/` packages we depend on. There are
|
||||||
|
several vulnerabilities fixed in these libraries.
|
||||||
|
|
||||||
|
Echo still tries to support last 4 Go versions but there are occasions we can not guarantee this promise.
|
||||||
|
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Bump x/text to 0.3.8 [#2305](https://github.com/labstack/echo/pull/2305)
|
||||||
|
* Bump dependencies and add notes about Go releases we support [#2336](https://github.com/labstack/echo/pull/2336)
|
||||||
|
* Add helper interface for ProxyBalancer interface [#2316](https://github.com/labstack/echo/pull/2316)
|
||||||
|
* Expose `middleware.CreateExtractors` function so we can use it from echo-contrib repository [#2338](https://github.com/labstack/echo/pull/2338)
|
||||||
|
* Refactor func(Context) error to HandlerFunc [#2315](https://github.com/labstack/echo/pull/2315)
|
||||||
|
* Improve function comments [#2329](https://github.com/labstack/echo/pull/2329)
|
||||||
|
* Add new method HTTPError.WithInternal [#2340](https://github.com/labstack/echo/pull/2340)
|
||||||
|
* Replace io/ioutil package usages [#2342](https://github.com/labstack/echo/pull/2342)
|
||||||
|
* Add staticcheck to CI flow [#2343](https://github.com/labstack/echo/pull/2343)
|
||||||
|
* Replace relative path determination from proprietary to std [#2345](https://github.com/labstack/echo/pull/2345)
|
||||||
|
* Remove square brackets from ipv6 addresses in XFF (X-Forwarded-For header) [#2182](https://github.com/labstack/echo/pull/2182)
|
||||||
|
* Add testcases for some BodyLimit middleware configuration options [#2350](https://github.com/labstack/echo/pull/2350)
|
||||||
|
* Additional configuration options for RequestLogger and Logger middleware [#2341](https://github.com/labstack/echo/pull/2341)
|
||||||
|
* Add route to request log [#2162](https://github.com/labstack/echo/pull/2162)
|
||||||
|
* GitHub Workflows security hardening [#2358](https://github.com/labstack/echo/pull/2358)
|
||||||
|
* Add govulncheck to CI and bump dependencies [#2362](https://github.com/labstack/echo/pull/2362)
|
||||||
|
* Fix rate limiter docs [#2366](https://github.com/labstack/echo/pull/2366)
|
||||||
|
* Refactor how `e.Routes()` work and introduce `e.OnAddRouteHandler` callback [#2337](https://github.com/labstack/echo/pull/2337)
|
||||||
|
|
||||||
|
|
||||||
|
## v4.9.1 - 2022-10-12
|
||||||
|
|
||||||
|
**Fixes**
|
||||||
|
|
||||||
|
* Fix logger panicing (when template is set to empty) by bumping dependency version [#2295](https://github.com/labstack/echo/issues/2295)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Improve CORS documentation [#2272](https://github.com/labstack/echo/pull/2272)
|
||||||
|
* Update readme about supported Go versions [#2291](https://github.com/labstack/echo/pull/2291)
|
||||||
|
* Tests: improve error handling on closing body [#2254](https://github.com/labstack/echo/pull/2254)
|
||||||
|
* Tests: refactor some of the assertions in tests [#2275](https://github.com/labstack/echo/pull/2275)
|
||||||
|
* Tests: refactor assertions [#2301](https://github.com/labstack/echo/pull/2301)
|
||||||
|
|
||||||
|
## v4.9.0 - 2022-09-04
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
|
||||||
|
* Fix open redirect vulnerability in handlers serving static directories (e.Static, e.StaticFs, echo.StaticDirectoryHandler) [#2260](https://github.com/labstack/echo/pull/2260)
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Allow configuring ErrorHandler in CSRF middleware [#2257](https://github.com/labstack/echo/pull/2257)
|
||||||
|
* Replace HTTP method constants in tests with stdlib constants [#2247](https://github.com/labstack/echo/pull/2247)
|
||||||
|
|
||||||
|
|
||||||
|
## v4.8.0 - 2022-08-10
|
||||||
|
|
||||||
|
**Most notable things**
|
||||||
|
|
||||||
|
You can now add any arbitrary HTTP method type as a route [#2237](https://github.com/labstack/echo/pull/2237)
|
||||||
|
```go
|
||||||
|
e.Add("COPY", "/*", func(c echo.Context) error
|
||||||
|
return c.String(http.StatusOK, "OK COPY")
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
You can add custom 404 handler for specific paths [#2217](https://github.com/labstack/echo/pull/2217)
|
||||||
|
```go
|
||||||
|
e.RouteNotFound("/*", func(c echo.Context) error { return c.NoContent(http.StatusNotFound) })
|
||||||
|
|
||||||
|
g := e.Group("/images")
|
||||||
|
g.RouteNotFound("/*", func(c echo.Context) error { return c.NoContent(http.StatusNotFound) })
|
||||||
|
```
|
||||||
|
|
||||||
|
**Enhancements**
|
||||||
|
|
||||||
|
* Add new value binding methods (UnixTimeMilli,TextUnmarshaler,JSONUnmarshaler) to Valuebinder [#2127](https://github.com/labstack/echo/pull/2127)
|
||||||
|
* Refactor: body_limit middleware unit test [#2145](https://github.com/labstack/echo/pull/2145)
|
||||||
|
* Refactor: Timeout mw: rework how test waits for timeout. [#2187](https://github.com/labstack/echo/pull/2187)
|
||||||
|
* BasicAuth middleware returns 500 InternalServerError on invalid base64 strings but should return 400 [#2191](https://github.com/labstack/echo/pull/2191)
|
||||||
|
* Refactor: duplicated findStaticChild process at findChildWithLabel [#2176](https://github.com/labstack/echo/pull/2176)
|
||||||
|
* Allow different param names in different methods with same path scheme [#2209](https://github.com/labstack/echo/pull/2209)
|
||||||
|
* Add support for registering handlers for different 404 routes [#2217](https://github.com/labstack/echo/pull/2217)
|
||||||
|
* Middlewares should use errors.As() instead of type assertion on HTTPError [#2227](https://github.com/labstack/echo/pull/2227)
|
||||||
|
* Allow arbitrary HTTP method types to be added as routes [#2237](https://github.com/labstack/echo/pull/2237)
|
||||||
|
|
||||||
## v4.7.2 - 2022-03-16
|
## v4.7.2 - 2022-03-16
|
||||||
|
|
||||||
**Fixes**
|
**Fixes**
|
||||||
|
8
vendor/github.com/labstack/echo/v4/Makefile
generated
vendored
8
vendor/github.com/labstack/echo/v4/Makefile
generated
vendored
@ -9,9 +9,11 @@ tag:
|
|||||||
check: lint vet race ## Check project
|
check: lint vet race ## Check project
|
||||||
|
|
||||||
init:
|
init:
|
||||||
@go get -u golang.org/x/lint/golint
|
@go install golang.org/x/lint/golint@latest
|
||||||
|
@go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||||
|
|
||||||
lint: ## Lint the files
|
lint: ## Lint the files
|
||||||
|
@staticcheck ${PKG_LIST}
|
||||||
@golint -set_exit_status ${PKG_LIST}
|
@golint -set_exit_status ${PKG_LIST}
|
||||||
|
|
||||||
vet: ## Vet the files
|
vet: ## Vet the files
|
||||||
@ -29,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.15"
|
goversion ?= "1.17"
|
||||||
test_version: ## Run tests inside Docker with given version (defaults to 1.15 oldest supported). Example: make test_version goversion=1.15
|
test_version: ## Run tests inside Docker with given version (defaults to 1.17 oldest supported). Example: make test_version goversion=1.17
|
||||||
@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"
|
||||||
|
24
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
24
vendor/github.com/labstack/echo/v4/README.md
generated
vendored
@ -11,12 +11,11 @@
|
|||||||
|
|
||||||
## Supported Go versions
|
## Supported Go versions
|
||||||
|
|
||||||
|
Latest version of Echo supports last four Go major [releases](https://go.dev/doc/devel/release) and might work with older versions.
|
||||||
|
|
||||||
As of version 4.0.0, Echo is available as a [Go module](https://github.com/golang/go/wiki/Modules).
|
As of version 4.0.0, Echo is available as a [Go module](https://github.com/golang/go/wiki/Modules).
|
||||||
Therefore a Go version capable of understanding /vN suffixed imports is required:
|
Therefore a Go version capable of understanding /vN suffixed imports is required:
|
||||||
|
|
||||||
- 1.9.7+
|
|
||||||
- 1.10.3+
|
|
||||||
- 1.14+
|
|
||||||
|
|
||||||
Any of these versions will allow you to import Echo as `github.com/labstack/echo/v4` which is the recommended
|
Any of these versions will allow you to import Echo as `github.com/labstack/echo/v4` which is the recommended
|
||||||
way of using Echo going forward.
|
way of using Echo going forward.
|
||||||
@ -93,15 +92,16 @@ func hello(c echo.Context) error {
|
|||||||
|
|
||||||
# Third-party middlewares
|
# Third-party middlewares
|
||||||
|
|
||||||
| Repository | Description |
|
| Repository | Description |
|
||||||
|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| [github.com/labstack/echo-contrib](https://github.com/labstack/echo-contrib) | (by Echo team) [casbin](https://github.com/casbin/casbin), [gorilla/sessions](https://github.com/gorilla/sessions), [jaegertracing](github.com/uber/jaeger-client-go), [prometheus](https://github.com/prometheus/client_golang/), [pprof](https://pkg.go.dev/net/http/pprof), [zipkin](https://github.com/openzipkin/zipkin-go) middlewares |
|
| [github.com/labstack/echo-contrib](https://github.com/labstack/echo-contrib) | (by Echo team) [casbin](https://github.com/casbin/casbin), [gorilla/sessions](https://github.com/gorilla/sessions), [jaegertracing](github.com/uber/jaeger-client-go), [prometheus](https://github.com/prometheus/client_golang/), [pprof](https://pkg.go.dev/net/http/pprof), [zipkin](https://github.com/openzipkin/zipkin-go) middlewares |
|
||||||
| [deepmap/oapi-codegen](https://github.com/deepmap/oapi-codegen) | Automatically generate RESTful API documentation with [OpenAPI](https://swagger.io/specification/) Client and Server Code Generator |
|
| [deepmap/oapi-codegen](https://github.com/deepmap/oapi-codegen) | Automatically generate RESTful API documentation with [OpenAPI](https://swagger.io/specification/) Client and Server Code Generator |
|
||||||
| [github.com/swaggo/echo-swagger](https://github.com/swaggo/echo-swagger) | Automatically generate RESTful API documentation with [Swagger](https://swagger.io/) 2.0. |
|
| [github.com/swaggo/echo-swagger](https://github.com/swaggo/echo-swagger) | Automatically generate RESTful API documentation with [Swagger](https://swagger.io/) 2.0. |
|
||||||
| [github.com/ziflex/lecho](https://github.com/ziflex/lecho) | [Zerolog](https://github.com/rs/zerolog) logging library wrapper for Echo logger interface. |
|
| [github.com/ziflex/lecho](https://github.com/ziflex/lecho) | [Zerolog](https://github.com/rs/zerolog) logging library wrapper for Echo logger interface. |
|
||||||
| [github.com/brpaz/echozap](https://github.com/brpaz/echozap) | Uber´s [Zap](https://github.com/uber-go/zap) logging library wrapper for Echo logger interface. |
|
| [github.com/brpaz/echozap](https://github.com/brpaz/echozap) | Uber´s [Zap](https://github.com/uber-go/zap) logging library wrapper for Echo logger interface. |
|
||||||
| [github.com/darkweak/souin/plugins/echo](https://github.com/darkweak/souin/tree/master/plugins/echo) | HTTP cache system based on [Souin](https://github.com/darkweak/souin) to automatically get your endpoints cached. It supports some distributed and non-distributed storage systems depending your needs. |
|
| [github.com/darkweak/souin/plugins/echo](https://github.com/darkweak/souin/tree/master/plugins/echo) | HTTP cache system based on [Souin](https://github.com/darkweak/souin) to automatically get your endpoints cached. It supports some distributed and non-distributed storage systems depending your needs. |
|
||||||
| [github.com/mikestefanello/pagoda](https://github.com/mikestefanello/pagoda) | Rapid, easy full-stack web development starter kit built with Echo.
|
| [github.com/mikestefanello/pagoda](https://github.com/mikestefanello/pagoda) | Rapid, easy full-stack web development starter kit built with Echo. |
|
||||||
|
| [github.com/go-woo/protoc-gen-echo](https://github.com/go-woo/protoc-gen-echo) | ProtoBuf generate Echo server side code |
|
||||||
|
|
||||||
Please send a PR to add your own library here.
|
Please send a PR to add your own library here.
|
||||||
|
|
||||||
|
197
vendor/github.com/labstack/echo/v4/binder.go
generated
vendored
197
vendor/github.com/labstack/echo/v4/binder.go
generated
vendored
@ -1,6 +1,8 @@
|
|||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -52,8 +54,11 @@ import (
|
|||||||
* time
|
* time
|
||||||
* duration
|
* duration
|
||||||
* BindUnmarshaler() interface
|
* BindUnmarshaler() interface
|
||||||
|
* TextUnmarshaler() interface
|
||||||
|
* JSONUnmarshaler() interface
|
||||||
* UnixTime() - converts unix time (integer) to time.Time
|
* UnixTime() - converts unix time (integer) to time.Time
|
||||||
* UnixTimeNano() - converts unix time with nano second precision (integer) to time.Time
|
* UnixTimeMilli() - converts unix time with millisecond precision (integer) to time.Time
|
||||||
|
* UnixTimeNano() - converts unix time with nanosecond precision (integer) to time.Time
|
||||||
* CustomFunc() - callback function for your custom conversion logic. Signature `func(values []string) []error`
|
* CustomFunc() - callback function for your custom conversion logic. Signature `func(values []string) []error`
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -204,7 +209,7 @@ func (b *ValueBinder) CustomFunc(sourceParam string, customFunc func(values []st
|
|||||||
return b.customFunc(sourceParam, customFunc, false)
|
return b.customFunc(sourceParam, customFunc, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustCustomFunc requires parameter values to exist to be bind with Func. Returns error when value does not exist.
|
// MustCustomFunc requires parameter values to exist to bind with Func. Returns error when value does not exist.
|
||||||
func (b *ValueBinder) MustCustomFunc(sourceParam string, customFunc func(values []string) []error) *ValueBinder {
|
func (b *ValueBinder) MustCustomFunc(sourceParam string, customFunc func(values []string) []error) *ValueBinder {
|
||||||
return b.customFunc(sourceParam, customFunc, true)
|
return b.customFunc(sourceParam, customFunc, true)
|
||||||
}
|
}
|
||||||
@ -241,7 +246,7 @@ func (b *ValueBinder) String(sourceParam string, dest *string) *ValueBinder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustString requires parameter value to exist to be bind to string variable. Returns error when value does not exist
|
// MustString requires parameter value to exist to bind to string variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustString(sourceParam string, dest *string) *ValueBinder {
|
func (b *ValueBinder) MustString(sourceParam string, dest *string) *ValueBinder {
|
||||||
if b.failFast && b.errors != nil {
|
if b.failFast && b.errors != nil {
|
||||||
return b
|
return b
|
||||||
@ -270,7 +275,7 @@ func (b *ValueBinder) Strings(sourceParam string, dest *[]string) *ValueBinder {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustStrings requires parameter values to exist to be bind to slice of string variables. Returns error when value does not exist
|
// MustStrings requires parameter values to exist to bind to slice of string variables. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustStrings(sourceParam string, dest *[]string) *ValueBinder {
|
func (b *ValueBinder) MustStrings(sourceParam string, dest *[]string) *ValueBinder {
|
||||||
if b.failFast && b.errors != nil {
|
if b.failFast && b.errors != nil {
|
||||||
return b
|
return b
|
||||||
@ -302,7 +307,7 @@ func (b *ValueBinder) BindUnmarshaler(sourceParam string, dest BindUnmarshaler)
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustBindUnmarshaler requires parameter value to exist to be bind to destination implementing BindUnmarshaler interface.
|
// MustBindUnmarshaler requires parameter value to exist to bind to destination implementing BindUnmarshaler interface.
|
||||||
// Returns error when value does not exist
|
// Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustBindUnmarshaler(sourceParam string, dest BindUnmarshaler) *ValueBinder {
|
func (b *ValueBinder) MustBindUnmarshaler(sourceParam string, dest BindUnmarshaler) *ValueBinder {
|
||||||
if b.failFast && b.errors != nil {
|
if b.failFast && b.errors != nil {
|
||||||
@ -321,13 +326,85 @@ func (b *ValueBinder) MustBindUnmarshaler(sourceParam string, dest BindUnmarshal
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JSONUnmarshaler binds parameter to destination implementing json.Unmarshaler interface
|
||||||
|
func (b *ValueBinder) JSONUnmarshaler(sourceParam string, dest json.Unmarshaler) *ValueBinder {
|
||||||
|
if b.failFast && b.errors != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := b.ValueFunc(sourceParam)
|
||||||
|
if tmp == "" {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dest.UnmarshalJSON([]byte(tmp)); err != nil {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "failed to bind field value to json.Unmarshaler interface", err))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustJSONUnmarshaler requires parameter value to exist to bind to destination implementing json.Unmarshaler interface.
|
||||||
|
// Returns error when value does not exist
|
||||||
|
func (b *ValueBinder) MustJSONUnmarshaler(sourceParam string, dest json.Unmarshaler) *ValueBinder {
|
||||||
|
if b.failFast && b.errors != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := b.ValueFunc(sourceParam)
|
||||||
|
if tmp == "" {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "required field value is empty", nil))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dest.UnmarshalJSON([]byte(tmp)); err != nil {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "failed to bind field value to json.Unmarshaler interface", err))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextUnmarshaler binds parameter to destination implementing encoding.TextUnmarshaler interface
|
||||||
|
func (b *ValueBinder) TextUnmarshaler(sourceParam string, dest encoding.TextUnmarshaler) *ValueBinder {
|
||||||
|
if b.failFast && b.errors != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := b.ValueFunc(sourceParam)
|
||||||
|
if tmp == "" {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dest.UnmarshalText([]byte(tmp)); err != nil {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "failed to bind field value to encoding.TextUnmarshaler interface", err))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustTextUnmarshaler requires parameter value to exist to bind to destination implementing encoding.TextUnmarshaler interface.
|
||||||
|
// Returns error when value does not exist
|
||||||
|
func (b *ValueBinder) MustTextUnmarshaler(sourceParam string, dest encoding.TextUnmarshaler) *ValueBinder {
|
||||||
|
if b.failFast && b.errors != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := b.ValueFunc(sourceParam)
|
||||||
|
if tmp == "" {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "required field value is empty", nil))
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dest.UnmarshalText([]byte(tmp)); err != nil {
|
||||||
|
b.setError(b.ErrorFunc(sourceParam, []string{tmp}, "failed to bind field value to encoding.TextUnmarshaler interface", err))
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
// BindWithDelimiter binds parameter to destination by suitable conversion function.
|
// BindWithDelimiter binds parameter to destination by suitable conversion function.
|
||||||
// Delimiter is used before conversion to split parameter value to separate values
|
// Delimiter is used before conversion to split parameter value to separate values
|
||||||
func (b *ValueBinder) BindWithDelimiter(sourceParam string, dest interface{}, delimiter string) *ValueBinder {
|
func (b *ValueBinder) BindWithDelimiter(sourceParam string, dest interface{}, delimiter string) *ValueBinder {
|
||||||
return b.bindWithDelimiter(sourceParam, dest, delimiter, false)
|
return b.bindWithDelimiter(sourceParam, dest, delimiter, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustBindWithDelimiter requires parameter value to exist to be bind destination by suitable conversion function.
|
// MustBindWithDelimiter requires parameter value to exist to bind destination by suitable conversion function.
|
||||||
// Delimiter is used before conversion to split parameter value to separate values
|
// Delimiter is used before conversion to split parameter value to separate values
|
||||||
func (b *ValueBinder) MustBindWithDelimiter(sourceParam string, dest interface{}, delimiter string) *ValueBinder {
|
func (b *ValueBinder) MustBindWithDelimiter(sourceParam string, dest interface{}, delimiter string) *ValueBinder {
|
||||||
return b.bindWithDelimiter(sourceParam, dest, delimiter, true)
|
return b.bindWithDelimiter(sourceParam, dest, delimiter, true)
|
||||||
@ -376,7 +453,7 @@ func (b *ValueBinder) Int64(sourceParam string, dest *int64) *ValueBinder {
|
|||||||
return b.intValue(sourceParam, dest, 64, false)
|
return b.intValue(sourceParam, dest, 64, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt64 requires parameter value to exist to be bind to int64 variable. Returns error when value does not exist
|
// MustInt64 requires parameter value to exist to bind to int64 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt64(sourceParam string, dest *int64) *ValueBinder {
|
func (b *ValueBinder) MustInt64(sourceParam string, dest *int64) *ValueBinder {
|
||||||
return b.intValue(sourceParam, dest, 64, true)
|
return b.intValue(sourceParam, dest, 64, true)
|
||||||
}
|
}
|
||||||
@ -386,7 +463,7 @@ func (b *ValueBinder) Int32(sourceParam string, dest *int32) *ValueBinder {
|
|||||||
return b.intValue(sourceParam, dest, 32, false)
|
return b.intValue(sourceParam, dest, 32, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt32 requires parameter value to exist to be bind to int32 variable. Returns error when value does not exist
|
// MustInt32 requires parameter value to exist to bind to int32 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt32(sourceParam string, dest *int32) *ValueBinder {
|
func (b *ValueBinder) MustInt32(sourceParam string, dest *int32) *ValueBinder {
|
||||||
return b.intValue(sourceParam, dest, 32, true)
|
return b.intValue(sourceParam, dest, 32, true)
|
||||||
}
|
}
|
||||||
@ -396,7 +473,7 @@ func (b *ValueBinder) Int16(sourceParam string, dest *int16) *ValueBinder {
|
|||||||
return b.intValue(sourceParam, dest, 16, false)
|
return b.intValue(sourceParam, dest, 16, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt16 requires parameter value to exist to be bind to int16 variable. Returns error when value does not exist
|
// MustInt16 requires parameter value to exist to bind to int16 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt16(sourceParam string, dest *int16) *ValueBinder {
|
func (b *ValueBinder) MustInt16(sourceParam string, dest *int16) *ValueBinder {
|
||||||
return b.intValue(sourceParam, dest, 16, true)
|
return b.intValue(sourceParam, dest, 16, true)
|
||||||
}
|
}
|
||||||
@ -406,7 +483,7 @@ func (b *ValueBinder) Int8(sourceParam string, dest *int8) *ValueBinder {
|
|||||||
return b.intValue(sourceParam, dest, 8, false)
|
return b.intValue(sourceParam, dest, 8, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt8 requires parameter value to exist to be bind to int8 variable. Returns error when value does not exist
|
// MustInt8 requires parameter value to exist to bind to int8 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt8(sourceParam string, dest *int8) *ValueBinder {
|
func (b *ValueBinder) MustInt8(sourceParam string, dest *int8) *ValueBinder {
|
||||||
return b.intValue(sourceParam, dest, 8, true)
|
return b.intValue(sourceParam, dest, 8, true)
|
||||||
}
|
}
|
||||||
@ -416,7 +493,7 @@ func (b *ValueBinder) Int(sourceParam string, dest *int) *ValueBinder {
|
|||||||
return b.intValue(sourceParam, dest, 0, false)
|
return b.intValue(sourceParam, dest, 0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt requires parameter value to exist to be bind to int variable. Returns error when value does not exist
|
// MustInt requires parameter value to exist to bind to int variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt(sourceParam string, dest *int) *ValueBinder {
|
func (b *ValueBinder) MustInt(sourceParam string, dest *int) *ValueBinder {
|
||||||
return b.intValue(sourceParam, dest, 0, true)
|
return b.intValue(sourceParam, dest, 0, true)
|
||||||
}
|
}
|
||||||
@ -544,7 +621,7 @@ func (b *ValueBinder) Int64s(sourceParam string, dest *[]int64) *ValueBinder {
|
|||||||
return b.intsValue(sourceParam, dest, false)
|
return b.intsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt64s requires parameter value to exist to be bind to int64 slice variable. Returns error when value does not exist
|
// MustInt64s requires parameter value to exist to bind to int64 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt64s(sourceParam string, dest *[]int64) *ValueBinder {
|
func (b *ValueBinder) MustInt64s(sourceParam string, dest *[]int64) *ValueBinder {
|
||||||
return b.intsValue(sourceParam, dest, true)
|
return b.intsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -554,7 +631,7 @@ func (b *ValueBinder) Int32s(sourceParam string, dest *[]int32) *ValueBinder {
|
|||||||
return b.intsValue(sourceParam, dest, false)
|
return b.intsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt32s requires parameter value to exist to be bind to int32 slice variable. Returns error when value does not exist
|
// MustInt32s requires parameter value to exist to bind to int32 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt32s(sourceParam string, dest *[]int32) *ValueBinder {
|
func (b *ValueBinder) MustInt32s(sourceParam string, dest *[]int32) *ValueBinder {
|
||||||
return b.intsValue(sourceParam, dest, true)
|
return b.intsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -564,7 +641,7 @@ func (b *ValueBinder) Int16s(sourceParam string, dest *[]int16) *ValueBinder {
|
|||||||
return b.intsValue(sourceParam, dest, false)
|
return b.intsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt16s requires parameter value to exist to be bind to int16 slice variable. Returns error when value does not exist
|
// MustInt16s requires parameter value to exist to bind to int16 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt16s(sourceParam string, dest *[]int16) *ValueBinder {
|
func (b *ValueBinder) MustInt16s(sourceParam string, dest *[]int16) *ValueBinder {
|
||||||
return b.intsValue(sourceParam, dest, true)
|
return b.intsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -574,7 +651,7 @@ func (b *ValueBinder) Int8s(sourceParam string, dest *[]int8) *ValueBinder {
|
|||||||
return b.intsValue(sourceParam, dest, false)
|
return b.intsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInt8s requires parameter value to exist to be bind to int8 slice variable. Returns error when value does not exist
|
// MustInt8s requires parameter value to exist to bind to int8 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInt8s(sourceParam string, dest *[]int8) *ValueBinder {
|
func (b *ValueBinder) MustInt8s(sourceParam string, dest *[]int8) *ValueBinder {
|
||||||
return b.intsValue(sourceParam, dest, true)
|
return b.intsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -584,7 +661,7 @@ func (b *ValueBinder) Ints(sourceParam string, dest *[]int) *ValueBinder {
|
|||||||
return b.intsValue(sourceParam, dest, false)
|
return b.intsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustInts requires parameter value to exist to be bind to int slice variable. Returns error when value does not exist
|
// MustInts requires parameter value to exist to bind to int slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustInts(sourceParam string, dest *[]int) *ValueBinder {
|
func (b *ValueBinder) MustInts(sourceParam string, dest *[]int) *ValueBinder {
|
||||||
return b.intsValue(sourceParam, dest, true)
|
return b.intsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -594,7 +671,7 @@ func (b *ValueBinder) Uint64(sourceParam string, dest *uint64) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 64, false)
|
return b.uintValue(sourceParam, dest, 64, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint64 requires parameter value to exist to be bind to uint64 variable. Returns error when value does not exist
|
// MustUint64 requires parameter value to exist to bind to uint64 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint64(sourceParam string, dest *uint64) *ValueBinder {
|
func (b *ValueBinder) MustUint64(sourceParam string, dest *uint64) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 64, true)
|
return b.uintValue(sourceParam, dest, 64, true)
|
||||||
}
|
}
|
||||||
@ -604,7 +681,7 @@ func (b *ValueBinder) Uint32(sourceParam string, dest *uint32) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 32, false)
|
return b.uintValue(sourceParam, dest, 32, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint32 requires parameter value to exist to be bind to uint32 variable. Returns error when value does not exist
|
// MustUint32 requires parameter value to exist to bind to uint32 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint32(sourceParam string, dest *uint32) *ValueBinder {
|
func (b *ValueBinder) MustUint32(sourceParam string, dest *uint32) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 32, true)
|
return b.uintValue(sourceParam, dest, 32, true)
|
||||||
}
|
}
|
||||||
@ -614,7 +691,7 @@ func (b *ValueBinder) Uint16(sourceParam string, dest *uint16) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 16, false)
|
return b.uintValue(sourceParam, dest, 16, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint16 requires parameter value to exist to be bind to uint16 variable. Returns error when value does not exist
|
// MustUint16 requires parameter value to exist to bind to uint16 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint16(sourceParam string, dest *uint16) *ValueBinder {
|
func (b *ValueBinder) MustUint16(sourceParam string, dest *uint16) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 16, true)
|
return b.uintValue(sourceParam, dest, 16, true)
|
||||||
}
|
}
|
||||||
@ -624,7 +701,7 @@ func (b *ValueBinder) Uint8(sourceParam string, dest *uint8) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 8, false)
|
return b.uintValue(sourceParam, dest, 8, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint8 requires parameter value to exist to be bind to uint8 variable. Returns error when value does not exist
|
// MustUint8 requires parameter value to exist to bind to uint8 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint8(sourceParam string, dest *uint8) *ValueBinder {
|
func (b *ValueBinder) MustUint8(sourceParam string, dest *uint8) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 8, true)
|
return b.uintValue(sourceParam, dest, 8, true)
|
||||||
}
|
}
|
||||||
@ -634,7 +711,7 @@ func (b *ValueBinder) Byte(sourceParam string, dest *byte) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 8, false)
|
return b.uintValue(sourceParam, dest, 8, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustByte requires parameter value to exist to be bind to byte variable. Returns error when value does not exist
|
// MustByte requires parameter value to exist to bind to byte variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustByte(sourceParam string, dest *byte) *ValueBinder {
|
func (b *ValueBinder) MustByte(sourceParam string, dest *byte) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 8, true)
|
return b.uintValue(sourceParam, dest, 8, true)
|
||||||
}
|
}
|
||||||
@ -644,7 +721,7 @@ func (b *ValueBinder) Uint(sourceParam string, dest *uint) *ValueBinder {
|
|||||||
return b.uintValue(sourceParam, dest, 0, false)
|
return b.uintValue(sourceParam, dest, 0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint requires parameter value to exist to be bind to uint variable. Returns error when value does not exist
|
// MustUint requires parameter value to exist to bind to uint variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint(sourceParam string, dest *uint) *ValueBinder {
|
func (b *ValueBinder) MustUint(sourceParam string, dest *uint) *ValueBinder {
|
||||||
return b.uintValue(sourceParam, dest, 0, true)
|
return b.uintValue(sourceParam, dest, 0, true)
|
||||||
}
|
}
|
||||||
@ -772,7 +849,7 @@ func (b *ValueBinder) Uint64s(sourceParam string, dest *[]uint64) *ValueBinder {
|
|||||||
return b.uintsValue(sourceParam, dest, false)
|
return b.uintsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint64s requires parameter value to exist to be bind to uint64 slice variable. Returns error when value does not exist
|
// MustUint64s requires parameter value to exist to bind to uint64 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint64s(sourceParam string, dest *[]uint64) *ValueBinder {
|
func (b *ValueBinder) MustUint64s(sourceParam string, dest *[]uint64) *ValueBinder {
|
||||||
return b.uintsValue(sourceParam, dest, true)
|
return b.uintsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -782,7 +859,7 @@ func (b *ValueBinder) Uint32s(sourceParam string, dest *[]uint32) *ValueBinder {
|
|||||||
return b.uintsValue(sourceParam, dest, false)
|
return b.uintsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint32s requires parameter value to exist to be bind to uint32 slice variable. Returns error when value does not exist
|
// MustUint32s requires parameter value to exist to bind to uint32 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint32s(sourceParam string, dest *[]uint32) *ValueBinder {
|
func (b *ValueBinder) MustUint32s(sourceParam string, dest *[]uint32) *ValueBinder {
|
||||||
return b.uintsValue(sourceParam, dest, true)
|
return b.uintsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -792,7 +869,7 @@ func (b *ValueBinder) Uint16s(sourceParam string, dest *[]uint16) *ValueBinder {
|
|||||||
return b.uintsValue(sourceParam, dest, false)
|
return b.uintsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint16s requires parameter value to exist to be bind to uint16 slice variable. Returns error when value does not exist
|
// MustUint16s requires parameter value to exist to bind to uint16 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint16s(sourceParam string, dest *[]uint16) *ValueBinder {
|
func (b *ValueBinder) MustUint16s(sourceParam string, dest *[]uint16) *ValueBinder {
|
||||||
return b.uintsValue(sourceParam, dest, true)
|
return b.uintsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -802,7 +879,7 @@ func (b *ValueBinder) Uint8s(sourceParam string, dest *[]uint8) *ValueBinder {
|
|||||||
return b.uintsValue(sourceParam, dest, false)
|
return b.uintsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUint8s requires parameter value to exist to be bind to uint8 slice variable. Returns error when value does not exist
|
// MustUint8s requires parameter value to exist to bind to uint8 slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUint8s(sourceParam string, dest *[]uint8) *ValueBinder {
|
func (b *ValueBinder) MustUint8s(sourceParam string, dest *[]uint8) *ValueBinder {
|
||||||
return b.uintsValue(sourceParam, dest, true)
|
return b.uintsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -812,7 +889,7 @@ func (b *ValueBinder) Uints(sourceParam string, dest *[]uint) *ValueBinder {
|
|||||||
return b.uintsValue(sourceParam, dest, false)
|
return b.uintsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUints requires parameter value to exist to be bind to uint slice variable. Returns error when value does not exist
|
// MustUints requires parameter value to exist to bind to uint slice variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustUints(sourceParam string, dest *[]uint) *ValueBinder {
|
func (b *ValueBinder) MustUints(sourceParam string, dest *[]uint) *ValueBinder {
|
||||||
return b.uintsValue(sourceParam, dest, true)
|
return b.uintsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -822,7 +899,7 @@ func (b *ValueBinder) Bool(sourceParam string, dest *bool) *ValueBinder {
|
|||||||
return b.boolValue(sourceParam, dest, false)
|
return b.boolValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustBool requires parameter value to exist to be bind to bool variable. Returns error when value does not exist
|
// MustBool requires parameter value to exist to bind to bool variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustBool(sourceParam string, dest *bool) *ValueBinder {
|
func (b *ValueBinder) MustBool(sourceParam string, dest *bool) *ValueBinder {
|
||||||
return b.boolValue(sourceParam, dest, true)
|
return b.boolValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -887,7 +964,7 @@ func (b *ValueBinder) Bools(sourceParam string, dest *[]bool) *ValueBinder {
|
|||||||
return b.boolsValue(sourceParam, dest, false)
|
return b.boolsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustBools requires parameter values to exist to be bind to slice of bool variables. Returns error when values does not exist
|
// MustBools requires parameter values to exist to bind to slice of bool variables. Returns error when values does not exist
|
||||||
func (b *ValueBinder) MustBools(sourceParam string, dest *[]bool) *ValueBinder {
|
func (b *ValueBinder) MustBools(sourceParam string, dest *[]bool) *ValueBinder {
|
||||||
return b.boolsValue(sourceParam, dest, true)
|
return b.boolsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -897,7 +974,7 @@ func (b *ValueBinder) Float64(sourceParam string, dest *float64) *ValueBinder {
|
|||||||
return b.floatValue(sourceParam, dest, 64, false)
|
return b.floatValue(sourceParam, dest, 64, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustFloat64 requires parameter value to exist to be bind to float64 variable. Returns error when value does not exist
|
// MustFloat64 requires parameter value to exist to bind to float64 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustFloat64(sourceParam string, dest *float64) *ValueBinder {
|
func (b *ValueBinder) MustFloat64(sourceParam string, dest *float64) *ValueBinder {
|
||||||
return b.floatValue(sourceParam, dest, 64, true)
|
return b.floatValue(sourceParam, dest, 64, true)
|
||||||
}
|
}
|
||||||
@ -907,7 +984,7 @@ func (b *ValueBinder) Float32(sourceParam string, dest *float32) *ValueBinder {
|
|||||||
return b.floatValue(sourceParam, dest, 32, false)
|
return b.floatValue(sourceParam, dest, 32, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustFloat32 requires parameter value to exist to be bind to float32 variable. Returns error when value does not exist
|
// MustFloat32 requires parameter value to exist to bind to float32 variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustFloat32(sourceParam string, dest *float32) *ValueBinder {
|
func (b *ValueBinder) MustFloat32(sourceParam string, dest *float32) *ValueBinder {
|
||||||
return b.floatValue(sourceParam, dest, 32, true)
|
return b.floatValue(sourceParam, dest, 32, true)
|
||||||
}
|
}
|
||||||
@ -992,7 +1069,7 @@ func (b *ValueBinder) Float64s(sourceParam string, dest *[]float64) *ValueBinder
|
|||||||
return b.floatsValue(sourceParam, dest, false)
|
return b.floatsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustFloat64s requires parameter values to exist to be bind to slice of float64 variables. Returns error when values does not exist
|
// MustFloat64s requires parameter values to exist to bind to slice of float64 variables. Returns error when values does not exist
|
||||||
func (b *ValueBinder) MustFloat64s(sourceParam string, dest *[]float64) *ValueBinder {
|
func (b *ValueBinder) MustFloat64s(sourceParam string, dest *[]float64) *ValueBinder {
|
||||||
return b.floatsValue(sourceParam, dest, true)
|
return b.floatsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -1002,7 +1079,7 @@ func (b *ValueBinder) Float32s(sourceParam string, dest *[]float32) *ValueBinder
|
|||||||
return b.floatsValue(sourceParam, dest, false)
|
return b.floatsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustFloat32s requires parameter values to exist to be bind to slice of float32 variables. Returns error when values does not exist
|
// MustFloat32s requires parameter values to exist to bind to slice of float32 variables. Returns error when values does not exist
|
||||||
func (b *ValueBinder) MustFloat32s(sourceParam string, dest *[]float32) *ValueBinder {
|
func (b *ValueBinder) MustFloat32s(sourceParam string, dest *[]float32) *ValueBinder {
|
||||||
return b.floatsValue(sourceParam, dest, true)
|
return b.floatsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -1012,7 +1089,7 @@ func (b *ValueBinder) Time(sourceParam string, dest *time.Time, layout string) *
|
|||||||
return b.time(sourceParam, dest, layout, false)
|
return b.time(sourceParam, dest, layout, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustTime requires parameter value to exist to be bind to time.Time variable. Returns error when value does not exist
|
// MustTime requires parameter value to exist to bind to time.Time variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustTime(sourceParam string, dest *time.Time, layout string) *ValueBinder {
|
func (b *ValueBinder) MustTime(sourceParam string, dest *time.Time, layout string) *ValueBinder {
|
||||||
return b.time(sourceParam, dest, layout, true)
|
return b.time(sourceParam, dest, layout, true)
|
||||||
}
|
}
|
||||||
@ -1043,7 +1120,7 @@ func (b *ValueBinder) Times(sourceParam string, dest *[]time.Time, layout string
|
|||||||
return b.times(sourceParam, dest, layout, false)
|
return b.times(sourceParam, dest, layout, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustTimes requires parameter values to exist to be bind to slice of time.Time variables. Returns error when values does not exist
|
// MustTimes requires parameter values to exist to bind to slice of time.Time variables. Returns error when values does not exist
|
||||||
func (b *ValueBinder) MustTimes(sourceParam string, dest *[]time.Time, layout string) *ValueBinder {
|
func (b *ValueBinder) MustTimes(sourceParam string, dest *[]time.Time, layout string) *ValueBinder {
|
||||||
return b.times(sourceParam, dest, layout, true)
|
return b.times(sourceParam, dest, layout, true)
|
||||||
}
|
}
|
||||||
@ -1084,7 +1161,7 @@ func (b *ValueBinder) Duration(sourceParam string, dest *time.Duration) *ValueBi
|
|||||||
return b.duration(sourceParam, dest, false)
|
return b.duration(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustDuration requires parameter value to exist to be bind to time.Duration variable. Returns error when value does not exist
|
// MustDuration requires parameter value to exist to bind to time.Duration variable. Returns error when value does not exist
|
||||||
func (b *ValueBinder) MustDuration(sourceParam string, dest *time.Duration) *ValueBinder {
|
func (b *ValueBinder) MustDuration(sourceParam string, dest *time.Duration) *ValueBinder {
|
||||||
return b.duration(sourceParam, dest, true)
|
return b.duration(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -1115,7 +1192,7 @@ func (b *ValueBinder) Durations(sourceParam string, dest *[]time.Duration) *Valu
|
|||||||
return b.durationsValue(sourceParam, dest, false)
|
return b.durationsValue(sourceParam, dest, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustDurations requires parameter values to exist to be bind to slice of time.Duration variables. Returns error when values does not exist
|
// MustDurations requires parameter values to exist to bind to slice of time.Duration variables. Returns error when values does not exist
|
||||||
func (b *ValueBinder) MustDurations(sourceParam string, dest *[]time.Duration) *ValueBinder {
|
func (b *ValueBinder) MustDurations(sourceParam string, dest *[]time.Duration) *ValueBinder {
|
||||||
return b.durationsValue(sourceParam, dest, true)
|
return b.durationsValue(sourceParam, dest, true)
|
||||||
}
|
}
|
||||||
@ -1161,10 +1238,10 @@ func (b *ValueBinder) durations(sourceParam string, values []string, dest *[]tim
|
|||||||
// Note:
|
// Note:
|
||||||
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
func (b *ValueBinder) UnixTime(sourceParam string, dest *time.Time) *ValueBinder {
|
func (b *ValueBinder) UnixTime(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
return b.unixTime(sourceParam, dest, false, false)
|
return b.unixTime(sourceParam, dest, false, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUnixTime requires parameter value to exist to be bind to time.Duration variable (in local Time corresponding
|
// MustUnixTime requires parameter value to exist to bind to time.Duration variable (in local time corresponding
|
||||||
// to the given Unix time). Returns error when value does not exist.
|
// to the given Unix time). Returns error when value does not exist.
|
||||||
//
|
//
|
||||||
// Example: 1609180603 bind to 2020-12-28T18:36:43.000000000+00:00
|
// Example: 1609180603 bind to 2020-12-28T18:36:43.000000000+00:00
|
||||||
@ -1172,10 +1249,31 @@ func (b *ValueBinder) UnixTime(sourceParam string, dest *time.Time) *ValueBinder
|
|||||||
// Note:
|
// Note:
|
||||||
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
func (b *ValueBinder) MustUnixTime(sourceParam string, dest *time.Time) *ValueBinder {
|
func (b *ValueBinder) MustUnixTime(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
return b.unixTime(sourceParam, dest, true, false)
|
return b.unixTime(sourceParam, dest, true, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnixTimeNano binds parameter to time.Time variable (in local Time corresponding to the given Unix time in nano second precision).
|
// UnixTimeMilli binds parameter to time.Time variable (in local time corresponding to the given Unix time in millisecond precision).
|
||||||
|
//
|
||||||
|
// Example: 1647184410140 bind to 2022-03-13T15:13:30.140000000+00:00
|
||||||
|
//
|
||||||
|
// Note:
|
||||||
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
|
func (b *ValueBinder) UnixTimeMilli(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
|
return b.unixTime(sourceParam, dest, false, time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustUnixTimeMilli requires parameter value to exist to bind to time.Duration variable (in local time corresponding
|
||||||
|
// to the given Unix time in millisecond precision). Returns error when value does not exist.
|
||||||
|
//
|
||||||
|
// Example: 1647184410140 bind to 2022-03-13T15:13:30.140000000+00:00
|
||||||
|
//
|
||||||
|
// Note:
|
||||||
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
|
func (b *ValueBinder) MustUnixTimeMilli(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
|
return b.unixTime(sourceParam, dest, true, time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnixTimeNano binds parameter to time.Time variable (in local time corresponding to the given Unix time in nanosecond precision).
|
||||||
//
|
//
|
||||||
// Example: 1609180603123456789 binds to 2020-12-28T18:36:43.123456789+00:00
|
// Example: 1609180603123456789 binds to 2020-12-28T18:36:43.123456789+00:00
|
||||||
// Example: 1000000000 binds to 1970-01-01T00:00:01.000000000+00:00
|
// Example: 1000000000 binds to 1970-01-01T00:00:01.000000000+00:00
|
||||||
@ -1185,10 +1283,10 @@ func (b *ValueBinder) MustUnixTime(sourceParam string, dest *time.Time) *ValueBi
|
|||||||
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
// * Javascript's Number type only has about 53 bits of precision (Number.MAX_SAFE_INTEGER = 9007199254740991). Compare it to 1609180603123456789 in example.
|
// * Javascript's Number type only has about 53 bits of precision (Number.MAX_SAFE_INTEGER = 9007199254740991). Compare it to 1609180603123456789 in example.
|
||||||
func (b *ValueBinder) UnixTimeNano(sourceParam string, dest *time.Time) *ValueBinder {
|
func (b *ValueBinder) UnixTimeNano(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
return b.unixTime(sourceParam, dest, false, true)
|
return b.unixTime(sourceParam, dest, false, time.Nanosecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustUnixTimeNano requires parameter value to exist to be bind to time.Duration variable (in local Time corresponding
|
// MustUnixTimeNano requires parameter value to exist to bind to time.Duration variable (in local Time corresponding
|
||||||
// to the given Unix time value in nano second precision). Returns error when value does not exist.
|
// to the given Unix time value in nano second precision). Returns error when value does not exist.
|
||||||
//
|
//
|
||||||
// Example: 1609180603123456789 binds to 2020-12-28T18:36:43.123456789+00:00
|
// Example: 1609180603123456789 binds to 2020-12-28T18:36:43.123456789+00:00
|
||||||
@ -1199,10 +1297,10 @@ func (b *ValueBinder) UnixTimeNano(sourceParam string, dest *time.Time) *ValueBi
|
|||||||
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
// * time.Time{} (param is empty) and time.Unix(0,0) (param = "0") are not equal
|
||||||
// * Javascript's Number type only has about 53 bits of precision (Number.MAX_SAFE_INTEGER = 9007199254740991). Compare it to 1609180603123456789 in example.
|
// * Javascript's Number type only has about 53 bits of precision (Number.MAX_SAFE_INTEGER = 9007199254740991). Compare it to 1609180603123456789 in example.
|
||||||
func (b *ValueBinder) MustUnixTimeNano(sourceParam string, dest *time.Time) *ValueBinder {
|
func (b *ValueBinder) MustUnixTimeNano(sourceParam string, dest *time.Time) *ValueBinder {
|
||||||
return b.unixTime(sourceParam, dest, true, true)
|
return b.unixTime(sourceParam, dest, true, time.Nanosecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ValueBinder) unixTime(sourceParam string, dest *time.Time, valueMustExist bool, isNano bool) *ValueBinder {
|
func (b *ValueBinder) unixTime(sourceParam string, dest *time.Time, valueMustExist bool, precision time.Duration) *ValueBinder {
|
||||||
if b.failFast && b.errors != nil {
|
if b.failFast && b.errors != nil {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
@ -1221,10 +1319,13 @@ func (b *ValueBinder) unixTime(sourceParam string, dest *time.Time, valueMustExi
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
if isNano {
|
switch precision {
|
||||||
*dest = time.Unix(0, n)
|
case time.Second:
|
||||||
} else {
|
|
||||||
*dest = time.Unix(n, 0)
|
*dest = time.Unix(n, 0)
|
||||||
|
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
|
||||||
|
case time.Nanosecond:
|
||||||
|
*dest = time.Unix(0, n)
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
15
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
15
vendor/github.com/labstack/echo/v4/context.go
generated
vendored
@ -169,7 +169,11 @@ type (
|
|||||||
// Redirect redirects the request to a provided URL with status code.
|
// Redirect redirects the request to a provided URL with status code.
|
||||||
Redirect(code int, url string) error
|
Redirect(code int, url string) error
|
||||||
|
|
||||||
// Error invokes the registered HTTP error handler. Generally used by middleware.
|
// Error invokes the registered global HTTP error handler. Generally used by middleware.
|
||||||
|
// A side-effect of calling global error handler is that now Response has been committed (sent to the client) and
|
||||||
|
// middlewares up in chain can not change Response status code or Response body anymore.
|
||||||
|
//
|
||||||
|
// Avoid using this method in handlers as no middleware will be able to effectively handle errors after that.
|
||||||
Error(err error)
|
Error(err error)
|
||||||
|
|
||||||
// Handler returns the matched handler by router.
|
// Handler returns the matched handler by router.
|
||||||
@ -181,7 +185,7 @@ type (
|
|||||||
// Logger returns the `Logger` instance.
|
// Logger returns the `Logger` instance.
|
||||||
Logger() Logger
|
Logger() Logger
|
||||||
|
|
||||||
// Set the logger
|
// SetLogger Set the logger
|
||||||
SetLogger(l Logger)
|
SetLogger(l Logger)
|
||||||
|
|
||||||
// Echo returns the `Echo` instance.
|
// Echo returns the `Echo` instance.
|
||||||
@ -282,11 +286,16 @@ func (c *context) RealIP() string {
|
|||||||
if ip := c.request.Header.Get(HeaderXForwardedFor); ip != "" {
|
if ip := c.request.Header.Get(HeaderXForwardedFor); ip != "" {
|
||||||
i := strings.IndexAny(ip, ",")
|
i := strings.IndexAny(ip, ",")
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
return strings.TrimSpace(ip[:i])
|
xffip := strings.TrimSpace(ip[:i])
|
||||||
|
xffip = strings.TrimPrefix(xffip, "[")
|
||||||
|
xffip = strings.TrimSuffix(xffip, "]")
|
||||||
|
return xffip
|
||||||
}
|
}
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
if ip := c.request.Header.Get(HeaderXRealIP); ip != "" {
|
if ip := c.request.Header.Get(HeaderXRealIP); ip != "" {
|
||||||
|
ip = strings.TrimPrefix(ip, "[")
|
||||||
|
ip = strings.TrimSuffix(ip, "]")
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
ra, _, _ := net.SplitHostPort(c.request.RemoteAddr)
|
ra, _, _ := net.SplitHostPort(c.request.RemoteAddr)
|
||||||
|
42
vendor/github.com/labstack/echo/v4/context_fs.go
generated
vendored
42
vendor/github.com/labstack/echo/v4/context_fs.go
generated
vendored
@ -1,33 +1,49 @@
|
|||||||
//go:build !go1.16
|
|
||||||
// +build !go1.16
|
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *context) File(file string) (err error) {
|
func (c *context) File(file string) error {
|
||||||
f, err := os.Open(file)
|
return fsFile(c, file, c.echo.Filesystem)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileFS serves file from given file system.
|
||||||
|
//
|
||||||
|
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||||
|
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||||
|
// including `assets/images` as their prefix.
|
||||||
|
func (c *context) FileFS(file string, filesystem fs.FS) error {
|
||||||
|
return fsFile(c, file, filesystem)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fsFile(c Context, file string, filesystem fs.FS) error {
|
||||||
|
f, err := filesystem.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NotFoundHandler(c)
|
return ErrNotFound
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
fi, _ := f.Stat()
|
fi, _ := f.Stat()
|
||||||
if fi.IsDir() {
|
if fi.IsDir() {
|
||||||
file = filepath.Join(file, indexPage)
|
file = filepath.ToSlash(filepath.Join(file, indexPage)) // ToSlash is necessary for Windows. fs.Open and os.Open are different in that aspect.
|
||||||
f, err = os.Open(file)
|
f, err = filesystem.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NotFoundHandler(c)
|
return ErrNotFound
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
if fi, err = f.Stat(); err != nil {
|
if fi, err = f.Stat(); err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), f)
|
ff, ok := f.(io.ReadSeeker)
|
||||||
return
|
if !ok {
|
||||||
|
return errors.New("file does not implement io.ReadSeeker")
|
||||||
|
}
|
||||||
|
http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), ff)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
52
vendor/github.com/labstack/echo/v4/context_fs_go1.16.go
generated
vendored
52
vendor/github.com/labstack/echo/v4/context_fs_go1.16.go
generated
vendored
@ -1,52 +0,0 @@
|
|||||||
//go:build go1.16
|
|
||||||
// +build go1.16
|
|
||||||
|
|
||||||
package echo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"io/fs"
|
|
||||||
"net/http"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *context) File(file string) error {
|
|
||||||
return fsFile(c, file, c.echo.Filesystem)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileFS serves file from given file system.
|
|
||||||
//
|
|
||||||
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
|
||||||
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
|
||||||
// including `assets/images` as their prefix.
|
|
||||||
func (c *context) FileFS(file string, filesystem fs.FS) error {
|
|
||||||
return fsFile(c, file, filesystem)
|
|
||||||
}
|
|
||||||
|
|
||||||
func fsFile(c Context, file string, filesystem fs.FS) error {
|
|
||||||
f, err := filesystem.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return ErrNotFound
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
fi, _ := f.Stat()
|
|
||||||
if fi.IsDir() {
|
|
||||||
file = filepath.ToSlash(filepath.Join(file, indexPage)) // ToSlash is necessary for Windows. fs.Open and os.Open are different in that aspect.
|
|
||||||
f, err = filesystem.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return ErrNotFound
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
if fi, err = f.Stat(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ff, ok := f.(io.ReadSeeker)
|
|
||||||
if !ok {
|
|
||||||
return errors.New("file does not implement io.ReadSeeker")
|
|
||||||
}
|
|
||||||
http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), ff)
|
|
||||||
return nil
|
|
||||||
}
|
|
162
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
162
vendor/github.com/labstack/echo/v4/echo.go
generated
vendored
@ -3,50 +3,49 @@ Package echo implements high performance, minimalist Go web framework.
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handler
|
// Handler
|
||||||
func hello(c echo.Context) error {
|
func hello(c echo.Context) error {
|
||||||
return c.String(http.StatusOK, "Hello, World!")
|
return c.String(http.StatusOK, "Hello, World!")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Echo instance
|
// Echo instance
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
|
|
||||||
// Middleware
|
// Middleware
|
||||||
e.Use(middleware.Logger())
|
e.Use(middleware.Logger())
|
||||||
e.Use(middleware.Recover())
|
e.Use(middleware.Recover())
|
||||||
|
|
||||||
// Routes
|
// Routes
|
||||||
e.GET("/", hello)
|
e.GET("/", hello)
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
e.Logger.Fatal(e.Start(":1323"))
|
e.Logger.Fatal(e.Start(":1323"))
|
||||||
}
|
}
|
||||||
|
|
||||||
Learn more at https://echo.labstack.com
|
Learn more at https://echo.labstack.com
|
||||||
*/
|
*/
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
stdContext "context"
|
stdContext "context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
stdLog "log"
|
stdLog "log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
@ -62,20 +61,28 @@ import (
|
|||||||
|
|
||||||
type (
|
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
|
||||||
|
// 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!
|
||||||
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 binded) without having data races.
|
||||||
startupMutex sync.RWMutex
|
startupMutex sync.RWMutex
|
||||||
|
colorer *color.Color
|
||||||
|
|
||||||
|
// premiddleware are middlewares that are run before routing is done. In case a pre-middleware returns
|
||||||
|
// an error the router is not executed and the request will end up in the global error handler.
|
||||||
|
premiddleware []MiddlewareFunc
|
||||||
|
middleware []MiddlewareFunc
|
||||||
|
maxParam *int
|
||||||
|
router *Router
|
||||||
|
routers map[string]*Router
|
||||||
|
pool sync.Pool
|
||||||
|
|
||||||
StdLogger *stdLog.Logger
|
StdLogger *stdLog.Logger
|
||||||
colorer *color.Color
|
|
||||||
premiddleware []MiddlewareFunc
|
|
||||||
middleware []MiddlewareFunc
|
|
||||||
maxParam *int
|
|
||||||
router *Router
|
|
||||||
routers map[string]*Router
|
|
||||||
pool sync.Pool
|
|
||||||
Server *http.Server
|
Server *http.Server
|
||||||
TLSServer *http.Server
|
TLSServer *http.Server
|
||||||
Listener net.Listener
|
Listener net.Listener
|
||||||
@ -93,6 +100,9 @@ type (
|
|||||||
Logger Logger
|
Logger Logger
|
||||||
IPExtractor IPExtractor
|
IPExtractor IPExtractor
|
||||||
ListenerNetwork string
|
ListenerNetwork string
|
||||||
|
|
||||||
|
// OnAddRouteHandler is called when Echo adds new route to specific host router.
|
||||||
|
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.
|
||||||
@ -116,7 +126,7 @@ type (
|
|||||||
HandlerFunc func(c Context) error
|
HandlerFunc func(c Context) error
|
||||||
|
|
||||||
// HTTPErrorHandler is a centralized HTTP error handler.
|
// HTTPErrorHandler is a centralized HTTP error handler.
|
||||||
HTTPErrorHandler func(error, Context)
|
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 {
|
Validator interface {
|
||||||
@ -183,6 +193,8 @@ const (
|
|||||||
PROPFIND = "PROPFIND"
|
PROPFIND = "PROPFIND"
|
||||||
// REPORT Method can be used to get information about a resource, see rfc 3253
|
// REPORT Method can be used to get information about a resource, see rfc 3253
|
||||||
REPORT = "REPORT"
|
REPORT = "REPORT"
|
||||||
|
// RouteNotFound is special method type for routes handling "route not found" (404) cases
|
||||||
|
RouteNotFound = "echo_route_not_found"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Headers
|
// Headers
|
||||||
@ -246,7 +258,7 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Version of Echo
|
// Version of Echo
|
||||||
Version = "4.7.2"
|
Version = "4.10.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 = `
|
||||||
@ -480,8 +492,21 @@ func (e *Echo) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
|
|||||||
return e.Add(http.MethodTrace, path, h, m...)
|
return e.Add(http.MethodTrace, path, h, m...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any registers a new route for all HTTP methods and path with matching handler
|
// RouteNotFound registers a special-case route which is executed when no other route is found (i.e. HTTP 404 cases)
|
||||||
|
// for current request URL.
|
||||||
|
// Path supports static and named/any parameters just like other http method is defined. Generally path is ended with
|
||||||
|
// wildcard/match-any character (`/*`, `/download/*` etc).
|
||||||
|
//
|
||||||
|
// Example: `e.RouteNotFound("/*", func(c echo.Context) error { return c.NoContent(http.StatusNotFound) })`
|
||||||
|
func (e *Echo) RouteNotFound(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
|
||||||
|
return e.Add(RouteNotFound, path, h, m...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any registers a new route for all HTTP methods (supported by Echo) and path with matching handler
|
||||||
// in the router with optional route-level middleware.
|
// in the router with optional route-level middleware.
|
||||||
|
//
|
||||||
|
// Note: this method only adds specific set of supported HTTP methods as handler and is not true
|
||||||
|
// "catch-any-arbitrary-method" way of matching requests.
|
||||||
func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route {
|
func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route {
|
||||||
routes := make([]*Route, len(methods))
|
routes := make([]*Route, len(methods))
|
||||||
for i, m := range methods {
|
for i, m := range methods {
|
||||||
@ -512,20 +537,20 @@ func (e *Echo) File(path, file string, m ...MiddlewareFunc) *Route {
|
|||||||
return e.file(path, file, e.GET, m...)
|
return e.file(path, file, e.GET, m...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Echo) add(host, method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route {
|
func (e *Echo) add(host, method, path string, handler HandlerFunc, middlewares ...MiddlewareFunc) *Route {
|
||||||
name := handlerName(handler)
|
|
||||||
router := e.findRouter(host)
|
router := e.findRouter(host)
|
||||||
router.Add(method, path, func(c Context) error {
|
//FIXME: when handler+middleware are both nil ... make it behave like handler removal
|
||||||
h := applyMiddleware(handler, middleware...)
|
name := handlerName(handler)
|
||||||
|
route := router.add(method, path, name, func(c Context) error {
|
||||||
|
h := applyMiddleware(handler, middlewares...)
|
||||||
return h(c)
|
return h(c)
|
||||||
})
|
})
|
||||||
r := &Route{
|
|
||||||
Method: method,
|
if e.OnAddRouteHandler != nil {
|
||||||
Path: path,
|
e.OnAddRouteHandler(host, *route, handler, middlewares)
|
||||||
Name: name,
|
|
||||||
}
|
}
|
||||||
e.router.routes[method+path] = r
|
|
||||||
return r
|
return route
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add registers a new route for an HTTP method and path with matching handler
|
// Add registers a new route for an HTTP method and path with matching handler
|
||||||
@ -549,7 +574,7 @@ func (e *Echo) Group(prefix string, m ...MiddlewareFunc) (g *Group) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// URI generates a URI from handler.
|
// URI generates an URI from handler.
|
||||||
func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string {
|
func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string {
|
||||||
name := handlerName(handler)
|
name := handlerName(handler)
|
||||||
return e.Reverse(name, params...)
|
return e.Reverse(name, params...)
|
||||||
@ -562,35 +587,13 @@ func (e *Echo) URL(h HandlerFunc, params ...interface{}) string {
|
|||||||
|
|
||||||
// Reverse generates an URL from route name and provided parameters.
|
// Reverse generates an URL from route name and provided parameters.
|
||||||
func (e *Echo) Reverse(name string, params ...interface{}) string {
|
func (e *Echo) Reverse(name string, params ...interface{}) string {
|
||||||
uri := new(bytes.Buffer)
|
return e.router.Reverse(name, params...)
|
||||||
ln := len(params)
|
|
||||||
n := 0
|
|
||||||
for _, r := range e.router.routes {
|
|
||||||
if r.Name == name {
|
|
||||||
for i, l := 0, len(r.Path); i < l; i++ {
|
|
||||||
if (r.Path[i] == ':' || r.Path[i] == '*') && n < ln {
|
|
||||||
for ; i < l && r.Path[i] != '/'; i++ {
|
|
||||||
}
|
|
||||||
uri.WriteString(fmt.Sprintf("%v", params[n]))
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
if i < l {
|
|
||||||
uri.WriteByte(r.Path[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uri.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routes returns the registered routes.
|
// Routes returns the registered routes for default router.
|
||||||
|
// In case when Echo serves multiple hosts/domains use `e.Routers()["domain2.site"].Routes()` to get specific host routes.
|
||||||
func (e *Echo) Routes() []*Route {
|
func (e *Echo) Routes() []*Route {
|
||||||
routes := make([]*Route, 0, len(e.router.routes))
|
return e.router.Routes()
|
||||||
for _, v := range e.router.routes {
|
|
||||||
routes = append(routes, v)
|
|
||||||
}
|
|
||||||
return routes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AcquireContext returns an empty `Context` instance from the pool.
|
// AcquireContext returns an empty `Context` instance from the pool.
|
||||||
@ -610,7 +613,7 @@ func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
// Acquire context
|
// Acquire context
|
||||||
c := e.pool.Get().(*context)
|
c := e.pool.Get().(*context)
|
||||||
c.Reset(r, w)
|
c.Reset(r, w)
|
||||||
var h func(Context) error
|
var h HandlerFunc
|
||||||
|
|
||||||
if e.premiddleware == nil {
|
if e.premiddleware == nil {
|
||||||
e.findRouter(r.Host).Find(r.Method, GetPath(r), c)
|
e.findRouter(r.Host).Find(r.Method, GetPath(r), c)
|
||||||
@ -684,7 +687,7 @@ func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) (err erro
|
|||||||
func filepathOrContent(fileOrContent interface{}) (content []byte, err error) {
|
func filepathOrContent(fileOrContent interface{}) (content []byte, err error) {
|
||||||
switch v := fileOrContent.(type) {
|
switch v := fileOrContent.(type) {
|
||||||
case string:
|
case string:
|
||||||
return ioutil.ReadFile(v)
|
return os.ReadFile(v)
|
||||||
case []byte:
|
case []byte:
|
||||||
return v, nil
|
return v, nil
|
||||||
default:
|
default:
|
||||||
@ -868,6 +871,15 @@ func (he *HTTPError) SetInternal(err error) *HTTPError {
|
|||||||
return he
|
return he
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithInternal returns clone of HTTPError with err set to HTTPError.Internal field
|
||||||
|
func (he *HTTPError) WithInternal(err error) *HTTPError {
|
||||||
|
return &HTTPError{
|
||||||
|
Code: he.Code,
|
||||||
|
Message: he.Message,
|
||||||
|
Internal: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Unwrap satisfies the Go 1.13 error wrapper interface.
|
// Unwrap satisfies the Go 1.13 error wrapper interface.
|
||||||
func (he *HTTPError) Unwrap() error {
|
func (he *HTTPError) Unwrap() error {
|
||||||
return he.Internal
|
return he.Internal
|
||||||
@ -897,8 +909,8 @@ func WrapMiddleware(m func(http.Handler) http.Handler) MiddlewareFunc {
|
|||||||
|
|
||||||
// GetPath returns RawPath, if it's empty returns Path from URL
|
// GetPath returns RawPath, if it's empty returns Path from URL
|
||||||
// Difference between RawPath and Path is:
|
// Difference between RawPath and Path is:
|
||||||
// * Path is where request path is stored. Value is stored in decoded form: /%47%6f%2f becomes /Go/.
|
// - Path is where request path is stored. Value is stored in decoded form: /%47%6f%2f becomes /Go/.
|
||||||
// * RawPath is an optional field which only gets set if the default encoding is different from Path.
|
// - RawPath is an optional field which only gets set if the default encoding is different from Path.
|
||||||
func GetPath(r *http.Request) string {
|
func GetPath(r *http.Request) string {
|
||||||
path := r.URL.RawPath
|
path := r.URL.RawPath
|
||||||
if path == "" {
|
if path == "" {
|
||||||
|
167
vendor/github.com/labstack/echo/v4/echo_fs.go
generated
vendored
167
vendor/github.com/labstack/echo/v4/echo_fs.go
generated
vendored
@ -1,62 +1,159 @@
|
|||||||
//go:build !go1.16
|
|
||||||
// +build !go1.16
|
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type filesystem struct {
|
type filesystem struct {
|
||||||
|
// Filesystem is file system used by Static and File handlers to access files.
|
||||||
|
// Defaults to os.DirFS(".")
|
||||||
|
//
|
||||||
|
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||||
|
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||||
|
// including `assets/images` as their prefix.
|
||||||
|
Filesystem fs.FS
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFilesystem() filesystem {
|
func createFilesystem() filesystem {
|
||||||
return filesystem{}
|
return filesystem{
|
||||||
}
|
Filesystem: newDefaultFS(),
|
||||||
|
|
||||||
// Static registers a new route with path prefix to serve static files from the
|
|
||||||
// provided root directory.
|
|
||||||
func (e *Echo) Static(prefix, root string) *Route {
|
|
||||||
if root == "" {
|
|
||||||
root = "." // For security we want to restrict to CWD.
|
|
||||||
}
|
}
|
||||||
return e.static(prefix, root, e.GET)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (common) static(prefix, root string, get func(string, HandlerFunc, ...MiddlewareFunc) *Route) *Route {
|
// Static registers a new route with path prefix to serve static files from the provided root directory.
|
||||||
h := func(c Context) error {
|
func (e *Echo) Static(pathPrefix, fsRoot string) *Route {
|
||||||
p, err := url.PathUnescape(c.Param("*"))
|
subFs := MustSubFS(e.Filesystem, fsRoot)
|
||||||
if err != nil {
|
return e.Add(
|
||||||
return err
|
http.MethodGet,
|
||||||
|
pathPrefix+"*",
|
||||||
|
StaticDirectoryHandler(subFs, false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StaticFS registers a new route with path prefix to serve static files from the provided file system.
|
||||||
|
//
|
||||||
|
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||||
|
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||||
|
// including `assets/images` as their prefix.
|
||||||
|
func (e *Echo) StaticFS(pathPrefix string, filesystem fs.FS) *Route {
|
||||||
|
return e.Add(
|
||||||
|
http.MethodGet,
|
||||||
|
pathPrefix+"*",
|
||||||
|
StaticDirectoryHandler(filesystem, false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StaticDirectoryHandler creates handler function to serve files from provided file system
|
||||||
|
// When disablePathUnescaping is set then file name from path is not unescaped and is served as is.
|
||||||
|
func StaticDirectoryHandler(fileSystem fs.FS, disablePathUnescaping bool) HandlerFunc {
|
||||||
|
return func(c Context) error {
|
||||||
|
p := c.Param("*")
|
||||||
|
if !disablePathUnescaping { // when router is already unescaping we do not want to do is twice
|
||||||
|
tmpPath, err := url.PathUnescape(p)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to unescape path variable: %w", err)
|
||||||
|
}
|
||||||
|
p = tmpPath
|
||||||
}
|
}
|
||||||
|
|
||||||
name := filepath.Join(root, filepath.Clean("/"+p)) // "/"+ for security
|
// fs.FS.Open() already assumes that file names are relative to FS root path and considers name with prefix `/` as invalid
|
||||||
fi, err := os.Stat(name)
|
name := filepath.ToSlash(filepath.Clean(strings.TrimPrefix(p, "/")))
|
||||||
|
fi, err := fs.Stat(fileSystem, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// The access path does not exist
|
return ErrNotFound
|
||||||
return NotFoundHandler(c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the request is for a directory and does not end with "/"
|
// If the request is for a directory and does not end with "/"
|
||||||
p = c.Request().URL.Path // path must not be empty.
|
p = c.Request().URL.Path // path must not be empty.
|
||||||
if fi.IsDir() && p[len(p)-1] != '/' {
|
if fi.IsDir() && len(p) > 0 && p[len(p)-1] != '/' {
|
||||||
// Redirect to ends with "/"
|
// Redirect to ends with "/"
|
||||||
return c.Redirect(http.StatusMovedPermanently, p+"/")
|
return c.Redirect(http.StatusMovedPermanently, sanitizeURI(p+"/"))
|
||||||
}
|
}
|
||||||
return c.File(name)
|
return fsFile(c, name, fileSystem)
|
||||||
}
|
}
|
||||||
// Handle added routes based on trailing slash:
|
}
|
||||||
// /prefix => exact route "/prefix" + any route "/prefix/*"
|
|
||||||
// /prefix/ => only any route "/prefix/*"
|
// FileFS registers a new route with path to serve file from the provided file system.
|
||||||
if prefix != "" {
|
func (e *Echo) FileFS(path, file string, filesystem fs.FS, m ...MiddlewareFunc) *Route {
|
||||||
if prefix[len(prefix)-1] == '/' {
|
return e.GET(path, StaticFileHandler(file, filesystem), m...)
|
||||||
// Only add any route for intentional trailing slash
|
}
|
||||||
return get(prefix+"*", h)
|
|
||||||
}
|
// StaticFileHandler creates handler function to serve file from provided file system
|
||||||
get(prefix, h)
|
func StaticFileHandler(file string, filesystem fs.FS) HandlerFunc {
|
||||||
}
|
return func(c Context) error {
|
||||||
return get(prefix+"/*", h)
|
return fsFile(c, file, filesystem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultFS exists to preserve pre v4.7.0 behaviour where files were open by `os.Open`.
|
||||||
|
// v4.7 introduced `echo.Filesystem` field which is Go1.16+ `fs.Fs` interface.
|
||||||
|
// Difference between `os.Open` and `fs.Open` is that FS does not allow opening path that start with `.`, `..` or `/`
|
||||||
|
// etc. For example previously you could have `../images` in your application but `fs := os.DirFS("./")` would not
|
||||||
|
// allow you to use `fs.Open("../images")` and this would break all old applications that rely on being able to
|
||||||
|
// traverse up from current executable run path.
|
||||||
|
// NB: private because you really should use fs.FS implementation instances
|
||||||
|
type defaultFS struct {
|
||||||
|
prefix string
|
||||||
|
fs fs.FS
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDefaultFS() *defaultFS {
|
||||||
|
dir, _ := os.Getwd()
|
||||||
|
return &defaultFS{
|
||||||
|
prefix: dir,
|
||||||
|
fs: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs defaultFS) Open(name string) (fs.File, error) {
|
||||||
|
if fs.fs == nil {
|
||||||
|
return os.Open(name)
|
||||||
|
}
|
||||||
|
return fs.fs.Open(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func subFS(currentFs fs.FS, root string) (fs.FS, error) {
|
||||||
|
root = filepath.ToSlash(filepath.Clean(root)) // note: fs.FS operates only with slashes. `ToSlash` is necessary for Windows
|
||||||
|
if dFS, ok := currentFs.(*defaultFS); ok {
|
||||||
|
// we need to make exception for `defaultFS` instances as it interprets root prefix differently from fs.FS.
|
||||||
|
// fs.Fs.Open does not like relative paths ("./", "../") and absolute paths at all but prior echo.Filesystem we
|
||||||
|
// were able to use paths like `./myfile.log`, `/etc/hosts` and these would work fine with `os.Open` but not with fs.Fs
|
||||||
|
if !filepath.IsAbs(root) {
|
||||||
|
root = filepath.Join(dFS.prefix, root)
|
||||||
|
}
|
||||||
|
return &defaultFS{
|
||||||
|
prefix: root,
|
||||||
|
fs: os.DirFS(root),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return fs.Sub(currentFs, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustSubFS creates sub FS from current filesystem or panic on failure.
|
||||||
|
// Panic happens when `fsRoot` contains invalid path according to `fs.ValidPath` rules.
|
||||||
|
//
|
||||||
|
// MustSubFS is helpful when dealing with `embed.FS` because for example `//go:embed assets/images` embeds files with
|
||||||
|
// paths including `assets/images` as their prefix. In that case use `fs := echo.MustSubFS(fs, "rootDirectory") to
|
||||||
|
// create sub fs which uses necessary prefix for directory path.
|
||||||
|
func MustSubFS(currentFs fs.FS, fsRoot string) fs.FS {
|
||||||
|
subFs, err := subFS(currentFs, fsRoot)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("can not create sub FS, invalid root given, err: %w", err))
|
||||||
|
}
|
||||||
|
return subFs
|
||||||
|
}
|
||||||
|
|
||||||
|
func sanitizeURI(uri string) string {
|
||||||
|
// double slash `\\`, `//` or even `\/` is absolute uri for browsers and by redirecting request to that uri
|
||||||
|
// we are vulnerable to open redirect attack. so replace all slashes from the beginning with single slash
|
||||||
|
if len(uri) > 1 && (uri[0] == '\\' || uri[0] == '/') && (uri[1] == '\\' || uri[1] == '/') {
|
||||||
|
uri = "/" + strings.TrimLeft(uri, `/\`)
|
||||||
|
}
|
||||||
|
return uri
|
||||||
}
|
}
|
||||||
|
169
vendor/github.com/labstack/echo/v4/echo_fs_go1.16.go
generated
vendored
169
vendor/github.com/labstack/echo/v4/echo_fs_go1.16.go
generated
vendored
@ -1,169 +0,0 @@
|
|||||||
//go:build go1.16
|
|
||||||
// +build go1.16
|
|
||||||
|
|
||||||
package echo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type filesystem struct {
|
|
||||||
// Filesystem is file system used by Static and File handlers to access files.
|
|
||||||
// Defaults to os.DirFS(".")
|
|
||||||
//
|
|
||||||
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
|
||||||
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
|
||||||
// including `assets/images` as their prefix.
|
|
||||||
Filesystem fs.FS
|
|
||||||
}
|
|
||||||
|
|
||||||
func createFilesystem() filesystem {
|
|
||||||
return filesystem{
|
|
||||||
Filesystem: newDefaultFS(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Static registers a new route with path prefix to serve static files from the provided root directory.
|
|
||||||
func (e *Echo) Static(pathPrefix, fsRoot string) *Route {
|
|
||||||
subFs := MustSubFS(e.Filesystem, fsRoot)
|
|
||||||
return e.Add(
|
|
||||||
http.MethodGet,
|
|
||||||
pathPrefix+"*",
|
|
||||||
StaticDirectoryHandler(subFs, false),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StaticFS registers a new route with path prefix to serve static files from the provided file system.
|
|
||||||
//
|
|
||||||
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
|
||||||
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
|
||||||
// including `assets/images` as their prefix.
|
|
||||||
func (e *Echo) StaticFS(pathPrefix string, filesystem fs.FS) *Route {
|
|
||||||
return e.Add(
|
|
||||||
http.MethodGet,
|
|
||||||
pathPrefix+"*",
|
|
||||||
StaticDirectoryHandler(filesystem, false),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StaticDirectoryHandler creates handler function to serve files from provided file system
|
|
||||||
// When disablePathUnescaping is set then file name from path is not unescaped and is served as is.
|
|
||||||
func StaticDirectoryHandler(fileSystem fs.FS, disablePathUnescaping bool) HandlerFunc {
|
|
||||||
return func(c Context) error {
|
|
||||||
p := c.Param("*")
|
|
||||||
if !disablePathUnescaping { // when router is already unescaping we do not want to do is twice
|
|
||||||
tmpPath, err := url.PathUnescape(p)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to unescape path variable: %w", err)
|
|
||||||
}
|
|
||||||
p = tmpPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// fs.FS.Open() already assumes that file names are relative to FS root path and considers name with prefix `/` as invalid
|
|
||||||
name := filepath.ToSlash(filepath.Clean(strings.TrimPrefix(p, "/")))
|
|
||||||
fi, err := fs.Stat(fileSystem, name)
|
|
||||||
if err != nil {
|
|
||||||
return ErrNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the request is for a directory and does not end with "/"
|
|
||||||
p = c.Request().URL.Path // path must not be empty.
|
|
||||||
if fi.IsDir() && len(p) > 0 && p[len(p)-1] != '/' {
|
|
||||||
// Redirect to ends with "/"
|
|
||||||
return c.Redirect(http.StatusMovedPermanently, p+"/")
|
|
||||||
}
|
|
||||||
return fsFile(c, name, fileSystem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileFS registers a new route with path to serve file from the provided file system.
|
|
||||||
func (e *Echo) FileFS(path, file string, filesystem fs.FS, m ...MiddlewareFunc) *Route {
|
|
||||||
return e.GET(path, StaticFileHandler(file, filesystem), m...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StaticFileHandler creates handler function to serve file from provided file system
|
|
||||||
func StaticFileHandler(file string, filesystem fs.FS) HandlerFunc {
|
|
||||||
return func(c Context) error {
|
|
||||||
return fsFile(c, file, filesystem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaultFS exists to preserve pre v4.7.0 behaviour where files were open by `os.Open`.
|
|
||||||
// v4.7 introduced `echo.Filesystem` field which is Go1.16+ `fs.Fs` interface.
|
|
||||||
// Difference between `os.Open` and `fs.Open` is that FS does not allow opening path that start with `.`, `..` or `/`
|
|
||||||
// etc. For example previously you could have `../images` in your application but `fs := os.DirFS("./")` would not
|
|
||||||
// allow you to use `fs.Open("../images")` and this would break all old applications that rely on being able to
|
|
||||||
// traverse up from current executable run path.
|
|
||||||
// NB: private because you really should use fs.FS implementation instances
|
|
||||||
type defaultFS struct {
|
|
||||||
prefix string
|
|
||||||
fs fs.FS
|
|
||||||
}
|
|
||||||
|
|
||||||
func newDefaultFS() *defaultFS {
|
|
||||||
dir, _ := os.Getwd()
|
|
||||||
return &defaultFS{
|
|
||||||
prefix: dir,
|
|
||||||
fs: nil,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fs defaultFS) Open(name string) (fs.File, error) {
|
|
||||||
if fs.fs == nil {
|
|
||||||
return os.Open(name)
|
|
||||||
}
|
|
||||||
return fs.fs.Open(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func subFS(currentFs fs.FS, root string) (fs.FS, error) {
|
|
||||||
root = filepath.ToSlash(filepath.Clean(root)) // note: fs.FS operates only with slashes. `ToSlash` is necessary for Windows
|
|
||||||
if dFS, ok := currentFs.(*defaultFS); ok {
|
|
||||||
// we need to make exception for `defaultFS` instances as it interprets root prefix differently from fs.FS.
|
|
||||||
// fs.Fs.Open does not like relative paths ("./", "../") and absolute paths at all but prior echo.Filesystem we
|
|
||||||
// were able to use paths like `./myfile.log`, `/etc/hosts` and these would work fine with `os.Open` but not with fs.Fs
|
|
||||||
if isRelativePath(root) {
|
|
||||||
root = filepath.Join(dFS.prefix, root)
|
|
||||||
}
|
|
||||||
return &defaultFS{
|
|
||||||
prefix: root,
|
|
||||||
fs: os.DirFS(root),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
return fs.Sub(currentFs, root)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isRelativePath(path string) bool {
|
|
||||||
if path == "" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if path[0] == '/' {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if runtime.GOOS == "windows" && strings.IndexByte(path, ':') != -1 {
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#file_and_directory_names
|
|
||||||
// https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustSubFS creates sub FS from current filesystem or panic on failure.
|
|
||||||
// Panic happens when `fsRoot` contains invalid path according to `fs.ValidPath` rules.
|
|
||||||
//
|
|
||||||
// MustSubFS is helpful when dealing with `embed.FS` because for example `//go:embed assets/images` embeds files with
|
|
||||||
// paths including `assets/images` as their prefix. In that case use `fs := echo.MustSubFS(fs, "rootDirectory") to
|
|
||||||
// create sub fs which uses necessary prefix for directory path.
|
|
||||||
func MustSubFS(currentFs fs.FS, fsRoot string) fs.FS {
|
|
||||||
subFs, err := subFS(currentFs, fsRoot)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("can not create sub FS, invalid root given, err: %w", err))
|
|
||||||
}
|
|
||||||
return subFs
|
|
||||||
}
|
|
7
vendor/github.com/labstack/echo/v4/group.go
generated
vendored
7
vendor/github.com/labstack/echo/v4/group.go
generated
vendored
@ -107,6 +107,13 @@ func (g *Group) File(path, file string) {
|
|||||||
g.file(path, file, g.GET)
|
g.file(path, file, g.GET)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RouteNotFound implements `Echo#RouteNotFound()` for sub-routes within the Group.
|
||||||
|
//
|
||||||
|
// Example: `g.RouteNotFound("/*", func(c echo.Context) error { return c.NoContent(http.StatusNotFound) })`
|
||||||
|
func (g *Group) RouteNotFound(path string, h HandlerFunc, m ...MiddlewareFunc) *Route {
|
||||||
|
return g.Add(RouteNotFound, path, h, m...)
|
||||||
|
}
|
||||||
|
|
||||||
// Add implements `Echo#Add()` for sub-routes within the Group.
|
// Add implements `Echo#Add()` for sub-routes within the Group.
|
||||||
func (g *Group) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route {
|
func (g *Group) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route {
|
||||||
// Combine into a new slice to avoid accidentally passing the same slice for
|
// Combine into a new slice to avoid accidentally passing the same slice for
|
||||||
|
31
vendor/github.com/labstack/echo/v4/group_fs.go
generated
vendored
31
vendor/github.com/labstack/echo/v4/group_fs.go
generated
vendored
@ -1,9 +1,30 @@
|
|||||||
//go:build !go1.16
|
|
||||||
// +build !go1.16
|
|
||||||
|
|
||||||
package echo
|
package echo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
// Static implements `Echo#Static()` for sub-routes within the Group.
|
// Static implements `Echo#Static()` for sub-routes within the Group.
|
||||||
func (g *Group) Static(prefix, root string) {
|
func (g *Group) Static(pathPrefix, fsRoot string) {
|
||||||
g.static(prefix, root, g.GET)
|
subFs := MustSubFS(g.echo.Filesystem, fsRoot)
|
||||||
|
g.StaticFS(pathPrefix, subFs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StaticFS implements `Echo#StaticFS()` for sub-routes within the Group.
|
||||||
|
//
|
||||||
|
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
||||||
|
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
||||||
|
// including `assets/images` as their prefix.
|
||||||
|
func (g *Group) StaticFS(pathPrefix string, filesystem fs.FS) {
|
||||||
|
g.Add(
|
||||||
|
http.MethodGet,
|
||||||
|
pathPrefix+"*",
|
||||||
|
StaticDirectoryHandler(filesystem, false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileFS implements `Echo#FileFS()` for sub-routes within the Group.
|
||||||
|
func (g *Group) FileFS(path, file string, filesystem fs.FS, m ...MiddlewareFunc) *Route {
|
||||||
|
return g.GET(path, StaticFileHandler(file, filesystem), m...)
|
||||||
}
|
}
|
||||||
|
33
vendor/github.com/labstack/echo/v4/group_fs_go1.16.go
generated
vendored
33
vendor/github.com/labstack/echo/v4/group_fs_go1.16.go
generated
vendored
@ -1,33 +0,0 @@
|
|||||||
//go:build go1.16
|
|
||||||
// +build go1.16
|
|
||||||
|
|
||||||
package echo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/fs"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Static implements `Echo#Static()` for sub-routes within the Group.
|
|
||||||
func (g *Group) Static(pathPrefix, fsRoot string) {
|
|
||||||
subFs := MustSubFS(g.echo.Filesystem, fsRoot)
|
|
||||||
g.StaticFS(pathPrefix, subFs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StaticFS implements `Echo#StaticFS()` for sub-routes within the Group.
|
|
||||||
//
|
|
||||||
// When dealing with `embed.FS` use `fs := echo.MustSubFS(fs, "rootDirectory") to create sub fs which uses necessary
|
|
||||||
// prefix for directory path. This is necessary as `//go:embed assets/images` embeds files with paths
|
|
||||||
// including `assets/images` as their prefix.
|
|
||||||
func (g *Group) StaticFS(pathPrefix string, filesystem fs.FS) {
|
|
||||||
g.Add(
|
|
||||||
http.MethodGet,
|
|
||||||
pathPrefix+"*",
|
|
||||||
StaticDirectoryHandler(filesystem, false),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileFS implements `Echo#FileFS()` for sub-routes within the Group.
|
|
||||||
func (g *Group) FileFS(path, file string, filesystem fs.FS, m ...MiddlewareFunc) *Route {
|
|
||||||
return g.GET(path, StaticFileHandler(file, filesystem), m...)
|
|
||||||
}
|
|
7
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
7
vendor/github.com/labstack/echo/v4/ip.go
generated
vendored
@ -227,6 +227,8 @@ func ExtractIPFromRealIPHeader(options ...TrustOption) IPExtractor {
|
|||||||
return func(req *http.Request) string {
|
return func(req *http.Request) string {
|
||||||
realIP := req.Header.Get(HeaderXRealIP)
|
realIP := req.Header.Get(HeaderXRealIP)
|
||||||
if realIP != "" {
|
if realIP != "" {
|
||||||
|
realIP = strings.TrimPrefix(realIP, "[")
|
||||||
|
realIP = strings.TrimSuffix(realIP, "]")
|
||||||
if ip := net.ParseIP(realIP); ip != nil && checker.trust(ip) {
|
if ip := net.ParseIP(realIP); ip != nil && checker.trust(ip) {
|
||||||
return realIP
|
return realIP
|
||||||
}
|
}
|
||||||
@ -248,7 +250,10 @@ func ExtractIPFromXFFHeader(options ...TrustOption) IPExtractor {
|
|||||||
}
|
}
|
||||||
ips := append(strings.Split(strings.Join(xffs, ","), ","), directIP)
|
ips := append(strings.Split(strings.Join(xffs, ","), ","), directIP)
|
||||||
for i := len(ips) - 1; i >= 0; i-- {
|
for i := len(ips) - 1; i >= 0; i-- {
|
||||||
ip := net.ParseIP(strings.TrimSpace(ips[i]))
|
ips[i] = strings.TrimSpace(ips[i])
|
||||||
|
ips[i] = strings.TrimPrefix(ips[i], "[")
|
||||||
|
ips[i] = strings.TrimSuffix(ips[i], "]")
|
||||||
|
ip := net.ParseIP(ips[i])
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
// Unable to parse IP; cannot trust entire records
|
// Unable to parse IP; cannot trust entire records
|
||||||
return directIP
|
return directIP
|
||||||
|
369
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
369
vendor/github.com/labstack/echo/v4/router.go
generated
vendored
@ -2,6 +2,7 @@ package echo
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,30 +20,39 @@ type (
|
|||||||
prefix string
|
prefix string
|
||||||
parent *node
|
parent *node
|
||||||
staticChildren children
|
staticChildren children
|
||||||
ppath string
|
originalPath string
|
||||||
pnames []string
|
methods *routeMethods
|
||||||
methodHandler *methodHandler
|
|
||||||
paramChild *node
|
paramChild *node
|
||||||
anyChild *node
|
anyChild *node
|
||||||
|
paramsCount int
|
||||||
// isLeaf indicates that node does not have child routes
|
// isLeaf indicates that node does not have child routes
|
||||||
isLeaf bool
|
isLeaf bool
|
||||||
// isHandler indicates that node has at least one handler registered to it
|
// isHandler indicates that node has at least one handler registered to it
|
||||||
isHandler bool
|
isHandler bool
|
||||||
|
|
||||||
|
// notFoundHandler is handler registered with RouteNotFound method and is executed for 404 cases
|
||||||
|
notFoundHandler *routeMethod
|
||||||
}
|
}
|
||||||
kind uint8
|
kind uint8
|
||||||
children []*node
|
children []*node
|
||||||
methodHandler struct {
|
routeMethod struct {
|
||||||
connect HandlerFunc
|
ppath string
|
||||||
delete HandlerFunc
|
pnames []string
|
||||||
get HandlerFunc
|
handler HandlerFunc
|
||||||
head HandlerFunc
|
}
|
||||||
options HandlerFunc
|
routeMethods struct {
|
||||||
patch HandlerFunc
|
connect *routeMethod
|
||||||
post HandlerFunc
|
delete *routeMethod
|
||||||
propfind HandlerFunc
|
get *routeMethod
|
||||||
put HandlerFunc
|
head *routeMethod
|
||||||
trace HandlerFunc
|
options *routeMethod
|
||||||
report HandlerFunc
|
patch *routeMethod
|
||||||
|
post *routeMethod
|
||||||
|
propfind *routeMethod
|
||||||
|
put *routeMethod
|
||||||
|
trace *routeMethod
|
||||||
|
report *routeMethod
|
||||||
|
anyOther map[string]*routeMethod
|
||||||
allowHeader string
|
allowHeader string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -56,7 +66,7 @@ const (
|
|||||||
anyLabel = byte('*')
|
anyLabel = byte('*')
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *methodHandler) isHandler() bool {
|
func (m *routeMethods) isHandler() bool {
|
||||||
return m.connect != nil ||
|
return m.connect != nil ||
|
||||||
m.delete != nil ||
|
m.delete != nil ||
|
||||||
m.get != nil ||
|
m.get != nil ||
|
||||||
@ -67,10 +77,12 @@ func (m *methodHandler) isHandler() bool {
|
|||||||
m.propfind != nil ||
|
m.propfind != nil ||
|
||||||
m.put != nil ||
|
m.put != nil ||
|
||||||
m.trace != nil ||
|
m.trace != nil ||
|
||||||
m.report != nil
|
m.report != nil ||
|
||||||
|
len(m.anyOther) != 0
|
||||||
|
// RouteNotFound/404 is not considered as a handler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *methodHandler) updateAllowHeader() {
|
func (m *routeMethods) updateAllowHeader() {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
buf.WriteString(http.MethodOptions)
|
buf.WriteString(http.MethodOptions)
|
||||||
|
|
||||||
@ -112,6 +124,10 @@ func (m *methodHandler) updateAllowHeader() {
|
|||||||
if m.report != nil {
|
if m.report != nil {
|
||||||
buf.WriteString(", REPORT")
|
buf.WriteString(", REPORT")
|
||||||
}
|
}
|
||||||
|
for method := range m.anyOther { // for simplicity, we use map and therefore order is not deterministic here
|
||||||
|
buf.WriteString(", ")
|
||||||
|
buf.WriteString(method)
|
||||||
|
}
|
||||||
m.allowHeader = buf.String()
|
m.allowHeader = buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,13 +135,58 @@ func (m *methodHandler) updateAllowHeader() {
|
|||||||
func NewRouter(e *Echo) *Router {
|
func NewRouter(e *Echo) *Router {
|
||||||
return &Router{
|
return &Router{
|
||||||
tree: &node{
|
tree: &node{
|
||||||
methodHandler: new(methodHandler),
|
methods: new(routeMethods),
|
||||||
},
|
},
|
||||||
routes: map[string]*Route{},
|
routes: map[string]*Route{},
|
||||||
echo: e,
|
echo: e,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Routes returns the registered routes.
|
||||||
|
func (r *Router) Routes() []*Route {
|
||||||
|
routes := make([]*Route, 0, len(r.routes))
|
||||||
|
for _, v := range r.routes {
|
||||||
|
routes = append(routes, v)
|
||||||
|
}
|
||||||
|
return routes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverse generates an URL from route name and provided parameters.
|
||||||
|
func (r *Router) Reverse(name string, params ...interface{}) string {
|
||||||
|
uri := new(bytes.Buffer)
|
||||||
|
ln := len(params)
|
||||||
|
n := 0
|
||||||
|
for _, route := range r.routes {
|
||||||
|
if route.Name == name {
|
||||||
|
for i, l := 0, len(route.Path); i < l; i++ {
|
||||||
|
if (route.Path[i] == ':' || route.Path[i] == '*') && n < ln {
|
||||||
|
for ; i < l && route.Path[i] != '/'; i++ {
|
||||||
|
}
|
||||||
|
uri.WriteString(fmt.Sprintf("%v", params[n]))
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
if i < l {
|
||||||
|
uri.WriteByte(route.Path[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uri.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Router) add(method, path, name string, h HandlerFunc) *Route {
|
||||||
|
r.Add(method, path, h)
|
||||||
|
|
||||||
|
route := &Route{
|
||||||
|
Method: method,
|
||||||
|
Path: path,
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
r.routes[method+path] = route
|
||||||
|
return 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
|
// Validate path
|
||||||
@ -153,7 +214,7 @@ func (r *Router) Add(method, path string, h HandlerFunc) {
|
|||||||
}
|
}
|
||||||
j := i + 1
|
j := i + 1
|
||||||
|
|
||||||
r.insert(method, path[:i], nil, staticKind, "", nil)
|
r.insert(method, path[:i], staticKind, routeMethod{})
|
||||||
for ; i < lcpIndex && path[i] != '/'; i++ {
|
for ; i < lcpIndex && path[i] != '/'; i++ {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,23 +224,23 @@ 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], h, paramKind, ppath, pnames)
|
r.insert(method, path[:i], paramKind, routeMethod{ppath, pnames, h})
|
||||||
} else {
|
} else {
|
||||||
r.insert(method, path[:i], nil, paramKind, "", nil)
|
r.insert(method, path[:i], paramKind, routeMethod{})
|
||||||
}
|
}
|
||||||
} else if path[i] == '*' {
|
} else if path[i] == '*' {
|
||||||
r.insert(method, path[:i], nil, staticKind, "", nil)
|
r.insert(method, path[:i], staticKind, routeMethod{})
|
||||||
pnames = append(pnames, "*")
|
pnames = append(pnames, "*")
|
||||||
r.insert(method, path[:i+1], h, anyKind, ppath, pnames)
|
r.insert(method, path[:i+1], anyKind, routeMethod{ppath, pnames, h})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.insert(method, path, h, staticKind, ppath, pnames)
|
r.insert(method, path, staticKind, routeMethod{ppath, pnames, h})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string, pnames []string) {
|
func (r *Router) insert(method, path string, t kind, rm routeMethod) {
|
||||||
// Adjust max param
|
// Adjust max param
|
||||||
paramLen := len(pnames)
|
paramLen := len(rm.pnames)
|
||||||
if *r.echo.maxParam < paramLen {
|
if *r.echo.maxParam < paramLen {
|
||||||
*r.echo.maxParam = paramLen
|
*r.echo.maxParam = paramLen
|
||||||
}
|
}
|
||||||
@ -207,25 +268,31 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
|||||||
// At root node
|
// At root node
|
||||||
currentNode.label = search[0]
|
currentNode.label = search[0]
|
||||||
currentNode.prefix = search
|
currentNode.prefix = search
|
||||||
if h != nil {
|
if rm.handler != nil {
|
||||||
currentNode.kind = t
|
currentNode.kind = t
|
||||||
currentNode.addHandler(method, h)
|
currentNode.addMethod(method, &rm)
|
||||||
currentNode.ppath = ppath
|
currentNode.paramsCount = len(rm.pnames)
|
||||||
currentNode.pnames = pnames
|
currentNode.originalPath = rm.ppath
|
||||||
}
|
}
|
||||||
currentNode.isLeaf = currentNode.staticChildren == nil && currentNode.paramChild == nil && currentNode.anyChild == nil
|
currentNode.isLeaf = currentNode.staticChildren == nil && currentNode.paramChild == nil && currentNode.anyChild == nil
|
||||||
} else if lcpLen < prefixLen {
|
} else if lcpLen < prefixLen {
|
||||||
// Split node
|
// Split node into two before we insert new node.
|
||||||
|
// This happens when we are inserting path that is submatch of any existing inserted paths.
|
||||||
|
// For example, we have node `/test` and now are about to insert `/te/*`. In that case
|
||||||
|
// 1. overlapping part is `/te` that is used as parent node
|
||||||
|
// 2. `st` is part from existing node that is not matching - it gets its own node (child to `/te`)
|
||||||
|
// 3. `/*` is the new part we are about to insert (child to `/te`)
|
||||||
n := newNode(
|
n := newNode(
|
||||||
currentNode.kind,
|
currentNode.kind,
|
||||||
currentNode.prefix[lcpLen:],
|
currentNode.prefix[lcpLen:],
|
||||||
currentNode,
|
currentNode,
|
||||||
currentNode.staticChildren,
|
currentNode.staticChildren,
|
||||||
currentNode.methodHandler,
|
currentNode.originalPath,
|
||||||
currentNode.ppath,
|
currentNode.methods,
|
||||||
currentNode.pnames,
|
currentNode.paramsCount,
|
||||||
currentNode.paramChild,
|
currentNode.paramChild,
|
||||||
currentNode.anyChild,
|
currentNode.anyChild,
|
||||||
|
currentNode.notFoundHandler,
|
||||||
)
|
)
|
||||||
// Update parent path for all children to new node
|
// Update parent path for all children to new node
|
||||||
for _, child := range currentNode.staticChildren {
|
for _, child := range currentNode.staticChildren {
|
||||||
@ -243,13 +310,14 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
|||||||
currentNode.label = currentNode.prefix[0]
|
currentNode.label = currentNode.prefix[0]
|
||||||
currentNode.prefix = currentNode.prefix[:lcpLen]
|
currentNode.prefix = currentNode.prefix[:lcpLen]
|
||||||
currentNode.staticChildren = nil
|
currentNode.staticChildren = nil
|
||||||
currentNode.methodHandler = new(methodHandler)
|
currentNode.originalPath = ""
|
||||||
currentNode.ppath = ""
|
currentNode.methods = new(routeMethods)
|
||||||
currentNode.pnames = nil
|
currentNode.paramsCount = 0
|
||||||
currentNode.paramChild = nil
|
currentNode.paramChild = nil
|
||||||
currentNode.anyChild = nil
|
currentNode.anyChild = nil
|
||||||
currentNode.isLeaf = false
|
currentNode.isLeaf = false
|
||||||
currentNode.isHandler = false
|
currentNode.isHandler = false
|
||||||
|
currentNode.notFoundHandler = nil
|
||||||
|
|
||||||
// Only Static children could reach here
|
// Only Static children could reach here
|
||||||
currentNode.addStaticChild(n)
|
currentNode.addStaticChild(n)
|
||||||
@ -257,13 +325,19 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
|||||||
if lcpLen == searchLen {
|
if lcpLen == searchLen {
|
||||||
// At parent node
|
// At parent node
|
||||||
currentNode.kind = t
|
currentNode.kind = t
|
||||||
currentNode.addHandler(method, h)
|
if rm.handler != nil {
|
||||||
currentNode.ppath = ppath
|
currentNode.addMethod(method, &rm)
|
||||||
currentNode.pnames = pnames
|
currentNode.paramsCount = len(rm.pnames)
|
||||||
|
currentNode.originalPath = rm.ppath
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Create child node
|
// Create child node
|
||||||
n = newNode(t, search[lcpLen:], currentNode, nil, new(methodHandler), ppath, pnames, nil, nil)
|
n = newNode(t, search[lcpLen:], currentNode, nil, "", new(routeMethods), 0, nil, nil, nil)
|
||||||
n.addHandler(method, h)
|
if rm.handler != nil {
|
||||||
|
n.addMethod(method, &rm)
|
||||||
|
n.paramsCount = len(rm.pnames)
|
||||||
|
n.originalPath = rm.ppath
|
||||||
|
}
|
||||||
// Only Static children could reach here
|
// Only Static children could reach here
|
||||||
currentNode.addStaticChild(n)
|
currentNode.addStaticChild(n)
|
||||||
}
|
}
|
||||||
@ -277,8 +351,12 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Create child node
|
// Create child node
|
||||||
n := newNode(t, search, currentNode, nil, new(methodHandler), ppath, pnames, nil, nil)
|
n := newNode(t, search, currentNode, nil, rm.ppath, new(routeMethods), 0, nil, nil, nil)
|
||||||
n.addHandler(method, h)
|
if rm.handler != nil {
|
||||||
|
n.addMethod(method, &rm)
|
||||||
|
n.paramsCount = len(rm.pnames)
|
||||||
|
}
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case staticKind:
|
case staticKind:
|
||||||
currentNode.addStaticChild(n)
|
currentNode.addStaticChild(n)
|
||||||
@ -290,32 +368,42 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
|
|||||||
currentNode.isLeaf = currentNode.staticChildren == nil && currentNode.paramChild == nil && currentNode.anyChild == nil
|
currentNode.isLeaf = currentNode.staticChildren == nil && currentNode.paramChild == nil && currentNode.anyChild == nil
|
||||||
} else {
|
} else {
|
||||||
// Node already exists
|
// Node already exists
|
||||||
if h != nil {
|
if rm.handler != nil {
|
||||||
currentNode.addHandler(method, h)
|
currentNode.addMethod(method, &rm)
|
||||||
currentNode.ppath = ppath
|
currentNode.paramsCount = len(rm.pnames)
|
||||||
if len(currentNode.pnames) == 0 { // Issue #729
|
currentNode.originalPath = rm.ppath
|
||||||
currentNode.pnames = pnames
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNode(t kind, pre string, p *node, sc children, mh *methodHandler, ppath string, pnames []string, paramChildren, anyChildren *node) *node {
|
func newNode(
|
||||||
|
t kind,
|
||||||
|
pre string,
|
||||||
|
p *node,
|
||||||
|
sc children,
|
||||||
|
originalPath string,
|
||||||
|
methods *routeMethods,
|
||||||
|
paramsCount int,
|
||||||
|
paramChildren,
|
||||||
|
anyChildren *node,
|
||||||
|
notFoundHandler *routeMethod,
|
||||||
|
) *node {
|
||||||
return &node{
|
return &node{
|
||||||
kind: t,
|
kind: t,
|
||||||
label: pre[0],
|
label: pre[0],
|
||||||
prefix: pre,
|
prefix: pre,
|
||||||
parent: p,
|
parent: p,
|
||||||
staticChildren: sc,
|
staticChildren: sc,
|
||||||
ppath: ppath,
|
originalPath: originalPath,
|
||||||
pnames: pnames,
|
methods: methods,
|
||||||
methodHandler: mh,
|
paramsCount: paramsCount,
|
||||||
paramChild: paramChildren,
|
paramChild: paramChildren,
|
||||||
anyChild: anyChildren,
|
anyChild: anyChildren,
|
||||||
isLeaf: sc == nil && paramChildren == nil && anyChildren == nil,
|
isLeaf: sc == nil && paramChildren == nil && anyChildren == nil,
|
||||||
isHandler: mh.isHandler(),
|
isHandler: methods.isHandler(),
|
||||||
|
notFoundHandler: notFoundHandler,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,10 +421,8 @@ func (n *node) findStaticChild(l byte) *node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) findChildWithLabel(l byte) *node {
|
func (n *node) findChildWithLabel(l byte) *node {
|
||||||
for _, c := range n.staticChildren {
|
if c := n.findStaticChild(l); c != nil {
|
||||||
if c.label == l {
|
return c
|
||||||
return c
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if l == paramLabel {
|
if l == paramLabel {
|
||||||
return n.paramChild
|
return n.paramChild
|
||||||
@ -347,66 +433,74 @@ func (n *node) findChildWithLabel(l byte) *node {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) addHandler(method string, h HandlerFunc) {
|
func (n *node) addMethod(method string, h *routeMethod) {
|
||||||
switch method {
|
switch method {
|
||||||
case http.MethodConnect:
|
case http.MethodConnect:
|
||||||
n.methodHandler.connect = h
|
n.methods.connect = h
|
||||||
case http.MethodDelete:
|
case http.MethodDelete:
|
||||||
n.methodHandler.delete = h
|
n.methods.delete = h
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
n.methodHandler.get = h
|
n.methods.get = h
|
||||||
case http.MethodHead:
|
case http.MethodHead:
|
||||||
n.methodHandler.head = h
|
n.methods.head = h
|
||||||
case http.MethodOptions:
|
case http.MethodOptions:
|
||||||
n.methodHandler.options = h
|
n.methods.options = h
|
||||||
case http.MethodPatch:
|
case http.MethodPatch:
|
||||||
n.methodHandler.patch = h
|
n.methods.patch = h
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
n.methodHandler.post = h
|
n.methods.post = h
|
||||||
case PROPFIND:
|
case PROPFIND:
|
||||||
n.methodHandler.propfind = h
|
n.methods.propfind = h
|
||||||
case http.MethodPut:
|
case http.MethodPut:
|
||||||
n.methodHandler.put = h
|
n.methods.put = h
|
||||||
case http.MethodTrace:
|
case http.MethodTrace:
|
||||||
n.methodHandler.trace = h
|
n.methods.trace = h
|
||||||
case REPORT:
|
case REPORT:
|
||||||
n.methodHandler.report = h
|
n.methods.report = h
|
||||||
|
case RouteNotFound:
|
||||||
|
n.notFoundHandler = h
|
||||||
|
return // RouteNotFound/404 is not considered as a handler so no further logic needs to be executed
|
||||||
|
default:
|
||||||
|
if n.methods.anyOther == nil {
|
||||||
|
n.methods.anyOther = make(map[string]*routeMethod)
|
||||||
|
}
|
||||||
|
if h.handler == nil {
|
||||||
|
delete(n.methods.anyOther, method)
|
||||||
|
} else {
|
||||||
|
n.methods.anyOther[method] = h
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n.methodHandler.updateAllowHeader()
|
n.methods.updateAllowHeader()
|
||||||
if h != nil {
|
n.isHandler = true
|
||||||
n.isHandler = true
|
|
||||||
} else {
|
|
||||||
n.isHandler = n.methodHandler.isHandler()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) findHandler(method string) HandlerFunc {
|
func (n *node) findMethod(method string) *routeMethod {
|
||||||
switch method {
|
switch method {
|
||||||
case http.MethodConnect:
|
case http.MethodConnect:
|
||||||
return n.methodHandler.connect
|
return n.methods.connect
|
||||||
case http.MethodDelete:
|
case http.MethodDelete:
|
||||||
return n.methodHandler.delete
|
return n.methods.delete
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
return n.methodHandler.get
|
return n.methods.get
|
||||||
case http.MethodHead:
|
case http.MethodHead:
|
||||||
return n.methodHandler.head
|
return n.methods.head
|
||||||
case http.MethodOptions:
|
case http.MethodOptions:
|
||||||
return n.methodHandler.options
|
return n.methods.options
|
||||||
case http.MethodPatch:
|
case http.MethodPatch:
|
||||||
return n.methodHandler.patch
|
return n.methods.patch
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
return n.methodHandler.post
|
return n.methods.post
|
||||||
case PROPFIND:
|
case PROPFIND:
|
||||||
return n.methodHandler.propfind
|
return n.methods.propfind
|
||||||
case http.MethodPut:
|
case http.MethodPut:
|
||||||
return n.methodHandler.put
|
return n.methods.put
|
||||||
case http.MethodTrace:
|
case http.MethodTrace:
|
||||||
return n.methodHandler.trace
|
return n.methods.trace
|
||||||
case REPORT:
|
case REPORT:
|
||||||
return n.methodHandler.report
|
return n.methods.report
|
||||||
default:
|
default: // RouteNotFound/404 is not considered as a handler
|
||||||
return nil
|
return n.methods.anyOther[method]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +529,7 @@ func (r *Router) Find(method, path string, c Context) {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
previousBestMatchNode *node
|
previousBestMatchNode *node
|
||||||
matchedHandler HandlerFunc
|
matchedRouteMethod *routeMethod
|
||||||
// search stores the remaining path to check for match. By each iteration we move from start of path to end of the path
|
// search stores the remaining path to check for match. By each iteration we move from start of path to end of the path
|
||||||
// and search value gets shorter and shorter.
|
// and search value gets shorter and shorter.
|
||||||
search = path
|
search = path
|
||||||
@ -508,7 +602,7 @@ func (r *Router) Find(method, path string, c Context) {
|
|||||||
// No matching prefix, let's backtrack to the first possible alternative node of the decision path
|
// No matching prefix, let's backtrack to the first possible alternative node of the decision path
|
||||||
nk, ok := backtrackToNextNodeKind(staticKind)
|
nk, ok := backtrackToNextNodeKind(staticKind)
|
||||||
if !ok {
|
if !ok {
|
||||||
return // No other possibilities on the decision path
|
return // No other possibilities on the decision path, handler will be whatever context is reset to.
|
||||||
} else if nk == paramKind {
|
} else if nk == paramKind {
|
||||||
goto Param
|
goto Param
|
||||||
// NOTE: this case (backtracking from static node to previous any node) can not happen by current any matching logic. Any node is end of search currently
|
// NOTE: this case (backtracking from static node to previous any node) can not happen by current any matching logic. Any node is end of search currently
|
||||||
@ -524,15 +618,21 @@ func (r *Router) Find(method, path string, c Context) {
|
|||||||
search = search[lcpLen:]
|
search = search[lcpLen:]
|
||||||
searchIndex = searchIndex + lcpLen
|
searchIndex = searchIndex + lcpLen
|
||||||
|
|
||||||
// Finish routing if no remaining search and we are on a node with handler and matching method type
|
// Finish routing if is no request path remaining to search
|
||||||
if search == "" && currentNode.isHandler {
|
if search == "" {
|
||||||
// check if current node has handler registered for http method we are looking for. we store currentNode as
|
// in case of node that is handler we have exact method type match or something for 405 to use
|
||||||
// best matching in case we do no find no more routes matching this path+method
|
if currentNode.isHandler {
|
||||||
if previousBestMatchNode == nil {
|
// check if current node has handler registered for http method we are looking for. we store currentNode as
|
||||||
previousBestMatchNode = currentNode
|
// best matching in case we do no find no more routes matching this path+method
|
||||||
}
|
if previousBestMatchNode == nil {
|
||||||
if h := currentNode.findHandler(method); h != nil {
|
previousBestMatchNode = currentNode
|
||||||
matchedHandler = h
|
}
|
||||||
|
if h := currentNode.findMethod(method); h != nil {
|
||||||
|
matchedRouteMethod = h
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else if currentNode.notFoundHandler != nil {
|
||||||
|
matchedRouteMethod = currentNode.notFoundHandler
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -552,7 +652,8 @@ func (r *Router) Find(method, path string, c Context) {
|
|||||||
i := 0
|
i := 0
|
||||||
l := len(search)
|
l := len(search)
|
||||||
if currentNode.isLeaf {
|
if currentNode.isLeaf {
|
||||||
// when param node does not have any children then param node should act similarly to any node - consider all remaining search as match
|
// when param node does not have any children (path param is last piece of route path) then param node should
|
||||||
|
// act similarly to any node - consider all remaining search as match
|
||||||
i = l
|
i = l
|
||||||
} else {
|
} else {
|
||||||
for ; i < l && search[i] != '/'; i++ {
|
for ; i < l && search[i] != '/'; i++ {
|
||||||
@ -571,19 +672,23 @@ func (r *Router) Find(method, path string, c Context) {
|
|||||||
if child := currentNode.anyChild; child != nil {
|
if child := currentNode.anyChild; child != nil {
|
||||||
// If any node is found, use remaining path for paramValues
|
// If any node is found, use remaining path for paramValues
|
||||||
currentNode = child
|
currentNode = child
|
||||||
paramValues[len(currentNode.pnames)-1] = search
|
paramValues[currentNode.paramsCount-1] = search
|
||||||
|
|
||||||
// update indexes/search in case we need to backtrack when no handler match is found
|
// update indexes/search in case we need to backtrack when no handler match is found
|
||||||
paramIndex++
|
paramIndex++
|
||||||
searchIndex += +len(search)
|
searchIndex += +len(search)
|
||||||
search = ""
|
search = ""
|
||||||
|
|
||||||
// check if current node has handler registered for http method we are looking for. we store currentNode as
|
if h := currentNode.findMethod(method); h != nil {
|
||||||
// best matching in case we do no find no more routes matching this path+method
|
matchedRouteMethod = h
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// we store currentNode as best matching in case we do not find more routes matching this path+method. Needed for 405
|
||||||
if previousBestMatchNode == nil {
|
if previousBestMatchNode == nil {
|
||||||
previousBestMatchNode = currentNode
|
previousBestMatchNode = currentNode
|
||||||
}
|
}
|
||||||
if h := currentNode.findHandler(method); h != nil {
|
if currentNode.notFoundHandler != nil {
|
||||||
matchedHandler = h
|
matchedRouteMethod = currentNode.notFoundHandler
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -606,22 +711,34 @@ func (r *Router) Find(method, path string, c Context) {
|
|||||||
return // nothing matched at all
|
return // nothing matched at all
|
||||||
}
|
}
|
||||||
|
|
||||||
if matchedHandler != nil {
|
// matchedHandler could be method+path handler that we matched or notFoundHandler from node with matching path
|
||||||
ctx.handler = matchedHandler
|
// user provided not found (404) handler has priority over generic method not found (405) handler or global 404 handler
|
||||||
|
var rPath string
|
||||||
|
var rPNames []string
|
||||||
|
if matchedRouteMethod != nil {
|
||||||
|
rPath = matchedRouteMethod.ppath
|
||||||
|
rPNames = matchedRouteMethod.pnames
|
||||||
|
ctx.handler = matchedRouteMethod.handler
|
||||||
} else {
|
} else {
|
||||||
// use previous match as basis. although we have no matching handler we have path match.
|
// use previous match as basis. although we have no matching handler we have path match.
|
||||||
// so we can send http.StatusMethodNotAllowed (405) instead of http.StatusNotFound (404)
|
// so we can send http.StatusMethodNotAllowed (405) instead of http.StatusNotFound (404)
|
||||||
currentNode = previousBestMatchNode
|
currentNode = previousBestMatchNode
|
||||||
|
|
||||||
|
rPath = currentNode.originalPath
|
||||||
|
rPNames = nil // no params here
|
||||||
ctx.handler = NotFoundHandler
|
ctx.handler = NotFoundHandler
|
||||||
if currentNode.isHandler {
|
if currentNode.notFoundHandler != nil {
|
||||||
ctx.Set(ContextKeyHeaderAllow, currentNode.methodHandler.allowHeader)
|
rPath = currentNode.notFoundHandler.ppath
|
||||||
|
rPNames = currentNode.notFoundHandler.pnames
|
||||||
|
ctx.handler = currentNode.notFoundHandler.handler
|
||||||
|
} else if currentNode.isHandler {
|
||||||
|
ctx.Set(ContextKeyHeaderAllow, currentNode.methods.allowHeader)
|
||||||
ctx.handler = MethodNotAllowedHandler
|
ctx.handler = MethodNotAllowedHandler
|
||||||
if method == http.MethodOptions {
|
if method == http.MethodOptions {
|
||||||
ctx.handler = optionsMethodHandler(currentNode.methodHandler.allowHeader)
|
ctx.handler = optionsMethodHandler(currentNode.methods.allowHeader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.path = currentNode.ppath
|
ctx.path = rPath
|
||||||
ctx.pnames = currentNode.pnames
|
ctx.pnames = rPNames
|
||||||
}
|
}
|
||||||
|
6
vendor/github.com/labstack/gommon/log/log.go
generated
vendored
6
vendor/github.com/labstack/gommon/log/log.go
generated
vendored
@ -391,7 +391,7 @@ func (l *Logger) log(level Lvl, format string, args ...interface{}) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
s := buf.String()
|
s := buf.String()
|
||||||
i := buf.Len() - 1
|
i := buf.Len() - 1
|
||||||
if s[i] == '}' {
|
if i >= 0 && s[i] == '}' {
|
||||||
// JSON header
|
// JSON header
|
||||||
buf.Truncate(i)
|
buf.Truncate(i)
|
||||||
buf.WriteByte(',')
|
buf.WriteByte(',')
|
||||||
@ -404,7 +404,9 @@ func (l *Logger) log(level Lvl, format string, args ...interface{}) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Text header
|
// Text header
|
||||||
buf.WriteByte(' ')
|
if len(s) > 0 {
|
||||||
|
buf.WriteByte(' ')
|
||||||
|
}
|
||||||
buf.WriteString(message)
|
buf.WriteString(message)
|
||||||
}
|
}
|
||||||
buf.WriteByte('\n')
|
buf.WriteByte('\n')
|
||||||
|
4
vendor/github.com/lib/pq/conn.go
generated
vendored
4
vendor/github.com/lib/pq/conn.go
generated
vendored
@ -1127,7 +1127,7 @@ func isDriverSetting(key string) bool {
|
|||||||
return true
|
return true
|
||||||
case "password":
|
case "password":
|
||||||
return true
|
return true
|
||||||
case "sslmode", "sslcert", "sslkey", "sslrootcert", "sslinline":
|
case "sslmode", "sslcert", "sslkey", "sslrootcert", "sslinline", "sslsni":
|
||||||
return true
|
return true
|
||||||
case "fallback_application_name":
|
case "fallback_application_name":
|
||||||
return true
|
return true
|
||||||
@ -2020,6 +2020,8 @@ func parseEnviron(env []string) (out map[string]string) {
|
|||||||
accrue("sslkey")
|
accrue("sslkey")
|
||||||
case "PGSSLROOTCERT":
|
case "PGSSLROOTCERT":
|
||||||
accrue("sslrootcert")
|
accrue("sslrootcert")
|
||||||
|
case "PGSSLSNI":
|
||||||
|
accrue("sslsni")
|
||||||
case "PGREQUIRESSL", "PGSSLCRL":
|
case "PGREQUIRESSL", "PGSSLCRL":
|
||||||
unsupported()
|
unsupported()
|
||||||
case "PGREQUIREPEER":
|
case "PGREQUIREPEER":
|
||||||
|
2
vendor/github.com/lib/pq/error.go
generated
vendored
2
vendor/github.com/lib/pq/error.go
generated
vendored
@ -449,7 +449,7 @@ func (err *Error) Get(k byte) (v string) {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err Error) Error() string {
|
func (err *Error) Error() string {
|
||||||
return "pq: " + err.Message
|
return "pq: " + err.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
vendor/github.com/lib/pq/ssl.go
generated
vendored
11
vendor/github.com/lib/pq/ssl.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ssl generates a function to upgrade a net.Conn based on the "sslmode" and
|
// ssl generates a function to upgrade a net.Conn based on the "sslmode" and
|
||||||
@ -50,6 +51,16 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
|
|||||||
return nil, fmterrorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode)
|
return nil, fmterrorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set Server Name Indication (SNI), if enabled by connection parameters.
|
||||||
|
// By default SNI is on, any value which is not starting with "1" disables
|
||||||
|
// SNI -- that is the same check vanilla libpq uses.
|
||||||
|
if sslsni := o["sslsni"]; sslsni == "" || strings.HasPrefix(sslsni, "1") {
|
||||||
|
// RFC 6066 asks to not set SNI if the host is a literal IP address (IPv4
|
||||||
|
// or IPv6). This check is coded already crypto.tls.hostnameInSNI, so
|
||||||
|
// just always set ServerName here and let crypto/tls do the filtering.
|
||||||
|
tlsConf.ServerName = o["host"]
|
||||||
|
}
|
||||||
|
|
||||||
err := sslClientCertificates(&tlsConf, o)
|
err := sslClientCertificates(&tlsConf, o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
4
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
4
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
//go:build (darwin || freebsd || openbsd || netbsd || dragonfly) && !appengine
|
//go:build (darwin || freebsd || openbsd || netbsd || dragonfly || hurd) && !appengine
|
||||||
// +build darwin freebsd openbsd netbsd dragonfly
|
// +build darwin freebsd openbsd netbsd dragonfly hurd
|
||||||
// +build !appengine
|
// +build !appengine
|
||||||
|
|
||||||
package isatty
|
package isatty
|
||||||
|
3
vendor/github.com/valyala/fasttemplate/template.go
generated
vendored
3
vendor/github.com/valyala/fasttemplate/template.go
generated
vendored
@ -112,8 +112,7 @@ func ExecuteFuncString(template, startTag, endTag string, f TagFunc) string {
|
|||||||
// but when f returns an error, ExecuteFuncStringWithErr won't panic like ExecuteFuncString
|
// but when f returns an error, ExecuteFuncStringWithErr won't panic like ExecuteFuncString
|
||||||
// it just returns an empty string and the error f returned
|
// it just returns an empty string and the error f returned
|
||||||
func ExecuteFuncStringWithErr(template, startTag, endTag string, f TagFunc) (string, error) {
|
func ExecuteFuncStringWithErr(template, startTag, endTag string, f TagFunc) (string, error) {
|
||||||
tagsCount := bytes.Count(unsafeString2Bytes(template), unsafeString2Bytes(startTag))
|
if n := bytes.Index(unsafeString2Bytes(template), unsafeString2Bytes(startTag)); n < 0 {
|
||||||
if tagsCount == 0 {
|
|
||||||
return template, nil
|
return template, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
3
vendor/golang.org/x/crypto/AUTHORS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# This source code refers to The Go Authors for copyright purposes.
|
|
||||||
# The master list of authors is in the main Go distribution,
|
|
||||||
# visible at https://tip.golang.org/AUTHORS.
|
|
3
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
3
vendor/golang.org/x/crypto/CONTRIBUTORS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# This source code was written by the Go contributors.
|
|
||||||
# The master list of contributors is in the main Go distribution,
|
|
||||||
# visible at https://tip.golang.org/CONTRIBUTORS.
|
|
8
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
8
vendor/golang.org/x/crypto/acme/acme.go
generated
vendored
@ -88,7 +88,7 @@ type Client struct {
|
|||||||
//
|
//
|
||||||
// The following algorithms are supported:
|
// The following algorithms are supported:
|
||||||
// RS256, ES256, ES384 and ES512.
|
// RS256, ES256, ES384 and ES512.
|
||||||
// See RFC7518 for more details about the algorithms.
|
// See RFC 7518 for more details about the algorithms.
|
||||||
Key crypto.Signer
|
Key crypto.Signer
|
||||||
|
|
||||||
// HTTPClient optionally specifies an HTTP client to use
|
// HTTPClient optionally specifies an HTTP client to use
|
||||||
@ -310,9 +310,9 @@ func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error)
|
|||||||
// On success client's Key is updated which is not concurrency safe.
|
// On success client's Key is updated which is not concurrency safe.
|
||||||
// On failure an error will be returned.
|
// On failure an error will be returned.
|
||||||
// The new key is already registered with the ACME provider if the following is true:
|
// The new key is already registered with the ACME provider if the following is true:
|
||||||
// - error is of type acme.Error
|
// - error is of type acme.Error
|
||||||
// - StatusCode should be 409 (Conflict)
|
// - StatusCode should be 409 (Conflict)
|
||||||
// - Location header will have the KID of the associated account
|
// - Location header will have the KID of the associated account
|
||||||
//
|
//
|
||||||
// More about account key rollover can be found at
|
// More about account key rollover can be found at
|
||||||
// https://tools.ietf.org/html/rfc8555#section-7.3.5.
|
// https://tools.ietf.org/html/rfc8555#section-7.3.5.
|
||||||
|
4
vendor/golang.org/x/crypto/acme/autocert/autocert.go
generated
vendored
4
vendor/golang.org/x/crypto/acme/autocert/autocert.go
generated
vendored
@ -463,7 +463,7 @@ func (m *Manager) cert(ctx context.Context, ck certKey) (*tls.Certificate, error
|
|||||||
leaf: cert.Leaf,
|
leaf: cert.Leaf,
|
||||||
}
|
}
|
||||||
m.state[ck] = s
|
m.state[ck] = s
|
||||||
go m.startRenew(ck, s.key, s.leaf.NotAfter)
|
m.startRenew(ck, s.key, s.leaf.NotAfter)
|
||||||
return cert, nil
|
return cert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +609,7 @@ func (m *Manager) createCert(ctx context.Context, ck certKey) (*tls.Certificate,
|
|||||||
}
|
}
|
||||||
state.cert = der
|
state.cert = der
|
||||||
state.leaf = leaf
|
state.leaf = leaf
|
||||||
go m.startRenew(ck, state.key, state.leaf.NotAfter)
|
m.startRenew(ck, state.key, state.leaf.NotAfter)
|
||||||
return state.tlscert()
|
return state.tlscert()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
vendor/golang.org/x/crypto/acme/autocert/cache.go
generated
vendored
5
vendor/golang.org/x/crypto/acme/autocert/cache.go
generated
vendored
@ -7,7 +7,6 @@ package autocert
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
@ -48,7 +47,7 @@ func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) {
|
|||||||
done = make(chan struct{})
|
done = make(chan struct{})
|
||||||
)
|
)
|
||||||
go func() {
|
go func() {
|
||||||
data, err = ioutil.ReadFile(name)
|
data, err = os.ReadFile(name)
|
||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
select {
|
select {
|
||||||
@ -119,7 +118,7 @@ func (d DirCache) Delete(ctx context.Context, name string) error {
|
|||||||
// writeTempFile writes b to a temporary file, closes the file and returns its path.
|
// writeTempFile writes b to a temporary file, closes the file and returns its path.
|
||||||
func (d DirCache) writeTempFile(prefix string, b []byte) (name string, reterr error) {
|
func (d DirCache) writeTempFile(prefix string, b []byte) (name string, reterr error) {
|
||||||
// TempFile uses 0600 permissions
|
// TempFile uses 0600 permissions
|
||||||
f, err := ioutil.TempFile(string(d), prefix)
|
f, err := os.CreateTemp(string(d), prefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
6
vendor/golang.org/x/crypto/acme/http.go
generated
vendored
6
vendor/golang.org/x/crypto/acme/http.go
generated
vendored
@ -12,7 +12,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -156,7 +156,7 @@ func (c *Client) get(ctx context.Context, url string, ok resOkay) (*http.Respons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// postAsGet is POST-as-GET, a replacement for GET in RFC8555
|
// postAsGet is POST-as-GET, a replacement for GET in RFC 8555
|
||||||
// as described in https://tools.ietf.org/html/rfc8555#section-6.3.
|
// as described in https://tools.ietf.org/html/rfc8555#section-6.3.
|
||||||
// It makes a POST request in KID form with zero JWS payload.
|
// It makes a POST request in KID form with zero JWS payload.
|
||||||
// See nopayload doc comments in jws.go.
|
// See nopayload doc comments in jws.go.
|
||||||
@ -310,7 +310,7 @@ func isRetriable(code int) bool {
|
|||||||
func responseError(resp *http.Response) error {
|
func responseError(resp *http.Response) error {
|
||||||
// don't care if ReadAll returns an error:
|
// don't care if ReadAll returns an error:
|
||||||
// json.Unmarshal will fail in that case anyway
|
// json.Unmarshal will fail in that case anyway
|
||||||
b, _ := ioutil.ReadAll(resp.Body)
|
b, _ := io.ReadAll(resp.Body)
|
||||||
e := &wireError{Status: resp.StatusCode}
|
e := &wireError{Status: resp.StatusCode}
|
||||||
if err := json.Unmarshal(b, e); err != nil {
|
if err := json.Unmarshal(b, e); err != nil {
|
||||||
// this is not a regular error response:
|
// this is not a regular error response:
|
||||||
|
5
vendor/golang.org/x/crypto/acme/rfc8555.go
generated
vendored
5
vendor/golang.org/x/crypto/acme/rfc8555.go
generated
vendored
@ -13,7 +13,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -390,7 +389,7 @@ func (c *Client) fetchCertRFC(ctx context.Context, url string, bundle bool) ([][
|
|||||||
// Get all the bytes up to a sane maximum.
|
// Get all the bytes up to a sane maximum.
|
||||||
// Account very roughly for base64 overhead.
|
// Account very roughly for base64 overhead.
|
||||||
const max = maxCertChainSize + maxCertChainSize/33
|
const max = maxCertChainSize + maxCertChainSize/33
|
||||||
b, err := ioutil.ReadAll(io.LimitReader(res.Body, max+1))
|
b, err := io.ReadAll(io.LimitReader(res.Body, max+1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("acme: fetch cert response stream: %v", err)
|
return nil, fmt.Errorf("acme: fetch cert response stream: %v", err)
|
||||||
}
|
}
|
||||||
@ -469,7 +468,7 @@ func (c *Client) ListCertAlternates(ctx context.Context, url string) ([]string,
|
|||||||
|
|
||||||
// We don't need the body but we need to discard it so we don't end up
|
// We don't need the body but we need to discard it so we don't end up
|
||||||
// preventing keep-alive
|
// preventing keep-alive
|
||||||
if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
|
if _, err := io.Copy(io.Discard, res.Body); err != nil {
|
||||||
return nil, fmt.Errorf("acme: cert alternates response stream: %v", err)
|
return nil, fmt.Errorf("acme: cert alternates response stream: %v", err)
|
||||||
}
|
}
|
||||||
alts := linkHeader(res.Header, "alternate")
|
alts := linkHeader(res.Header, "alternate")
|
||||||
|
4
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
4
vendor/golang.org/x/crypto/acme/types.go
generated
vendored
@ -297,7 +297,7 @@ type Directory struct {
|
|||||||
|
|
||||||
// CAA consists of lowercase hostname elements, which the ACME server
|
// CAA consists of lowercase hostname elements, which the ACME server
|
||||||
// recognises as referring to itself for the purposes of CAA record validation
|
// recognises as referring to itself for the purposes of CAA record validation
|
||||||
// as defined in RFC6844.
|
// as defined in RFC 6844.
|
||||||
CAA []string
|
CAA []string
|
||||||
|
|
||||||
// ExternalAccountRequired indicates that the CA requires for all account-related
|
// ExternalAccountRequired indicates that the CA requires for all account-related
|
||||||
@ -440,7 +440,7 @@ func DomainIDs(names ...string) []AuthzID {
|
|||||||
|
|
||||||
// IPIDs creates a slice of AuthzID with "ip" identifier type.
|
// IPIDs creates a slice of AuthzID with "ip" identifier type.
|
||||||
// Each element of addr is textual form of an address as defined
|
// Each element of addr is textual form of an address as defined
|
||||||
// in RFC1123 Section 2.1 for IPv4 and in RFC5952 Section 4 for IPv6.
|
// in RFC 1123 Section 2.1 for IPv4 and in RFC 5952 Section 4 for IPv6.
|
||||||
func IPIDs(addr ...string) []AuthzID {
|
func IPIDs(addr ...string) []AuthzID {
|
||||||
a := make([]AuthzID, len(addr))
|
a := make([]AuthzID, len(addr))
|
||||||
for i, v := range addr {
|
for i, v := range addr {
|
||||||
|
3
vendor/golang.org/x/net/AUTHORS
generated
vendored
3
vendor/golang.org/x/net/AUTHORS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# This source code refers to The Go Authors for copyright purposes.
|
|
||||||
# The master list of authors is in the main Go distribution,
|
|
||||||
# visible at http://tip.golang.org/AUTHORS.
|
|
3
vendor/golang.org/x/net/CONTRIBUTORS
generated
vendored
3
vendor/golang.org/x/net/CONTRIBUTORS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# This source code was written by the Go contributors.
|
|
||||||
# The master list of contributors is in the main Go distribution,
|
|
||||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
|
88
vendor/golang.org/x/net/http2/flow.go
generated
vendored
88
vendor/golang.org/x/net/http2/flow.go
generated
vendored
@ -6,23 +6,91 @@
|
|||||||
|
|
||||||
package http2
|
package http2
|
||||||
|
|
||||||
// flow is the flow control window's size.
|
// inflowMinRefresh is the minimum number of bytes we'll send for a
|
||||||
type flow struct {
|
// flow control window update.
|
||||||
|
const inflowMinRefresh = 4 << 10
|
||||||
|
|
||||||
|
// inflow accounts for an inbound flow control window.
|
||||||
|
// It tracks both the latest window sent to the peer (used for enforcement)
|
||||||
|
// and the accumulated unsent window.
|
||||||
|
type inflow struct {
|
||||||
|
avail int32
|
||||||
|
unsent int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// set sets the initial window.
|
||||||
|
func (f *inflow) init(n int32) {
|
||||||
|
f.avail = n
|
||||||
|
}
|
||||||
|
|
||||||
|
// add adds n bytes to the window, with a maximum window size of max,
|
||||||
|
// indicating that the peer can now send us more data.
|
||||||
|
// For example, the user read from a {Request,Response} body and consumed
|
||||||
|
// some of the buffered data, so the peer can now send more.
|
||||||
|
// It returns the number of bytes to send in a WINDOW_UPDATE frame to the peer.
|
||||||
|
// Window updates are accumulated and sent when the unsent capacity
|
||||||
|
// is at least inflowMinRefresh or will at least double the peer's available window.
|
||||||
|
func (f *inflow) add(n int) (connAdd int32) {
|
||||||
|
if n < 0 {
|
||||||
|
panic("negative update")
|
||||||
|
}
|
||||||
|
unsent := int64(f.unsent) + int64(n)
|
||||||
|
// "A sender MUST NOT allow a flow-control window to exceed 2^31-1 octets."
|
||||||
|
// RFC 7540 Section 6.9.1.
|
||||||
|
const maxWindow = 1<<31 - 1
|
||||||
|
if unsent+int64(f.avail) > maxWindow {
|
||||||
|
panic("flow control update exceeds maximum window size")
|
||||||
|
}
|
||||||
|
f.unsent = int32(unsent)
|
||||||
|
if f.unsent < inflowMinRefresh && f.unsent < f.avail {
|
||||||
|
// If there aren't at least inflowMinRefresh bytes of window to send,
|
||||||
|
// and this update won't at least double the window, buffer the update for later.
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
f.avail += f.unsent
|
||||||
|
f.unsent = 0
|
||||||
|
return int32(unsent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// take attempts to take n bytes from the peer's flow control window.
|
||||||
|
// It reports whether the window has available capacity.
|
||||||
|
func (f *inflow) take(n uint32) bool {
|
||||||
|
if n > uint32(f.avail) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
f.avail -= int32(n)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// takeInflows attempts to take n bytes from two inflows,
|
||||||
|
// typically connection-level and stream-level flows.
|
||||||
|
// It reports whether both windows have available capacity.
|
||||||
|
func takeInflows(f1, f2 *inflow, n uint32) bool {
|
||||||
|
if n > uint32(f1.avail) || n > uint32(f2.avail) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
f1.avail -= int32(n)
|
||||||
|
f2.avail -= int32(n)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// outflow is the outbound flow control window's size.
|
||||||
|
type outflow struct {
|
||||||
_ incomparable
|
_ incomparable
|
||||||
|
|
||||||
// n is the number of DATA bytes we're allowed to send.
|
// n is the number of DATA bytes we're allowed to send.
|
||||||
// A flow is kept both on a conn and a per-stream.
|
// An outflow is kept both on a conn and a per-stream.
|
||||||
n int32
|
n int32
|
||||||
|
|
||||||
// conn points to the shared connection-level flow that is
|
// conn points to the shared connection-level outflow that is
|
||||||
// shared by all streams on that conn. It is nil for the flow
|
// shared by all streams on that conn. It is nil for the outflow
|
||||||
// that's on the conn directly.
|
// that's on the conn directly.
|
||||||
conn *flow
|
conn *outflow
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *flow) setConnFlow(cf *flow) { f.conn = cf }
|
func (f *outflow) setConnFlow(cf *outflow) { f.conn = cf }
|
||||||
|
|
||||||
func (f *flow) available() int32 {
|
func (f *outflow) available() int32 {
|
||||||
n := f.n
|
n := f.n
|
||||||
if f.conn != nil && f.conn.n < n {
|
if f.conn != nil && f.conn.n < n {
|
||||||
n = f.conn.n
|
n = f.conn.n
|
||||||
@ -30,7 +98,7 @@ func (f *flow) available() int32 {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *flow) take(n int32) {
|
func (f *outflow) take(n int32) {
|
||||||
if n > f.available() {
|
if n > f.available() {
|
||||||
panic("internal error: took too much")
|
panic("internal error: took too much")
|
||||||
}
|
}
|
||||||
@ -42,7 +110,7 @@ func (f *flow) take(n int32) {
|
|||||||
|
|
||||||
// add adds n bytes (positive or negative) to the flow control window.
|
// add adds n bytes (positive or negative) to the flow control window.
|
||||||
// It returns false if the sum would exceed 2^31-1.
|
// It returns false if the sum would exceed 2^31-1.
|
||||||
func (f *flow) add(n int32) bool {
|
func (f *outflow) add(n int32) bool {
|
||||||
sum := f.n + n
|
sum := f.n + n
|
||||||
if (sum > n) == (f.n > 0) {
|
if (sum > n) == (f.n > 0) {
|
||||||
f.n = sum
|
f.n = sum
|
||||||
|
22
vendor/golang.org/x/net/http2/frame.go
generated
vendored
22
vendor/golang.org/x/net/http2/frame.go
generated
vendored
@ -23,7 +23,7 @@ const frameHeaderLen = 9
|
|||||||
var padZeros = make([]byte, 255) // zeros for padding
|
var padZeros = make([]byte, 255) // zeros for padding
|
||||||
|
|
||||||
// A FrameType is a registered frame type as defined in
|
// A FrameType is a registered frame type as defined in
|
||||||
// http://http2.github.io/http2-spec/#rfc.section.11.2
|
// https://httpwg.org/specs/rfc7540.html#rfc.section.11.2
|
||||||
type FrameType uint8
|
type FrameType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -146,7 +146,7 @@ func typeFrameParser(t FrameType) frameParser {
|
|||||||
|
|
||||||
// A FrameHeader is the 9 byte header of all HTTP/2 frames.
|
// A FrameHeader is the 9 byte header of all HTTP/2 frames.
|
||||||
//
|
//
|
||||||
// See http://http2.github.io/http2-spec/#FrameHeader
|
// See https://httpwg.org/specs/rfc7540.html#FrameHeader
|
||||||
type FrameHeader struct {
|
type FrameHeader struct {
|
||||||
valid bool // caller can access []byte fields in the Frame
|
valid bool // caller can access []byte fields in the Frame
|
||||||
|
|
||||||
@ -575,7 +575,7 @@ func (fr *Framer) checkFrameOrder(f Frame) error {
|
|||||||
|
|
||||||
// A DataFrame conveys arbitrary, variable-length sequences of octets
|
// A DataFrame conveys arbitrary, variable-length sequences of octets
|
||||||
// associated with a stream.
|
// associated with a stream.
|
||||||
// See http://http2.github.io/http2-spec/#rfc.section.6.1
|
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.1
|
||||||
type DataFrame struct {
|
type DataFrame struct {
|
||||||
FrameHeader
|
FrameHeader
|
||||||
data []byte
|
data []byte
|
||||||
@ -698,7 +698,7 @@ func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []by
|
|||||||
// endpoints communicate, such as preferences and constraints on peer
|
// endpoints communicate, such as preferences and constraints on peer
|
||||||
// behavior.
|
// behavior.
|
||||||
//
|
//
|
||||||
// See http://http2.github.io/http2-spec/#SETTINGS
|
// See https://httpwg.org/specs/rfc7540.html#SETTINGS
|
||||||
type SettingsFrame struct {
|
type SettingsFrame struct {
|
||||||
FrameHeader
|
FrameHeader
|
||||||
p []byte
|
p []byte
|
||||||
@ -837,7 +837,7 @@ func (f *Framer) WriteSettingsAck() error {
|
|||||||
// A PingFrame is a mechanism for measuring a minimal round trip time
|
// A PingFrame is a mechanism for measuring a minimal round trip time
|
||||||
// from the sender, as well as determining whether an idle connection
|
// from the sender, as well as determining whether an idle connection
|
||||||
// is still functional.
|
// is still functional.
|
||||||
// See http://http2.github.io/http2-spec/#rfc.section.6.7
|
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.7
|
||||||
type PingFrame struct {
|
type PingFrame struct {
|
||||||
FrameHeader
|
FrameHeader
|
||||||
Data [8]byte
|
Data [8]byte
|
||||||
@ -870,7 +870,7 @@ func (f *Framer) WritePing(ack bool, data [8]byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A GoAwayFrame informs the remote peer to stop creating streams on this connection.
|
// A GoAwayFrame informs the remote peer to stop creating streams on this connection.
|
||||||
// See http://http2.github.io/http2-spec/#rfc.section.6.8
|
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.8
|
||||||
type GoAwayFrame struct {
|
type GoAwayFrame struct {
|
||||||
FrameHeader
|
FrameHeader
|
||||||
LastStreamID uint32
|
LastStreamID uint32
|
||||||
@ -934,7 +934,7 @@ func parseUnknownFrame(_ *frameCache, fh FrameHeader, countError func(string), p
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A WindowUpdateFrame is used to implement flow control.
|
// A WindowUpdateFrame is used to implement flow control.
|
||||||
// See http://http2.github.io/http2-spec/#rfc.section.6.9
|
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.9
|
||||||
type WindowUpdateFrame struct {
|
type WindowUpdateFrame struct {
|
||||||
FrameHeader
|
FrameHeader
|
||||||
Increment uint32 // never read with high bit set
|
Increment uint32 // never read with high bit set
|
||||||
@ -1123,7 +1123,7 @@ func (f *Framer) WriteHeaders(p HeadersFrameParam) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A PriorityFrame specifies the sender-advised priority of a stream.
|
// A PriorityFrame specifies the sender-advised priority of a stream.
|
||||||
// See http://http2.github.io/http2-spec/#rfc.section.6.3
|
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.3
|
||||||
type PriorityFrame struct {
|
type PriorityFrame struct {
|
||||||
FrameHeader
|
FrameHeader
|
||||||
PriorityParam
|
PriorityParam
|
||||||
@ -1193,7 +1193,7 @@ func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A RSTStreamFrame allows for abnormal termination of a stream.
|
// A RSTStreamFrame allows for abnormal termination of a stream.
|
||||||
// See http://http2.github.io/http2-spec/#rfc.section.6.4
|
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.4
|
||||||
type RSTStreamFrame struct {
|
type RSTStreamFrame struct {
|
||||||
FrameHeader
|
FrameHeader
|
||||||
ErrCode ErrCode
|
ErrCode ErrCode
|
||||||
@ -1225,7 +1225,7 @@ func (f *Framer) WriteRSTStream(streamID uint32, code ErrCode) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A ContinuationFrame is used to continue a sequence of header block fragments.
|
// A ContinuationFrame is used to continue a sequence of header block fragments.
|
||||||
// See http://http2.github.io/http2-spec/#rfc.section.6.10
|
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.10
|
||||||
type ContinuationFrame struct {
|
type ContinuationFrame struct {
|
||||||
FrameHeader
|
FrameHeader
|
||||||
headerFragBuf []byte
|
headerFragBuf []byte
|
||||||
@ -1266,7 +1266,7 @@ func (f *Framer) WriteContinuation(streamID uint32, endHeaders bool, headerBlock
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A PushPromiseFrame is used to initiate a server stream.
|
// A PushPromiseFrame is used to initiate a server stream.
|
||||||
// See http://http2.github.io/http2-spec/#rfc.section.6.6
|
// See https://httpwg.org/specs/rfc7540.html#rfc.section.6.6
|
||||||
type PushPromiseFrame struct {
|
type PushPromiseFrame struct {
|
||||||
FrameHeader
|
FrameHeader
|
||||||
PromiseID uint32
|
PromiseID uint32
|
||||||
|
17
vendor/golang.org/x/net/http2/h2c/h2c.go
generated
vendored
17
vendor/golang.org/x/net/http2/h2c/h2c.go
generated
vendored
@ -70,6 +70,15 @@ func NewHandler(h http.Handler, s *http2.Server) http.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractServer extracts existing http.Server instance from http.Request or create an empty http.Server
|
||||||
|
func extractServer(r *http.Request) *http.Server {
|
||||||
|
server, ok := r.Context().Value(http.ServerContextKey).(*http.Server)
|
||||||
|
if ok {
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
return new(http.Server)
|
||||||
|
}
|
||||||
|
|
||||||
// ServeHTTP implement the h2c support that is enabled by h2c.GetH2CHandler.
|
// ServeHTTP implement the h2c support that is enabled by h2c.GetH2CHandler.
|
||||||
func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// Handle h2c with prior knowledge (RFC 7540 Section 3.4)
|
// Handle h2c with prior knowledge (RFC 7540 Section 3.4)
|
||||||
@ -87,6 +96,7 @@ func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
s.s.ServeConn(conn, &http2.ServeConnOpts{
|
s.s.ServeConn(conn, &http2.ServeConnOpts{
|
||||||
Context: r.Context(),
|
Context: r.Context(),
|
||||||
|
BaseConfig: extractServer(r),
|
||||||
Handler: s.Handler,
|
Handler: s.Handler,
|
||||||
SawClientPreface: true,
|
SawClientPreface: true,
|
||||||
})
|
})
|
||||||
@ -99,11 +109,13 @@ func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if http2VerboseLogs {
|
if http2VerboseLogs {
|
||||||
log.Printf("h2c: error h2c upgrade: %v", err)
|
log.Printf("h2c: error h2c upgrade: %v", err)
|
||||||
}
|
}
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
s.s.ServeConn(conn, &http2.ServeConnOpts{
|
s.s.ServeConn(conn, &http2.ServeConnOpts{
|
||||||
Context: r.Context(),
|
Context: r.Context(),
|
||||||
|
BaseConfig: extractServer(r),
|
||||||
Handler: s.Handler,
|
Handler: s.Handler,
|
||||||
UpgradeRequest: r,
|
UpgradeRequest: r,
|
||||||
Settings: settings,
|
Settings: settings,
|
||||||
@ -156,7 +168,10 @@ func h2cUpgrade(w http.ResponseWriter, r *http.Request) (_ net.Conn, settings []
|
|||||||
return nil, nil, errors.New("h2c: connection does not support Hijack")
|
return nil, nil, errors.New("h2c: connection does not support Hijack")
|
||||||
}
|
}
|
||||||
|
|
||||||
body, _ := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
r.Body = io.NopCloser(bytes.NewBuffer(body))
|
r.Body = io.NopCloser(bytes.NewBuffer(body))
|
||||||
|
|
||||||
conn, rw, err := hijacker.Hijack()
|
conn, rw, err := hijacker.Hijack()
|
||||||
|
18
vendor/golang.org/x/net/http2/headermap.go
generated
vendored
18
vendor/golang.org/x/net/http2/headermap.go
generated
vendored
@ -27,7 +27,14 @@ func buildCommonHeaderMaps() {
|
|||||||
"accept-language",
|
"accept-language",
|
||||||
"accept-ranges",
|
"accept-ranges",
|
||||||
"age",
|
"age",
|
||||||
|
"access-control-allow-credentials",
|
||||||
|
"access-control-allow-headers",
|
||||||
|
"access-control-allow-methods",
|
||||||
"access-control-allow-origin",
|
"access-control-allow-origin",
|
||||||
|
"access-control-expose-headers",
|
||||||
|
"access-control-max-age",
|
||||||
|
"access-control-request-headers",
|
||||||
|
"access-control-request-method",
|
||||||
"allow",
|
"allow",
|
||||||
"authorization",
|
"authorization",
|
||||||
"cache-control",
|
"cache-control",
|
||||||
@ -53,6 +60,7 @@ func buildCommonHeaderMaps() {
|
|||||||
"link",
|
"link",
|
||||||
"location",
|
"location",
|
||||||
"max-forwards",
|
"max-forwards",
|
||||||
|
"origin",
|
||||||
"proxy-authenticate",
|
"proxy-authenticate",
|
||||||
"proxy-authorization",
|
"proxy-authorization",
|
||||||
"range",
|
"range",
|
||||||
@ -68,6 +76,8 @@ func buildCommonHeaderMaps() {
|
|||||||
"vary",
|
"vary",
|
||||||
"via",
|
"via",
|
||||||
"www-authenticate",
|
"www-authenticate",
|
||||||
|
"x-forwarded-for",
|
||||||
|
"x-forwarded-proto",
|
||||||
}
|
}
|
||||||
commonLowerHeader = make(map[string]string, len(common))
|
commonLowerHeader = make(map[string]string, len(common))
|
||||||
commonCanonHeader = make(map[string]string, len(common))
|
commonCanonHeader = make(map[string]string, len(common))
|
||||||
@ -85,3 +95,11 @@ func lowerHeader(v string) (lower string, ascii bool) {
|
|||||||
}
|
}
|
||||||
return asciiToLower(v)
|
return asciiToLower(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func canonicalHeader(v string) string {
|
||||||
|
buildCommonHeaderMapsOnce()
|
||||||
|
if s, ok := commonCanonHeader[v]; ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return http.CanonicalHeaderKey(v)
|
||||||
|
}
|
||||||
|
7
vendor/golang.org/x/net/http2/hpack/encode.go
generated
vendored
7
vendor/golang.org/x/net/http2/hpack/encode.go
generated
vendored
@ -116,6 +116,11 @@ func (e *Encoder) SetMaxDynamicTableSize(v uint32) {
|
|||||||
e.dynTab.setMaxSize(v)
|
e.dynTab.setMaxSize(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MaxDynamicTableSize returns the current dynamic header table size.
|
||||||
|
func (e *Encoder) MaxDynamicTableSize() (v uint32) {
|
||||||
|
return e.dynTab.maxSize
|
||||||
|
}
|
||||||
|
|
||||||
// SetMaxDynamicTableSizeLimit changes the maximum value that can be
|
// SetMaxDynamicTableSizeLimit changes the maximum value that can be
|
||||||
// specified in SetMaxDynamicTableSize to v. By default, it is set to
|
// specified in SetMaxDynamicTableSize to v. By default, it is set to
|
||||||
// 4096, which is the same size of the default dynamic header table
|
// 4096, which is the same size of the default dynamic header table
|
||||||
@ -191,7 +196,7 @@ func appendTableSize(dst []byte, v uint32) []byte {
|
|||||||
// bit prefix, to dst and returns the extended buffer.
|
// bit prefix, to dst and returns the extended buffer.
|
||||||
//
|
//
|
||||||
// See
|
// See
|
||||||
// http://http2.github.io/http2-spec/compression.html#integer.representation
|
// https://httpwg.org/specs/rfc7541.html#integer.representation
|
||||||
func appendVarInt(dst []byte, n byte, i uint64) []byte {
|
func appendVarInt(dst []byte, n byte, i uint64) []byte {
|
||||||
k := uint64((1 << n) - 1)
|
k := uint64((1 << n) - 1)
|
||||||
if i < k {
|
if i < k {
|
||||||
|
16
vendor/golang.org/x/net/http2/hpack/hpack.go
generated
vendored
16
vendor/golang.org/x/net/http2/hpack/hpack.go
generated
vendored
@ -59,7 +59,7 @@ func (hf HeaderField) String() string {
|
|||||||
|
|
||||||
// Size returns the size of an entry per RFC 7541 section 4.1.
|
// Size returns the size of an entry per RFC 7541 section 4.1.
|
||||||
func (hf HeaderField) Size() uint32 {
|
func (hf HeaderField) Size() uint32 {
|
||||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
|
// https://httpwg.org/specs/rfc7541.html#rfc.section.4.1
|
||||||
// "The size of the dynamic table is the sum of the size of
|
// "The size of the dynamic table is the sum of the size of
|
||||||
// its entries. The size of an entry is the sum of its name's
|
// its entries. The size of an entry is the sum of its name's
|
||||||
// length in octets (as defined in Section 5.2), its value's
|
// length in octets (as defined in Section 5.2), its value's
|
||||||
@ -158,7 +158,7 @@ func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type dynamicTable struct {
|
type dynamicTable struct {
|
||||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
|
// https://httpwg.org/specs/rfc7541.html#rfc.section.2.3.2
|
||||||
table headerFieldTable
|
table headerFieldTable
|
||||||
size uint32 // in bytes
|
size uint32 // in bytes
|
||||||
maxSize uint32 // current maxSize
|
maxSize uint32 // current maxSize
|
||||||
@ -307,27 +307,27 @@ func (d *Decoder) parseHeaderFieldRepr() error {
|
|||||||
case b&128 != 0:
|
case b&128 != 0:
|
||||||
// Indexed representation.
|
// Indexed representation.
|
||||||
// High bit set?
|
// High bit set?
|
||||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.6.1
|
// https://httpwg.org/specs/rfc7541.html#rfc.section.6.1
|
||||||
return d.parseFieldIndexed()
|
return d.parseFieldIndexed()
|
||||||
case b&192 == 64:
|
case b&192 == 64:
|
||||||
// 6.2.1 Literal Header Field with Incremental Indexing
|
// 6.2.1 Literal Header Field with Incremental Indexing
|
||||||
// 0b10xxxxxx: top two bits are 10
|
// 0b10xxxxxx: top two bits are 10
|
||||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.1
|
// https://httpwg.org/specs/rfc7541.html#rfc.section.6.2.1
|
||||||
return d.parseFieldLiteral(6, indexedTrue)
|
return d.parseFieldLiteral(6, indexedTrue)
|
||||||
case b&240 == 0:
|
case b&240 == 0:
|
||||||
// 6.2.2 Literal Header Field without Indexing
|
// 6.2.2 Literal Header Field without Indexing
|
||||||
// 0b0000xxxx: top four bits are 0000
|
// 0b0000xxxx: top four bits are 0000
|
||||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.2
|
// https://httpwg.org/specs/rfc7541.html#rfc.section.6.2.2
|
||||||
return d.parseFieldLiteral(4, indexedFalse)
|
return d.parseFieldLiteral(4, indexedFalse)
|
||||||
case b&240 == 16:
|
case b&240 == 16:
|
||||||
// 6.2.3 Literal Header Field never Indexed
|
// 6.2.3 Literal Header Field never Indexed
|
||||||
// 0b0001xxxx: top four bits are 0001
|
// 0b0001xxxx: top four bits are 0001
|
||||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.3
|
// https://httpwg.org/specs/rfc7541.html#rfc.section.6.2.3
|
||||||
return d.parseFieldLiteral(4, indexedNever)
|
return d.parseFieldLiteral(4, indexedNever)
|
||||||
case b&224 == 32:
|
case b&224 == 32:
|
||||||
// 6.3 Dynamic Table Size Update
|
// 6.3 Dynamic Table Size Update
|
||||||
// Top three bits are '001'.
|
// Top three bits are '001'.
|
||||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.6.3
|
// https://httpwg.org/specs/rfc7541.html#rfc.section.6.3
|
||||||
return d.parseDynamicTableSizeUpdate()
|
return d.parseDynamicTableSizeUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,7 +420,7 @@ var errVarintOverflow = DecodingError{errors.New("varint integer overflow")}
|
|||||||
|
|
||||||
// readVarInt reads an unsigned variable length integer off the
|
// readVarInt reads an unsigned variable length integer off the
|
||||||
// beginning of p. n is the parameter as described in
|
// beginning of p. n is the parameter as described in
|
||||||
// http://http2.github.io/http2-spec/compression.html#rfc.section.5.1.
|
// https://httpwg.org/specs/rfc7541.html#rfc.section.5.1.
|
||||||
//
|
//
|
||||||
// n must always be between 1 and 8.
|
// n must always be between 1 and 8.
|
||||||
//
|
//
|
||||||
|
188
vendor/golang.org/x/net/http2/hpack/static_table.go
generated
vendored
Normal file
188
vendor/golang.org/x/net/http2/hpack/static_table.go
generated
vendored
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
// go generate gen.go
|
||||||
|
// Code generated by the command above; DO NOT EDIT.
|
||||||
|
|
||||||
|
package hpack
|
||||||
|
|
||||||
|
var staticTable = &headerFieldTable{
|
||||||
|
evictCount: 0,
|
||||||
|
byName: map[string]uint64{
|
||||||
|
":authority": 1,
|
||||||
|
":method": 3,
|
||||||
|
":path": 5,
|
||||||
|
":scheme": 7,
|
||||||
|
":status": 14,
|
||||||
|
"accept-charset": 15,
|
||||||
|
"accept-encoding": 16,
|
||||||
|
"accept-language": 17,
|
||||||
|
"accept-ranges": 18,
|
||||||
|
"accept": 19,
|
||||||
|
"access-control-allow-origin": 20,
|
||||||
|
"age": 21,
|
||||||
|
"allow": 22,
|
||||||
|
"authorization": 23,
|
||||||
|
"cache-control": 24,
|
||||||
|
"content-disposition": 25,
|
||||||
|
"content-encoding": 26,
|
||||||
|
"content-language": 27,
|
||||||
|
"content-length": 28,
|
||||||
|
"content-location": 29,
|
||||||
|
"content-range": 30,
|
||||||
|
"content-type": 31,
|
||||||
|
"cookie": 32,
|
||||||
|
"date": 33,
|
||||||
|
"etag": 34,
|
||||||
|
"expect": 35,
|
||||||
|
"expires": 36,
|
||||||
|
"from": 37,
|
||||||
|
"host": 38,
|
||||||
|
"if-match": 39,
|
||||||
|
"if-modified-since": 40,
|
||||||
|
"if-none-match": 41,
|
||||||
|
"if-range": 42,
|
||||||
|
"if-unmodified-since": 43,
|
||||||
|
"last-modified": 44,
|
||||||
|
"link": 45,
|
||||||
|
"location": 46,
|
||||||
|
"max-forwards": 47,
|
||||||
|
"proxy-authenticate": 48,
|
||||||
|
"proxy-authorization": 49,
|
||||||
|
"range": 50,
|
||||||
|
"referer": 51,
|
||||||
|
"refresh": 52,
|
||||||
|
"retry-after": 53,
|
||||||
|
"server": 54,
|
||||||
|
"set-cookie": 55,
|
||||||
|
"strict-transport-security": 56,
|
||||||
|
"transfer-encoding": 57,
|
||||||
|
"user-agent": 58,
|
||||||
|
"vary": 59,
|
||||||
|
"via": 60,
|
||||||
|
"www-authenticate": 61,
|
||||||
|
},
|
||||||
|
byNameValue: map[pairNameValue]uint64{
|
||||||
|
{name: ":authority", value: ""}: 1,
|
||||||
|
{name: ":method", value: "GET"}: 2,
|
||||||
|
{name: ":method", value: "POST"}: 3,
|
||||||
|
{name: ":path", value: "/"}: 4,
|
||||||
|
{name: ":path", value: "/index.html"}: 5,
|
||||||
|
{name: ":scheme", value: "http"}: 6,
|
||||||
|
{name: ":scheme", value: "https"}: 7,
|
||||||
|
{name: ":status", value: "200"}: 8,
|
||||||
|
{name: ":status", value: "204"}: 9,
|
||||||
|
{name: ":status", value: "206"}: 10,
|
||||||
|
{name: ":status", value: "304"}: 11,
|
||||||
|
{name: ":status", value: "400"}: 12,
|
||||||
|
{name: ":status", value: "404"}: 13,
|
||||||
|
{name: ":status", value: "500"}: 14,
|
||||||
|
{name: "accept-charset", value: ""}: 15,
|
||||||
|
{name: "accept-encoding", value: "gzip, deflate"}: 16,
|
||||||
|
{name: "accept-language", value: ""}: 17,
|
||||||
|
{name: "accept-ranges", value: ""}: 18,
|
||||||
|
{name: "accept", value: ""}: 19,
|
||||||
|
{name: "access-control-allow-origin", value: ""}: 20,
|
||||||
|
{name: "age", value: ""}: 21,
|
||||||
|
{name: "allow", value: ""}: 22,
|
||||||
|
{name: "authorization", value: ""}: 23,
|
||||||
|
{name: "cache-control", value: ""}: 24,
|
||||||
|
{name: "content-disposition", value: ""}: 25,
|
||||||
|
{name: "content-encoding", value: ""}: 26,
|
||||||
|
{name: "content-language", value: ""}: 27,
|
||||||
|
{name: "content-length", value: ""}: 28,
|
||||||
|
{name: "content-location", value: ""}: 29,
|
||||||
|
{name: "content-range", value: ""}: 30,
|
||||||
|
{name: "content-type", value: ""}: 31,
|
||||||
|
{name: "cookie", value: ""}: 32,
|
||||||
|
{name: "date", value: ""}: 33,
|
||||||
|
{name: "etag", value: ""}: 34,
|
||||||
|
{name: "expect", value: ""}: 35,
|
||||||
|
{name: "expires", value: ""}: 36,
|
||||||
|
{name: "from", value: ""}: 37,
|
||||||
|
{name: "host", value: ""}: 38,
|
||||||
|
{name: "if-match", value: ""}: 39,
|
||||||
|
{name: "if-modified-since", value: ""}: 40,
|
||||||
|
{name: "if-none-match", value: ""}: 41,
|
||||||
|
{name: "if-range", value: ""}: 42,
|
||||||
|
{name: "if-unmodified-since", value: ""}: 43,
|
||||||
|
{name: "last-modified", value: ""}: 44,
|
||||||
|
{name: "link", value: ""}: 45,
|
||||||
|
{name: "location", value: ""}: 46,
|
||||||
|
{name: "max-forwards", value: ""}: 47,
|
||||||
|
{name: "proxy-authenticate", value: ""}: 48,
|
||||||
|
{name: "proxy-authorization", value: ""}: 49,
|
||||||
|
{name: "range", value: ""}: 50,
|
||||||
|
{name: "referer", value: ""}: 51,
|
||||||
|
{name: "refresh", value: ""}: 52,
|
||||||
|
{name: "retry-after", value: ""}: 53,
|
||||||
|
{name: "server", value: ""}: 54,
|
||||||
|
{name: "set-cookie", value: ""}: 55,
|
||||||
|
{name: "strict-transport-security", value: ""}: 56,
|
||||||
|
{name: "transfer-encoding", value: ""}: 57,
|
||||||
|
{name: "user-agent", value: ""}: 58,
|
||||||
|
{name: "vary", value: ""}: 59,
|
||||||
|
{name: "via", value: ""}: 60,
|
||||||
|
{name: "www-authenticate", value: ""}: 61,
|
||||||
|
},
|
||||||
|
ents: []HeaderField{
|
||||||
|
{Name: ":authority", Value: "", Sensitive: false},
|
||||||
|
{Name: ":method", Value: "GET", Sensitive: false},
|
||||||
|
{Name: ":method", Value: "POST", Sensitive: false},
|
||||||
|
{Name: ":path", Value: "/", Sensitive: false},
|
||||||
|
{Name: ":path", Value: "/index.html", Sensitive: false},
|
||||||
|
{Name: ":scheme", Value: "http", Sensitive: false},
|
||||||
|
{Name: ":scheme", Value: "https", Sensitive: false},
|
||||||
|
{Name: ":status", Value: "200", Sensitive: false},
|
||||||
|
{Name: ":status", Value: "204", Sensitive: false},
|
||||||
|
{Name: ":status", Value: "206", Sensitive: false},
|
||||||
|
{Name: ":status", Value: "304", Sensitive: false},
|
||||||
|
{Name: ":status", Value: "400", Sensitive: false},
|
||||||
|
{Name: ":status", Value: "404", Sensitive: false},
|
||||||
|
{Name: ":status", Value: "500", Sensitive: false},
|
||||||
|
{Name: "accept-charset", Value: "", Sensitive: false},
|
||||||
|
{Name: "accept-encoding", Value: "gzip, deflate", Sensitive: false},
|
||||||
|
{Name: "accept-language", Value: "", Sensitive: false},
|
||||||
|
{Name: "accept-ranges", Value: "", Sensitive: false},
|
||||||
|
{Name: "accept", Value: "", Sensitive: false},
|
||||||
|
{Name: "access-control-allow-origin", Value: "", Sensitive: false},
|
||||||
|
{Name: "age", Value: "", Sensitive: false},
|
||||||
|
{Name: "allow", Value: "", Sensitive: false},
|
||||||
|
{Name: "authorization", Value: "", Sensitive: false},
|
||||||
|
{Name: "cache-control", Value: "", Sensitive: false},
|
||||||
|
{Name: "content-disposition", Value: "", Sensitive: false},
|
||||||
|
{Name: "content-encoding", Value: "", Sensitive: false},
|
||||||
|
{Name: "content-language", Value: "", Sensitive: false},
|
||||||
|
{Name: "content-length", Value: "", Sensitive: false},
|
||||||
|
{Name: "content-location", Value: "", Sensitive: false},
|
||||||
|
{Name: "content-range", Value: "", Sensitive: false},
|
||||||
|
{Name: "content-type", Value: "", Sensitive: false},
|
||||||
|
{Name: "cookie", Value: "", Sensitive: false},
|
||||||
|
{Name: "date", Value: "", Sensitive: false},
|
||||||
|
{Name: "etag", Value: "", Sensitive: false},
|
||||||
|
{Name: "expect", Value: "", Sensitive: false},
|
||||||
|
{Name: "expires", Value: "", Sensitive: false},
|
||||||
|
{Name: "from", Value: "", Sensitive: false},
|
||||||
|
{Name: "host", Value: "", Sensitive: false},
|
||||||
|
{Name: "if-match", Value: "", Sensitive: false},
|
||||||
|
{Name: "if-modified-since", Value: "", Sensitive: false},
|
||||||
|
{Name: "if-none-match", Value: "", Sensitive: false},
|
||||||
|
{Name: "if-range", Value: "", Sensitive: false},
|
||||||
|
{Name: "if-unmodified-since", Value: "", Sensitive: false},
|
||||||
|
{Name: "last-modified", Value: "", Sensitive: false},
|
||||||
|
{Name: "link", Value: "", Sensitive: false},
|
||||||
|
{Name: "location", Value: "", Sensitive: false},
|
||||||
|
{Name: "max-forwards", Value: "", Sensitive: false},
|
||||||
|
{Name: "proxy-authenticate", Value: "", Sensitive: false},
|
||||||
|
{Name: "proxy-authorization", Value: "", Sensitive: false},
|
||||||
|
{Name: "range", Value: "", Sensitive: false},
|
||||||
|
{Name: "referer", Value: "", Sensitive: false},
|
||||||
|
{Name: "refresh", Value: "", Sensitive: false},
|
||||||
|
{Name: "retry-after", Value: "", Sensitive: false},
|
||||||
|
{Name: "server", Value: "", Sensitive: false},
|
||||||
|
{Name: "set-cookie", Value: "", Sensitive: false},
|
||||||
|
{Name: "strict-transport-security", Value: "", Sensitive: false},
|
||||||
|
{Name: "transfer-encoding", Value: "", Sensitive: false},
|
||||||
|
{Name: "user-agent", Value: "", Sensitive: false},
|
||||||
|
{Name: "vary", Value: "", Sensitive: false},
|
||||||
|
{Name: "via", Value: "", Sensitive: false},
|
||||||
|
{Name: "www-authenticate", Value: "", Sensitive: false},
|
||||||
|
},
|
||||||
|
}
|
78
vendor/golang.org/x/net/http2/hpack/tables.go
generated
vendored
78
vendor/golang.org/x/net/http2/hpack/tables.go
generated
vendored
@ -96,8 +96,7 @@ func (t *headerFieldTable) evictOldest(n int) {
|
|||||||
// meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
|
// meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
|
||||||
// table, the return value i actually refers to the entry t.ents[t.len()-i].
|
// table, the return value i actually refers to the entry t.ents[t.len()-i].
|
||||||
//
|
//
|
||||||
// All tables are assumed to be a dynamic tables except for the global
|
// All tables are assumed to be a dynamic tables except for the global staticTable.
|
||||||
// staticTable pointer.
|
|
||||||
//
|
//
|
||||||
// See Section 2.3.3.
|
// See Section 2.3.3.
|
||||||
func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
|
func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
|
||||||
@ -125,81 +124,6 @@ func (t *headerFieldTable) idToIndex(id uint64) uint64 {
|
|||||||
return k + 1
|
return k + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
|
|
||||||
var staticTable = newStaticTable()
|
|
||||||
var staticTableEntries = [...]HeaderField{
|
|
||||||
{Name: ":authority"},
|
|
||||||
{Name: ":method", Value: "GET"},
|
|
||||||
{Name: ":method", Value: "POST"},
|
|
||||||
{Name: ":path", Value: "/"},
|
|
||||||
{Name: ":path", Value: "/index.html"},
|
|
||||||
{Name: ":scheme", Value: "http"},
|
|
||||||
{Name: ":scheme", Value: "https"},
|
|
||||||
{Name: ":status", Value: "200"},
|
|
||||||
{Name: ":status", Value: "204"},
|
|
||||||
{Name: ":status", Value: "206"},
|
|
||||||
{Name: ":status", Value: "304"},
|
|
||||||
{Name: ":status", Value: "400"},
|
|
||||||
{Name: ":status", Value: "404"},
|
|
||||||
{Name: ":status", Value: "500"},
|
|
||||||
{Name: "accept-charset"},
|
|
||||||
{Name: "accept-encoding", Value: "gzip, deflate"},
|
|
||||||
{Name: "accept-language"},
|
|
||||||
{Name: "accept-ranges"},
|
|
||||||
{Name: "accept"},
|
|
||||||
{Name: "access-control-allow-origin"},
|
|
||||||
{Name: "age"},
|
|
||||||
{Name: "allow"},
|
|
||||||
{Name: "authorization"},
|
|
||||||
{Name: "cache-control"},
|
|
||||||
{Name: "content-disposition"},
|
|
||||||
{Name: "content-encoding"},
|
|
||||||
{Name: "content-language"},
|
|
||||||
{Name: "content-length"},
|
|
||||||
{Name: "content-location"},
|
|
||||||
{Name: "content-range"},
|
|
||||||
{Name: "content-type"},
|
|
||||||
{Name: "cookie"},
|
|
||||||
{Name: "date"},
|
|
||||||
{Name: "etag"},
|
|
||||||
{Name: "expect"},
|
|
||||||
{Name: "expires"},
|
|
||||||
{Name: "from"},
|
|
||||||
{Name: "host"},
|
|
||||||
{Name: "if-match"},
|
|
||||||
{Name: "if-modified-since"},
|
|
||||||
{Name: "if-none-match"},
|
|
||||||
{Name: "if-range"},
|
|
||||||
{Name: "if-unmodified-since"},
|
|
||||||
{Name: "last-modified"},
|
|
||||||
{Name: "link"},
|
|
||||||
{Name: "location"},
|
|
||||||
{Name: "max-forwards"},
|
|
||||||
{Name: "proxy-authenticate"},
|
|
||||||
{Name: "proxy-authorization"},
|
|
||||||
{Name: "range"},
|
|
||||||
{Name: "referer"},
|
|
||||||
{Name: "refresh"},
|
|
||||||
{Name: "retry-after"},
|
|
||||||
{Name: "server"},
|
|
||||||
{Name: "set-cookie"},
|
|
||||||
{Name: "strict-transport-security"},
|
|
||||||
{Name: "transfer-encoding"},
|
|
||||||
{Name: "user-agent"},
|
|
||||||
{Name: "vary"},
|
|
||||||
{Name: "via"},
|
|
||||||
{Name: "www-authenticate"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func newStaticTable() *headerFieldTable {
|
|
||||||
t := &headerFieldTable{}
|
|
||||||
t.init()
|
|
||||||
for _, e := range staticTableEntries[:] {
|
|
||||||
t.addEntry(e)
|
|
||||||
}
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
var huffmanCodes = [256]uint32{
|
var huffmanCodes = [256]uint32{
|
||||||
0x1ff8,
|
0x1ff8,
|
||||||
0x7fffd8,
|
0x7fffd8,
|
||||||
|
8
vendor/golang.org/x/net/http2/http2.go
generated
vendored
8
vendor/golang.org/x/net/http2/http2.go
generated
vendored
@ -55,14 +55,14 @@ const (
|
|||||||
ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
|
ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
|
||||||
|
|
||||||
// SETTINGS_MAX_FRAME_SIZE default
|
// SETTINGS_MAX_FRAME_SIZE default
|
||||||
// http://http2.github.io/http2-spec/#rfc.section.6.5.2
|
// https://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2
|
||||||
initialMaxFrameSize = 16384
|
initialMaxFrameSize = 16384
|
||||||
|
|
||||||
// NextProtoTLS is the NPN/ALPN protocol negotiated during
|
// NextProtoTLS is the NPN/ALPN protocol negotiated during
|
||||||
// HTTP/2's TLS setup.
|
// HTTP/2's TLS setup.
|
||||||
NextProtoTLS = "h2"
|
NextProtoTLS = "h2"
|
||||||
|
|
||||||
// http://http2.github.io/http2-spec/#SettingValues
|
// https://httpwg.org/specs/rfc7540.html#SettingValues
|
||||||
initialHeaderTableSize = 4096
|
initialHeaderTableSize = 4096
|
||||||
|
|
||||||
initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
|
initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
|
||||||
@ -111,7 +111,7 @@ func (st streamState) String() string {
|
|||||||
// Setting is a setting parameter: which setting it is, and its value.
|
// Setting is a setting parameter: which setting it is, and its value.
|
||||||
type Setting struct {
|
type Setting struct {
|
||||||
// ID is which setting is being set.
|
// ID is which setting is being set.
|
||||||
// See http://http2.github.io/http2-spec/#SettingValues
|
// See https://httpwg.org/specs/rfc7540.html#SettingFormat
|
||||||
ID SettingID
|
ID SettingID
|
||||||
|
|
||||||
// Val is the value.
|
// Val is the value.
|
||||||
@ -143,7 +143,7 @@ func (s Setting) Valid() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A SettingID is an HTTP/2 setting as defined in
|
// A SettingID is an HTTP/2 setting as defined in
|
||||||
// http://http2.github.io/http2-spec/#iana-settings
|
// https://httpwg.org/specs/rfc7540.html#iana-settings
|
||||||
type SettingID uint16
|
type SettingID uint16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
311
vendor/golang.org/x/net/http2/server.go
generated
vendored
311
vendor/golang.org/x/net/http2/server.go
generated
vendored
@ -98,6 +98,19 @@ type Server struct {
|
|||||||
// the HTTP/2 spec's recommendations.
|
// the HTTP/2 spec's recommendations.
|
||||||
MaxConcurrentStreams uint32
|
MaxConcurrentStreams uint32
|
||||||
|
|
||||||
|
// MaxDecoderHeaderTableSize optionally specifies the http2
|
||||||
|
// SETTINGS_HEADER_TABLE_SIZE to send in the initial settings frame. It
|
||||||
|
// informs the remote endpoint of the maximum size of the header compression
|
||||||
|
// table used to decode header blocks, in octets. If zero, the default value
|
||||||
|
// of 4096 is used.
|
||||||
|
MaxDecoderHeaderTableSize uint32
|
||||||
|
|
||||||
|
// MaxEncoderHeaderTableSize optionally specifies an upper limit for the
|
||||||
|
// header compression table used for encoding request headers. Received
|
||||||
|
// SETTINGS_HEADER_TABLE_SIZE settings are capped at this limit. If zero,
|
||||||
|
// the default value of 4096 is used.
|
||||||
|
MaxEncoderHeaderTableSize uint32
|
||||||
|
|
||||||
// MaxReadFrameSize optionally specifies the largest frame
|
// MaxReadFrameSize optionally specifies the largest frame
|
||||||
// this server is willing to read. A valid value is between
|
// this server is willing to read. A valid value is between
|
||||||
// 16k and 16M, inclusive. If zero or otherwise invalid, a
|
// 16k and 16M, inclusive. If zero or otherwise invalid, a
|
||||||
@ -143,7 +156,7 @@ type Server struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initialConnRecvWindowSize() int32 {
|
func (s *Server) initialConnRecvWindowSize() int32 {
|
||||||
if s.MaxUploadBufferPerConnection > initialWindowSize {
|
if s.MaxUploadBufferPerConnection >= initialWindowSize {
|
||||||
return s.MaxUploadBufferPerConnection
|
return s.MaxUploadBufferPerConnection
|
||||||
}
|
}
|
||||||
return 1 << 20
|
return 1 << 20
|
||||||
@ -170,6 +183,20 @@ func (s *Server) maxConcurrentStreams() uint32 {
|
|||||||
return defaultMaxStreams
|
return defaultMaxStreams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) maxDecoderHeaderTableSize() uint32 {
|
||||||
|
if v := s.MaxDecoderHeaderTableSize; v > 0 {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return initialHeaderTableSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) maxEncoderHeaderTableSize() uint32 {
|
||||||
|
if v := s.MaxEncoderHeaderTableSize; v > 0 {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return initialHeaderTableSize
|
||||||
|
}
|
||||||
|
|
||||||
// maxQueuedControlFrames is the maximum number of control frames like
|
// maxQueuedControlFrames is the maximum number of control frames like
|
||||||
// SETTINGS, PING and RST_STREAM that will be queued for writing before
|
// SETTINGS, PING and RST_STREAM that will be queued for writing before
|
||||||
// the connection is closed to prevent memory exhaustion attacks.
|
// the connection is closed to prevent memory exhaustion attacks.
|
||||||
@ -394,7 +421,6 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
|||||||
advMaxStreams: s.maxConcurrentStreams(),
|
advMaxStreams: s.maxConcurrentStreams(),
|
||||||
initialStreamSendWindowSize: initialWindowSize,
|
initialStreamSendWindowSize: initialWindowSize,
|
||||||
maxFrameSize: initialMaxFrameSize,
|
maxFrameSize: initialMaxFrameSize,
|
||||||
headerTableSize: initialHeaderTableSize,
|
|
||||||
serveG: newGoroutineLock(),
|
serveG: newGoroutineLock(),
|
||||||
pushEnabled: true,
|
pushEnabled: true,
|
||||||
sawClientPreface: opts.SawClientPreface,
|
sawClientPreface: opts.SawClientPreface,
|
||||||
@ -422,14 +448,15 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
|
|||||||
// configured value for inflow, that will be updated when we send a
|
// configured value for inflow, that will be updated when we send a
|
||||||
// WINDOW_UPDATE shortly after sending SETTINGS.
|
// WINDOW_UPDATE shortly after sending SETTINGS.
|
||||||
sc.flow.add(initialWindowSize)
|
sc.flow.add(initialWindowSize)
|
||||||
sc.inflow.add(initialWindowSize)
|
sc.inflow.init(initialWindowSize)
|
||||||
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
|
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
|
||||||
|
sc.hpackEncoder.SetMaxDynamicTableSizeLimit(s.maxEncoderHeaderTableSize())
|
||||||
|
|
||||||
fr := NewFramer(sc.bw, c)
|
fr := NewFramer(sc.bw, c)
|
||||||
if s.CountError != nil {
|
if s.CountError != nil {
|
||||||
fr.countError = s.CountError
|
fr.countError = s.CountError
|
||||||
}
|
}
|
||||||
fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
|
fr.ReadMetaHeaders = hpack.NewDecoder(s.maxDecoderHeaderTableSize(), nil)
|
||||||
fr.MaxHeaderListSize = sc.maxHeaderListSize()
|
fr.MaxHeaderListSize = sc.maxHeaderListSize()
|
||||||
fr.SetMaxReadFrameSize(s.maxReadFrameSize())
|
fr.SetMaxReadFrameSize(s.maxReadFrameSize())
|
||||||
sc.framer = fr
|
sc.framer = fr
|
||||||
@ -536,8 +563,8 @@ type serverConn struct {
|
|||||||
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
|
wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
|
||||||
bodyReadCh chan bodyReadMsg // from handlers -> serve
|
bodyReadCh chan bodyReadMsg // from handlers -> serve
|
||||||
serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
|
serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
|
||||||
flow flow // conn-wide (not stream-specific) outbound flow control
|
flow outflow // conn-wide (not stream-specific) outbound flow control
|
||||||
inflow flow // conn-wide inbound flow control
|
inflow inflow // conn-wide inbound flow control
|
||||||
tlsState *tls.ConnectionState // shared by all handlers, like net/http
|
tlsState *tls.ConnectionState // shared by all handlers, like net/http
|
||||||
remoteAddrStr string
|
remoteAddrStr string
|
||||||
writeSched WriteScheduler
|
writeSched WriteScheduler
|
||||||
@ -559,9 +586,9 @@ type serverConn struct {
|
|||||||
streams map[uint32]*stream
|
streams map[uint32]*stream
|
||||||
initialStreamSendWindowSize int32
|
initialStreamSendWindowSize int32
|
||||||
maxFrameSize int32
|
maxFrameSize int32
|
||||||
headerTableSize uint32
|
|
||||||
peerMaxHeaderListSize uint32 // zero means unknown (default)
|
peerMaxHeaderListSize uint32 // zero means unknown (default)
|
||||||
canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
|
canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
|
||||||
|
canonHeaderKeysSize int // canonHeader keys size in bytes
|
||||||
writingFrame bool // started writing a frame (on serve goroutine or separate)
|
writingFrame bool // started writing a frame (on serve goroutine or separate)
|
||||||
writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
|
writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
|
||||||
needsFrameFlush bool // last frame write wasn't a flush
|
needsFrameFlush bool // last frame write wasn't a flush
|
||||||
@ -614,15 +641,17 @@ type stream struct {
|
|||||||
cancelCtx func()
|
cancelCtx func()
|
||||||
|
|
||||||
// owned by serverConn's serve loop:
|
// owned by serverConn's serve loop:
|
||||||
bodyBytes int64 // body bytes seen so far
|
bodyBytes int64 // body bytes seen so far
|
||||||
declBodyBytes int64 // or -1 if undeclared
|
declBodyBytes int64 // or -1 if undeclared
|
||||||
flow flow // limits writing from Handler to client
|
flow outflow // limits writing from Handler to client
|
||||||
inflow flow // what the client is allowed to POST/etc to us
|
inflow inflow // what the client is allowed to POST/etc to us
|
||||||
state streamState
|
state streamState
|
||||||
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
|
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
|
||||||
gotTrailerHeader bool // HEADER frame for trailers was seen
|
gotTrailerHeader bool // HEADER frame for trailers was seen
|
||||||
wroteHeaders bool // whether we wrote headers (not status 100)
|
wroteHeaders bool // whether we wrote headers (not status 100)
|
||||||
|
readDeadline *time.Timer // nil if unused
|
||||||
writeDeadline *time.Timer // nil if unused
|
writeDeadline *time.Timer // nil if unused
|
||||||
|
closeErr error // set before cw is closed
|
||||||
|
|
||||||
trailer http.Header // accumulated trailers
|
trailer http.Header // accumulated trailers
|
||||||
reqTrailer http.Header // handler's Request.Trailer
|
reqTrailer http.Header // handler's Request.Trailer
|
||||||
@ -738,6 +767,13 @@ func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size
|
||||||
|
// of the entries in the canonHeader cache.
|
||||||
|
// This should be larger than the size of unique, uncommon header keys likely to
|
||||||
|
// be sent by the peer, while not so high as to permit unreasonable memory usage
|
||||||
|
// if the peer sends an unbounded number of unique header keys.
|
||||||
|
const maxCachedCanonicalHeadersKeysSize = 2048
|
||||||
|
|
||||||
func (sc *serverConn) canonicalHeader(v string) string {
|
func (sc *serverConn) canonicalHeader(v string) string {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
buildCommonHeaderMapsOnce()
|
buildCommonHeaderMapsOnce()
|
||||||
@ -753,14 +789,10 @@ func (sc *serverConn) canonicalHeader(v string) string {
|
|||||||
sc.canonHeader = make(map[string]string)
|
sc.canonHeader = make(map[string]string)
|
||||||
}
|
}
|
||||||
cv = http.CanonicalHeaderKey(v)
|
cv = http.CanonicalHeaderKey(v)
|
||||||
// maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
|
size := 100 + len(v)*2 // 100 bytes of map overhead + key + value
|
||||||
// entries in the canonHeader cache. This should be larger than the number
|
if sc.canonHeaderKeysSize+size <= maxCachedCanonicalHeadersKeysSize {
|
||||||
// of unique, uncommon header keys likely to be sent by the peer, while not
|
|
||||||
// so high as to permit unreasonable memory usage if the peer sends an unbounded
|
|
||||||
// number of unique header keys.
|
|
||||||
const maxCachedCanonicalHeaders = 32
|
|
||||||
if len(sc.canonHeader) < maxCachedCanonicalHeaders {
|
|
||||||
sc.canonHeader[v] = cv
|
sc.canonHeader[v] = cv
|
||||||
|
sc.canonHeaderKeysSize += size
|
||||||
}
|
}
|
||||||
return cv
|
return cv
|
||||||
}
|
}
|
||||||
@ -862,6 +894,7 @@ func (sc *serverConn) serve() {
|
|||||||
{SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
|
{SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
|
||||||
{SettingMaxConcurrentStreams, sc.advMaxStreams},
|
{SettingMaxConcurrentStreams, sc.advMaxStreams},
|
||||||
{SettingMaxHeaderListSize, sc.maxHeaderListSize()},
|
{SettingMaxHeaderListSize, sc.maxHeaderListSize()},
|
||||||
|
{SettingHeaderTableSize, sc.srv.maxDecoderHeaderTableSize()},
|
||||||
{SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())},
|
{SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -948,6 +981,8 @@ func (sc *serverConn) serve() {
|
|||||||
}
|
}
|
||||||
case *startPushRequest:
|
case *startPushRequest:
|
||||||
sc.startPush(v)
|
sc.startPush(v)
|
||||||
|
case func(*serverConn):
|
||||||
|
v(sc)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unexpected type %T", v))
|
panic(fmt.Sprintf("unexpected type %T", v))
|
||||||
}
|
}
|
||||||
@ -1371,6 +1406,9 @@ func (sc *serverConn) startGracefulShutdownInternal() {
|
|||||||
func (sc *serverConn) goAway(code ErrCode) {
|
func (sc *serverConn) goAway(code ErrCode) {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
if sc.inGoAway {
|
if sc.inGoAway {
|
||||||
|
if sc.goAwayCode == ErrCodeNo {
|
||||||
|
sc.goAwayCode = code
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sc.inGoAway = true
|
sc.inGoAway = true
|
||||||
@ -1458,6 +1496,21 @@ func (sc *serverConn) processFrame(f Frame) error {
|
|||||||
sc.sawFirstSettings = true
|
sc.sawFirstSettings = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Discard frames for streams initiated after the identified last
|
||||||
|
// stream sent in a GOAWAY, or all frames after sending an error.
|
||||||
|
// We still need to return connection-level flow control for DATA frames.
|
||||||
|
// RFC 9113 Section 6.8.
|
||||||
|
if sc.inGoAway && (sc.goAwayCode != ErrCodeNo || f.Header().StreamID > sc.maxClientStreamID) {
|
||||||
|
|
||||||
|
if f, ok := f.(*DataFrame); ok {
|
||||||
|
if !sc.inflow.take(f.Length) {
|
||||||
|
return sc.countError("data_flow", streamError(f.Header().StreamID, ErrCodeFlowControl))
|
||||||
|
}
|
||||||
|
sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
switch f := f.(type) {
|
switch f := f.(type) {
|
||||||
case *SettingsFrame:
|
case *SettingsFrame:
|
||||||
return sc.processSettings(f)
|
return sc.processSettings(f)
|
||||||
@ -1500,9 +1553,6 @@ func (sc *serverConn) processPing(f *PingFrame) error {
|
|||||||
// PROTOCOL_ERROR."
|
// PROTOCOL_ERROR."
|
||||||
return sc.countError("ping_on_stream", ConnectionError(ErrCodeProtocol))
|
return sc.countError("ping_on_stream", ConnectionError(ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
sc.writeFrame(FrameWriteRequest{write: writePingAck{f}})
|
sc.writeFrame(FrameWriteRequest{write: writePingAck{f}})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1564,6 +1614,9 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
|||||||
panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
|
panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
|
||||||
}
|
}
|
||||||
st.state = stateClosed
|
st.state = stateClosed
|
||||||
|
if st.readDeadline != nil {
|
||||||
|
st.readDeadline.Stop()
|
||||||
|
}
|
||||||
if st.writeDeadline != nil {
|
if st.writeDeadline != nil {
|
||||||
st.writeDeadline.Stop()
|
st.writeDeadline.Stop()
|
||||||
}
|
}
|
||||||
@ -1589,6 +1642,14 @@ func (sc *serverConn) closeStream(st *stream, err error) {
|
|||||||
|
|
||||||
p.CloseWithError(err)
|
p.CloseWithError(err)
|
||||||
}
|
}
|
||||||
|
if e, ok := err.(StreamError); ok {
|
||||||
|
if e.Cause != nil {
|
||||||
|
err = e.Cause
|
||||||
|
} else {
|
||||||
|
err = errStreamClosed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
st.closeErr = err
|
||||||
st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
|
st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
|
||||||
sc.writeSched.CloseStream(st.id)
|
sc.writeSched.CloseStream(st.id)
|
||||||
}
|
}
|
||||||
@ -1631,7 +1692,6 @@ func (sc *serverConn) processSetting(s Setting) error {
|
|||||||
}
|
}
|
||||||
switch s.ID {
|
switch s.ID {
|
||||||
case SettingHeaderTableSize:
|
case SettingHeaderTableSize:
|
||||||
sc.headerTableSize = s.Val
|
|
||||||
sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)
|
sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)
|
||||||
case SettingEnablePush:
|
case SettingEnablePush:
|
||||||
sc.pushEnabled = s.Val != 0
|
sc.pushEnabled = s.Val != 0
|
||||||
@ -1685,16 +1745,6 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
|
|||||||
func (sc *serverConn) processData(f *DataFrame) error {
|
func (sc *serverConn) processData(f *DataFrame) error {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
id := f.Header().StreamID
|
id := f.Header().StreamID
|
||||||
if sc.inGoAway && (sc.goAwayCode != ErrCodeNo || id > sc.maxClientStreamID) {
|
|
||||||
// Discard all DATA frames if the GOAWAY is due to an
|
|
||||||
// error, or:
|
|
||||||
//
|
|
||||||
// Section 6.8: After sending a GOAWAY frame, the sender
|
|
||||||
// can discard frames for streams initiated by the
|
|
||||||
// receiver with identifiers higher than the identified
|
|
||||||
// last stream.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data := f.Data()
|
data := f.Data()
|
||||||
state, st := sc.state(id)
|
state, st := sc.state(id)
|
||||||
@ -1725,14 +1775,9 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||||||
// But still enforce their connection-level flow control,
|
// But still enforce their connection-level flow control,
|
||||||
// and return any flow control bytes since we're not going
|
// and return any flow control bytes since we're not going
|
||||||
// to consume them.
|
// to consume them.
|
||||||
if sc.inflow.available() < int32(f.Length) {
|
if !sc.inflow.take(f.Length) {
|
||||||
return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))
|
return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))
|
||||||
}
|
}
|
||||||
// Deduct the flow control from inflow, since we're
|
|
||||||
// going to immediately add it back in
|
|
||||||
// sendWindowUpdate, which also schedules sending the
|
|
||||||
// frames.
|
|
||||||
sc.inflow.take(int32(f.Length))
|
|
||||||
sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
|
sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
|
||||||
|
|
||||||
if st != nil && st.resetQueued {
|
if st != nil && st.resetQueued {
|
||||||
@ -1747,6 +1792,11 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||||||
|
|
||||||
// Sender sending more than they'd declared?
|
// Sender sending more than they'd declared?
|
||||||
if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
|
if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
|
||||||
|
if !sc.inflow.take(f.Length) {
|
||||||
|
return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))
|
||||||
|
}
|
||||||
|
sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
|
||||||
|
|
||||||
st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
|
st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
|
||||||
// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
|
// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
|
||||||
// value of a content-length header field does not equal the sum of the
|
// value of a content-length header field does not equal the sum of the
|
||||||
@ -1755,10 +1805,9 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||||||
}
|
}
|
||||||
if f.Length > 0 {
|
if f.Length > 0 {
|
||||||
// Check whether the client has flow control quota.
|
// Check whether the client has flow control quota.
|
||||||
if st.inflow.available() < int32(f.Length) {
|
if !takeInflows(&sc.inflow, &st.inflow, f.Length) {
|
||||||
return sc.countError("flow_on_data_length", streamError(id, ErrCodeFlowControl))
|
return sc.countError("flow_on_data_length", streamError(id, ErrCodeFlowControl))
|
||||||
}
|
}
|
||||||
st.inflow.take(int32(f.Length))
|
|
||||||
|
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
wrote, err := st.body.Write(data)
|
wrote, err := st.body.Write(data)
|
||||||
@ -1774,10 +1823,12 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||||||
|
|
||||||
// Return any padded flow control now, since we won't
|
// Return any padded flow control now, since we won't
|
||||||
// refund it later on body reads.
|
// refund it later on body reads.
|
||||||
if pad := int32(f.Length) - int32(len(data)); pad > 0 {
|
// Call sendWindowUpdate even if there is no padding,
|
||||||
sc.sendWindowUpdate32(nil, pad)
|
// to return buffered flow control credit if the sent
|
||||||
sc.sendWindowUpdate32(st, pad)
|
// window has shrunk.
|
||||||
}
|
pad := int32(f.Length) - int32(len(data))
|
||||||
|
sc.sendWindowUpdate32(nil, pad)
|
||||||
|
sc.sendWindowUpdate32(st, pad)
|
||||||
}
|
}
|
||||||
if f.StreamEnded() {
|
if f.StreamEnded() {
|
||||||
st.endStream()
|
st.endStream()
|
||||||
@ -1831,19 +1882,27 @@ func (st *stream) copyTrailersToHandlerRequest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// onReadTimeout is run on its own goroutine (from time.AfterFunc)
|
||||||
|
// when the stream's ReadTimeout has fired.
|
||||||
|
func (st *stream) onReadTimeout() {
|
||||||
|
// Wrap the ErrDeadlineExceeded to avoid callers depending on us
|
||||||
|
// returning the bare error.
|
||||||
|
st.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded))
|
||||||
|
}
|
||||||
|
|
||||||
// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
|
// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
|
||||||
// when the stream's WriteTimeout has fired.
|
// when the stream's WriteTimeout has fired.
|
||||||
func (st *stream) onWriteTimeout() {
|
func (st *stream) onWriteTimeout() {
|
||||||
st.sc.writeFrameFromHandler(FrameWriteRequest{write: streamError(st.id, ErrCodeInternal)})
|
st.sc.writeFrameFromHandler(FrameWriteRequest{write: StreamError{
|
||||||
|
StreamID: st.id,
|
||||||
|
Code: ErrCodeInternal,
|
||||||
|
Cause: os.ErrDeadlineExceeded,
|
||||||
|
}})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
id := f.StreamID
|
id := f.StreamID
|
||||||
if sc.inGoAway {
|
|
||||||
// Ignore.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// http://tools.ietf.org/html/rfc7540#section-5.1.1
|
// http://tools.ietf.org/html/rfc7540#section-5.1.1
|
||||||
// Streams initiated by a client MUST use odd-numbered stream
|
// Streams initiated by a client MUST use odd-numbered stream
|
||||||
// identifiers. [...] An endpoint that receives an unexpected
|
// identifiers. [...] An endpoint that receives an unexpected
|
||||||
@ -1946,6 +2005,9 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||||||
// (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{})
|
||||||
|
if st.body != nil {
|
||||||
|
st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
go sc.runHandler(rw, req, handler)
|
go sc.runHandler(rw, req, handler)
|
||||||
@ -2014,9 +2076,6 @@ func (sc *serverConn) checkPriority(streamID uint32, p PriorityParam) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serverConn) processPriority(f *PriorityFrame) error {
|
func (sc *serverConn) processPriority(f *PriorityFrame) error {
|
||||||
if sc.inGoAway {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil {
|
if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2041,8 +2100,7 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
|
|||||||
st.cw.Init()
|
st.cw.Init()
|
||||||
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.conn = &sc.inflow // link to conn-level counter
|
st.inflow.init(sc.srv.initialStreamRecvWindowSize())
|
||||||
st.inflow.add(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)
|
||||||
}
|
}
|
||||||
@ -2090,12 +2148,6 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
|||||||
return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol))
|
return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyOpen := !f.StreamEnded()
|
|
||||||
if rp.method == "HEAD" && bodyOpen {
|
|
||||||
// HEAD requests can't have bodies
|
|
||||||
return nil, nil, sc.countError("head_body", streamError(f.StreamID, ErrCodeProtocol))
|
|
||||||
}
|
|
||||||
|
|
||||||
rp.header = make(http.Header)
|
rp.header = make(http.Header)
|
||||||
for _, hf := range f.RegularFields() {
|
for _, hf := range f.RegularFields() {
|
||||||
rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value)
|
rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value)
|
||||||
@ -2108,6 +2160,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
bodyOpen := !f.StreamEnded()
|
||||||
if bodyOpen {
|
if bodyOpen {
|
||||||
if vv, ok := rp.header["Content-Length"]; ok {
|
if vv, ok := rp.header["Content-Length"]; ok {
|
||||||
if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil {
|
if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil {
|
||||||
@ -2223,6 +2276,9 @@ func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler
|
|||||||
didPanic := true
|
didPanic := true
|
||||||
defer func() {
|
defer func() {
|
||||||
rw.rws.stream.cancelCtx()
|
rw.rws.stream.cancelCtx()
|
||||||
|
if req.MultipartForm != nil {
|
||||||
|
req.MultipartForm.RemoveAll()
|
||||||
|
}
|
||||||
if didPanic {
|
if didPanic {
|
||||||
e := recover()
|
e := recover()
|
||||||
sc.writeFrameFromHandler(FrameWriteRequest{
|
sc.writeFrameFromHandler(FrameWriteRequest{
|
||||||
@ -2326,47 +2382,28 @@ func (sc *serverConn) noteBodyRead(st *stream, n int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// st may be nil for conn-level
|
// st may be nil for conn-level
|
||||||
func (sc *serverConn) sendWindowUpdate(st *stream, n int) {
|
func (sc *serverConn) sendWindowUpdate32(st *stream, n int32) {
|
||||||
sc.serveG.check()
|
sc.sendWindowUpdate(st, int(n))
|
||||||
// "The legal range for the increment to the flow control
|
|
||||||
// window is 1 to 2^31-1 (2,147,483,647) octets."
|
|
||||||
// A Go Read call on 64-bit machines could in theory read
|
|
||||||
// a larger Read than this. Very unlikely, but we handle it here
|
|
||||||
// rather than elsewhere for now.
|
|
||||||
const maxUint31 = 1<<31 - 1
|
|
||||||
for n >= maxUint31 {
|
|
||||||
sc.sendWindowUpdate32(st, maxUint31)
|
|
||||||
n -= maxUint31
|
|
||||||
}
|
|
||||||
sc.sendWindowUpdate32(st, int32(n))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// st may be nil for conn-level
|
// st may be nil for conn-level
|
||||||
func (sc *serverConn) sendWindowUpdate32(st *stream, n int32) {
|
func (sc *serverConn) sendWindowUpdate(st *stream, n int) {
|
||||||
sc.serveG.check()
|
sc.serveG.check()
|
||||||
if n == 0 {
|
var streamID uint32
|
||||||
|
var send int32
|
||||||
|
if st == nil {
|
||||||
|
send = sc.inflow.add(n)
|
||||||
|
} else {
|
||||||
|
streamID = st.id
|
||||||
|
send = st.inflow.add(n)
|
||||||
|
}
|
||||||
|
if send == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n < 0 {
|
|
||||||
panic("negative update")
|
|
||||||
}
|
|
||||||
var streamID uint32
|
|
||||||
if st != nil {
|
|
||||||
streamID = st.id
|
|
||||||
}
|
|
||||||
sc.writeFrame(FrameWriteRequest{
|
sc.writeFrame(FrameWriteRequest{
|
||||||
write: writeWindowUpdate{streamID: streamID, n: uint32(n)},
|
write: writeWindowUpdate{streamID: streamID, n: uint32(send)},
|
||||||
stream: st,
|
stream: st,
|
||||||
})
|
})
|
||||||
var ok bool
|
|
||||||
if st == nil {
|
|
||||||
ok = sc.inflow.add(n)
|
|
||||||
} else {
|
|
||||||
ok = st.inflow.add(n)
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
panic("internal error; sent too many window updates without decrements?")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// requestBody is the Handler's Request.Body type.
|
// requestBody is the Handler's Request.Body type.
|
||||||
@ -2454,7 +2491,15 @@ type responseWriterState struct {
|
|||||||
|
|
||||||
type chunkWriter struct{ rws *responseWriterState }
|
type chunkWriter struct{ rws *responseWriterState }
|
||||||
|
|
||||||
func (cw chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) }
|
func (cw chunkWriter) Write(p []byte) (n int, err error) {
|
||||||
|
n, err = cw.rws.writeChunk(p)
|
||||||
|
if err == errStreamClosed {
|
||||||
|
// If writing failed because the stream has been closed,
|
||||||
|
// return the reason it was closed.
|
||||||
|
err = cw.rws.stream.closeErr
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) > 0 }
|
func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) > 0 }
|
||||||
|
|
||||||
@ -2493,6 +2538,10 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
rws.writeHeader(200)
|
rws.writeHeader(200)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rws.handlerDone {
|
||||||
|
rws.promoteUndeclaredTrailers()
|
||||||
|
}
|
||||||
|
|
||||||
isHeadResp := rws.req.Method == "HEAD"
|
isHeadResp := rws.req.Method == "HEAD"
|
||||||
if !rws.sentHeader {
|
if !rws.sentHeader {
|
||||||
rws.sentHeader = true
|
rws.sentHeader = true
|
||||||
@ -2564,10 +2613,6 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if rws.handlerDone {
|
|
||||||
rws.promoteUndeclaredTrailers()
|
|
||||||
}
|
|
||||||
|
|
||||||
// only send trailers if they have actually been defined by the
|
// only send trailers if they have actually been defined by the
|
||||||
// server handler.
|
// server handler.
|
||||||
hasNonemptyTrailers := rws.hasNonemptyTrailers()
|
hasNonemptyTrailers := rws.hasNonemptyTrailers()
|
||||||
@ -2648,23 +2693,85 @@ func (rws *responseWriterState) promoteUndeclaredTrailers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
|
||||||
|
st := w.rws.stream
|
||||||
|
if !deadline.IsZero() && deadline.Before(time.Now()) {
|
||||||
|
// If we're setting a deadline in the past, reset the stream immediately
|
||||||
|
// so writes after SetWriteDeadline returns will fail.
|
||||||
|
st.onReadTimeout()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
w.rws.conn.sendServeMsg(func(sc *serverConn) {
|
||||||
|
if st.readDeadline != nil {
|
||||||
|
if !st.readDeadline.Stop() {
|
||||||
|
// Deadline already exceeded, or stream has been closed.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if deadline.IsZero() {
|
||||||
|
st.readDeadline = nil
|
||||||
|
} else if st.readDeadline == nil {
|
||||||
|
st.readDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onReadTimeout)
|
||||||
|
} else {
|
||||||
|
st.readDeadline.Reset(deadline.Sub(time.Now()))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *responseWriter) SetWriteDeadline(deadline time.Time) error {
|
||||||
|
st := w.rws.stream
|
||||||
|
if !deadline.IsZero() && deadline.Before(time.Now()) {
|
||||||
|
// If we're setting a deadline in the past, reset the stream immediately
|
||||||
|
// so writes after SetWriteDeadline returns will fail.
|
||||||
|
st.onWriteTimeout()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
w.rws.conn.sendServeMsg(func(sc *serverConn) {
|
||||||
|
if st.writeDeadline != nil {
|
||||||
|
if !st.writeDeadline.Stop() {
|
||||||
|
// Deadline already exceeded, or stream has been closed.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if deadline.IsZero() {
|
||||||
|
st.writeDeadline = nil
|
||||||
|
} else if st.writeDeadline == nil {
|
||||||
|
st.writeDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onWriteTimeout)
|
||||||
|
} else {
|
||||||
|
st.writeDeadline.Reset(deadline.Sub(time.Now()))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (w *responseWriter) Flush() {
|
func (w *responseWriter) Flush() {
|
||||||
|
w.FlushError()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *responseWriter) FlushError() error {
|
||||||
rws := w.rws
|
rws := w.rws
|
||||||
if rws == nil {
|
if rws == nil {
|
||||||
panic("Header called after Handler finished")
|
panic("Header called after Handler finished")
|
||||||
}
|
}
|
||||||
|
var err error
|
||||||
if rws.bw.Buffered() > 0 {
|
if rws.bw.Buffered() > 0 {
|
||||||
if err := rws.bw.Flush(); err != nil {
|
err = rws.bw.Flush()
|
||||||
// Ignore the error. The frame writer already knows.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// The bufio.Writer won't call chunkWriter.Write
|
// The bufio.Writer won't call chunkWriter.Write
|
||||||
// (writeChunk with zero bytes, so we have to do it
|
// (writeChunk with zero bytes, so we have to do it
|
||||||
// ourselves to force the HTTP response header and/or
|
// ourselves to force the HTTP response header and/or
|
||||||
// final DATA frame (with END_STREAM) to be sent.
|
// final DATA frame (with END_STREAM) to be sent.
|
||||||
rws.writeChunk(nil)
|
_, err = chunkWriter{rws}.Write(nil)
|
||||||
|
if err == nil {
|
||||||
|
select {
|
||||||
|
case <-rws.stream.cw:
|
||||||
|
err = rws.stream.closeErr
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *responseWriter) CloseNotify() <-chan bool {
|
func (w *responseWriter) CloseNotify() <-chan bool {
|
||||||
|
319
vendor/golang.org/x/net/http2/transport.go
generated
vendored
319
vendor/golang.org/x/net/http2/transport.go
generated
vendored
@ -16,6 +16,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
mathrand "math/rand"
|
mathrand "math/rand"
|
||||||
@ -46,10 +47,6 @@ const (
|
|||||||
// we buffer per stream.
|
// we buffer per stream.
|
||||||
transportDefaultStreamFlow = 4 << 20
|
transportDefaultStreamFlow = 4 << 20
|
||||||
|
|
||||||
// transportDefaultStreamMinRefresh is the minimum number of bytes we'll send
|
|
||||||
// a stream-level WINDOW_UPDATE for at a time.
|
|
||||||
transportDefaultStreamMinRefresh = 4 << 10
|
|
||||||
|
|
||||||
defaultUserAgent = "Go-http-client/2.0"
|
defaultUserAgent = "Go-http-client/2.0"
|
||||||
|
|
||||||
// initialMaxConcurrentStreams is a connections maxConcurrentStreams until
|
// initialMaxConcurrentStreams is a connections maxConcurrentStreams until
|
||||||
@ -67,13 +64,23 @@ const (
|
|||||||
// A Transport internally caches connections to servers. It is safe
|
// A Transport internally caches connections to servers. It is safe
|
||||||
// for concurrent use by multiple goroutines.
|
// for concurrent use by multiple goroutines.
|
||||||
type Transport struct {
|
type Transport struct {
|
||||||
// DialTLS specifies an optional dial function for creating
|
// DialTLSContext specifies an optional dial function with context for
|
||||||
// TLS connections for requests.
|
// creating TLS connections for requests.
|
||||||
//
|
//
|
||||||
// If DialTLS is nil, tls.Dial is used.
|
// If DialTLSContext and DialTLS is nil, tls.Dial is used.
|
||||||
//
|
//
|
||||||
// If the returned net.Conn has a ConnectionState method like tls.Conn,
|
// If the returned net.Conn has a ConnectionState method like tls.Conn,
|
||||||
// it will be used to set http.Response.TLS.
|
// it will be used to set http.Response.TLS.
|
||||||
|
DialTLSContext func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error)
|
||||||
|
|
||||||
|
// DialTLS specifies an optional dial function for creating
|
||||||
|
// TLS connections for requests.
|
||||||
|
//
|
||||||
|
// If DialTLSContext and DialTLS is nil, tls.Dial is used.
|
||||||
|
//
|
||||||
|
// Deprecated: Use DialTLSContext instead, which allows the transport
|
||||||
|
// to cancel dials as soon as they are no longer needed.
|
||||||
|
// If both are set, DialTLSContext takes priority.
|
||||||
DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error)
|
DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error)
|
||||||
|
|
||||||
// TLSClientConfig specifies the TLS configuration to use with
|
// TLSClientConfig specifies the TLS configuration to use with
|
||||||
@ -107,6 +114,28 @@ type Transport struct {
|
|||||||
// to mean no limit.
|
// to mean no limit.
|
||||||
MaxHeaderListSize uint32
|
MaxHeaderListSize uint32
|
||||||
|
|
||||||
|
// MaxReadFrameSize is the http2 SETTINGS_MAX_FRAME_SIZE to send in the
|
||||||
|
// initial settings frame. It is the size in bytes of the largest frame
|
||||||
|
// payload that the sender is willing to receive. If 0, no setting is
|
||||||
|
// sent, and the value is provided by the peer, which should be 16384
|
||||||
|
// according to the spec:
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc7540#section-6.5.2.
|
||||||
|
// Values are bounded in the range 16k to 16M.
|
||||||
|
MaxReadFrameSize uint32
|
||||||
|
|
||||||
|
// MaxDecoderHeaderTableSize optionally specifies the http2
|
||||||
|
// SETTINGS_HEADER_TABLE_SIZE to send in the initial settings frame. It
|
||||||
|
// informs the remote endpoint of the maximum size of the header compression
|
||||||
|
// table used to decode header blocks, in octets. If zero, the default value
|
||||||
|
// of 4096 is used.
|
||||||
|
MaxDecoderHeaderTableSize uint32
|
||||||
|
|
||||||
|
// MaxEncoderHeaderTableSize optionally specifies an upper limit for the
|
||||||
|
// header compression table used for encoding request headers. Received
|
||||||
|
// SETTINGS_HEADER_TABLE_SIZE settings are capped at this limit. If zero,
|
||||||
|
// the default value of 4096 is used.
|
||||||
|
MaxEncoderHeaderTableSize uint32
|
||||||
|
|
||||||
// StrictMaxConcurrentStreams controls whether the server's
|
// StrictMaxConcurrentStreams controls whether the server's
|
||||||
// SETTINGS_MAX_CONCURRENT_STREAMS should be respected
|
// SETTINGS_MAX_CONCURRENT_STREAMS should be respected
|
||||||
// globally. If false, new TCP connections are created to the
|
// globally. If false, new TCP connections are created to the
|
||||||
@ -160,6 +189,19 @@ func (t *Transport) maxHeaderListSize() uint32 {
|
|||||||
return t.MaxHeaderListSize
|
return t.MaxHeaderListSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Transport) maxFrameReadSize() uint32 {
|
||||||
|
if t.MaxReadFrameSize == 0 {
|
||||||
|
return 0 // use the default provided by the peer
|
||||||
|
}
|
||||||
|
if t.MaxReadFrameSize < minMaxFrameSize {
|
||||||
|
return minMaxFrameSize
|
||||||
|
}
|
||||||
|
if t.MaxReadFrameSize > maxFrameSize {
|
||||||
|
return maxFrameSize
|
||||||
|
}
|
||||||
|
return t.MaxReadFrameSize
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Transport) disableCompression() bool {
|
func (t *Transport) disableCompression() bool {
|
||||||
return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression)
|
return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression)
|
||||||
}
|
}
|
||||||
@ -248,7 +290,8 @@ func (t *Transport) initConnPool() {
|
|||||||
// HTTP/2 server.
|
// HTTP/2 server.
|
||||||
type ClientConn struct {
|
type ClientConn struct {
|
||||||
t *Transport
|
t *Transport
|
||||||
tconn net.Conn // usually *tls.Conn, except specialized impls
|
tconn net.Conn // usually *tls.Conn, except specialized impls
|
||||||
|
tconnClosed bool
|
||||||
tlsState *tls.ConnectionState // nil only for specialized impls
|
tlsState *tls.ConnectionState // nil only for specialized impls
|
||||||
reused uint32 // whether conn is being reused; atomic
|
reused uint32 // whether conn is being reused; atomic
|
||||||
singleUse bool // whether being used for a single http.Request
|
singleUse bool // whether being used for a single http.Request
|
||||||
@ -263,8 +306,8 @@ type ClientConn struct {
|
|||||||
|
|
||||||
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
|
||||||
flow flow // our conn-level flow control quota (cs.flow is per stream)
|
flow outflow // our conn-level flow control quota (cs.outflow is per stream)
|
||||||
inflow flow // peer's conn-level flow control
|
inflow inflow // peer's conn-level flow control
|
||||||
doNotReuse bool // whether conn is marked to not be reused for any future requests
|
doNotReuse bool // whether conn is marked to not be reused for any future requests
|
||||||
closing bool
|
closing bool
|
||||||
closed bool
|
closed bool
|
||||||
@ -281,10 +324,11 @@ type ClientConn struct {
|
|||||||
lastActive time.Time
|
lastActive time.Time
|
||||||
lastIdle time.Time // time last idle
|
lastIdle time.Time // time last idle
|
||||||
// Settings from peer: (also guarded by wmu)
|
// Settings from peer: (also guarded by wmu)
|
||||||
maxFrameSize uint32
|
maxFrameSize uint32
|
||||||
maxConcurrentStreams uint32
|
maxConcurrentStreams uint32
|
||||||
peerMaxHeaderListSize uint64
|
peerMaxHeaderListSize uint64
|
||||||
initialWindowSize uint32
|
peerMaxHeaderTableSize uint32
|
||||||
|
initialWindowSize uint32
|
||||||
|
|
||||||
// reqHeaderMu is a 1-element semaphore channel controlling access to sending new requests.
|
// reqHeaderMu is a 1-element semaphore channel controlling access to sending new requests.
|
||||||
// Write to reqHeaderMu to lock it, read from it to unlock.
|
// Write to reqHeaderMu to lock it, read from it to unlock.
|
||||||
@ -328,14 +372,14 @@ type clientStream struct {
|
|||||||
respHeaderRecv chan struct{} // closed when headers are received
|
respHeaderRecv chan struct{} // closed when headers are received
|
||||||
res *http.Response // set if respHeaderRecv is closed
|
res *http.Response // set if respHeaderRecv is closed
|
||||||
|
|
||||||
flow flow // guarded by cc.mu
|
flow outflow // guarded by cc.mu
|
||||||
inflow flow // guarded by cc.mu
|
inflow inflow // guarded by cc.mu
|
||||||
bytesRemain int64 // -1 means unknown; owned by transportResponseBody.Read
|
bytesRemain int64 // -1 means unknown; owned by transportResponseBody.Read
|
||||||
readErr error // sticky read error; owned by transportResponseBody.Read
|
readErr error // sticky read error; owned by transportResponseBody.Read
|
||||||
|
|
||||||
reqBody io.ReadCloser
|
reqBody io.ReadCloser
|
||||||
reqBodyContentLength int64 // -1 means unknown
|
reqBodyContentLength int64 // -1 means unknown
|
||||||
reqBodyClosed bool // body has been closed; guarded by cc.mu
|
reqBodyClosed chan struct{} // guarded by cc.mu; non-nil on Close, closed when done
|
||||||
|
|
||||||
// owned by writeRequest:
|
// owned by writeRequest:
|
||||||
sentEndStream bool // sent an END_STREAM flag to the peer
|
sentEndStream bool // sent an END_STREAM flag to the peer
|
||||||
@ -375,9 +419,8 @@ func (cs *clientStream) abortStreamLocked(err error) {
|
|||||||
cs.abortErr = err
|
cs.abortErr = err
|
||||||
close(cs.abort)
|
close(cs.abort)
|
||||||
})
|
})
|
||||||
if cs.reqBody != nil && !cs.reqBodyClosed {
|
if cs.reqBody != nil {
|
||||||
cs.reqBody.Close()
|
cs.closeReqBodyLocked()
|
||||||
cs.reqBodyClosed = true
|
|
||||||
}
|
}
|
||||||
// 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 {
|
||||||
@ -390,13 +433,24 @@ func (cs *clientStream) abortRequestBodyWrite() {
|
|||||||
cc := cs.cc
|
cc := cs.cc
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
defer cc.mu.Unlock()
|
defer cc.mu.Unlock()
|
||||||
if cs.reqBody != nil && !cs.reqBodyClosed {
|
if cs.reqBody != nil && cs.reqBodyClosed == nil {
|
||||||
cs.reqBody.Close()
|
cs.closeReqBodyLocked()
|
||||||
cs.reqBodyClosed = true
|
|
||||||
cc.cond.Broadcast()
|
cc.cond.Broadcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *clientStream) closeReqBodyLocked() {
|
||||||
|
if cs.reqBodyClosed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cs.reqBodyClosed = make(chan struct{})
|
||||||
|
reqBodyClosed := cs.reqBodyClosed
|
||||||
|
go func() {
|
||||||
|
cs.reqBody.Close()
|
||||||
|
close(reqBodyClosed)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
type stickyErrWriter struct {
|
type stickyErrWriter struct {
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
@ -480,6 +534,15 @@ 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)) {
|
||||||
@ -505,11 +568,14 @@ 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)
|
||||||
|
timer := backoffNewTimer(d)
|
||||||
select {
|
select {
|
||||||
case <-time.After(time.Second * time.Duration(backoff)):
|
case <-timer.C:
|
||||||
t.vlogf("RoundTrip retrying after failure: %v", err)
|
t.vlogf("RoundTrip retrying after failure: %v", err)
|
||||||
continue
|
continue
|
||||||
case <-req.Context().Done():
|
case <-req.Context().Done():
|
||||||
|
timer.Stop()
|
||||||
err = req.Context().Err()
|
err = req.Context().Err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -592,7 +658,7 @@ func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse b
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tconn, err := t.dialTLS(ctx)("tcp", addr, t.newTLSConfig(host))
|
tconn, err := t.dialTLS(ctx, "tcp", addr, t.newTLSConfig(host))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -613,24 +679,25 @@ func (t *Transport) newTLSConfig(host string) *tls.Config {
|
|||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) dialTLS(ctx context.Context) func(string, string, *tls.Config) (net.Conn, error) {
|
func (t *Transport) dialTLS(ctx context.Context, network, addr string, tlsCfg *tls.Config) (net.Conn, error) {
|
||||||
if t.DialTLS != nil {
|
if t.DialTLSContext != nil {
|
||||||
return t.DialTLS
|
return t.DialTLSContext(ctx, network, addr, tlsCfg)
|
||||||
|
} else if t.DialTLS != nil {
|
||||||
|
return t.DialTLS(network, addr, tlsCfg)
|
||||||
}
|
}
|
||||||
return func(network, addr string, cfg *tls.Config) (net.Conn, error) {
|
|
||||||
tlsCn, err := t.dialTLSWithContext(ctx, network, addr, cfg)
|
tlsCn, err := t.dialTLSWithContext(ctx, network, addr, tlsCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
|
||||||
state := tlsCn.ConnectionState()
|
|
||||||
if p := state.NegotiatedProtocol; p != NextProtoTLS {
|
|
||||||
return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, NextProtoTLS)
|
|
||||||
}
|
|
||||||
if !state.NegotiatedProtocolIsMutual {
|
|
||||||
return nil, errors.New("http2: could not negotiate protocol mutually")
|
|
||||||
}
|
|
||||||
return tlsCn, nil
|
|
||||||
}
|
}
|
||||||
|
state := tlsCn.ConnectionState()
|
||||||
|
if p := state.NegotiatedProtocol; p != NextProtoTLS {
|
||||||
|
return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, NextProtoTLS)
|
||||||
|
}
|
||||||
|
if !state.NegotiatedProtocolIsMutual {
|
||||||
|
return nil, errors.New("http2: could not negotiate protocol mutually")
|
||||||
|
}
|
||||||
|
return tlsCn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// disableKeepAlives reports whether connections should be closed as
|
// disableKeepAlives reports whether connections should be closed as
|
||||||
@ -646,6 +713,20 @@ func (t *Transport) expectContinueTimeout() time.Duration {
|
|||||||
return t.t1.ExpectContinueTimeout
|
return t.t1.ExpectContinueTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Transport) maxDecoderHeaderTableSize() uint32 {
|
||||||
|
if v := t.MaxDecoderHeaderTableSize; v > 0 {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return initialHeaderTableSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Transport) maxEncoderHeaderTableSize() uint32 {
|
||||||
|
if v := t.MaxEncoderHeaderTableSize; v > 0 {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return initialHeaderTableSize
|
||||||
|
}
|
||||||
|
|
||||||
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())
|
||||||
}
|
}
|
||||||
@ -686,15 +767,19 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
|
|||||||
})
|
})
|
||||||
cc.br = bufio.NewReader(c)
|
cc.br = bufio.NewReader(c)
|
||||||
cc.fr = NewFramer(cc.bw, cc.br)
|
cc.fr = NewFramer(cc.bw, cc.br)
|
||||||
|
if t.maxFrameReadSize() != 0 {
|
||||||
|
cc.fr.SetMaxReadFrameSize(t.maxFrameReadSize())
|
||||||
|
}
|
||||||
if t.CountError != nil {
|
if t.CountError != nil {
|
||||||
cc.fr.countError = t.CountError
|
cc.fr.countError = t.CountError
|
||||||
}
|
}
|
||||||
cc.fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
|
maxHeaderTableSize := t.maxDecoderHeaderTableSize()
|
||||||
|
cc.fr.ReadMetaHeaders = hpack.NewDecoder(maxHeaderTableSize, nil)
|
||||||
cc.fr.MaxHeaderListSize = t.maxHeaderListSize()
|
cc.fr.MaxHeaderListSize = t.maxHeaderListSize()
|
||||||
|
|
||||||
// TODO: SetMaxDynamicTableSize, SetMaxDynamicTableSizeLimit on
|
|
||||||
// henc in response to SETTINGS frames?
|
|
||||||
cc.henc = hpack.NewEncoder(&cc.hbuf)
|
cc.henc = hpack.NewEncoder(&cc.hbuf)
|
||||||
|
cc.henc.SetMaxDynamicTableSizeLimit(t.maxEncoderHeaderTableSize())
|
||||||
|
cc.peerMaxHeaderTableSize = initialHeaderTableSize
|
||||||
|
|
||||||
if t.AllowHTTP {
|
if t.AllowHTTP {
|
||||||
cc.nextStreamID = 3
|
cc.nextStreamID = 3
|
||||||
@ -709,14 +794,20 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
|
|||||||
{ID: SettingEnablePush, Val: 0},
|
{ID: SettingEnablePush, Val: 0},
|
||||||
{ID: SettingInitialWindowSize, Val: transportDefaultStreamFlow},
|
{ID: SettingInitialWindowSize, Val: transportDefaultStreamFlow},
|
||||||
}
|
}
|
||||||
|
if max := t.maxFrameReadSize(); max != 0 {
|
||||||
|
initialSettings = append(initialSettings, Setting{ID: SettingMaxFrameSize, Val: max})
|
||||||
|
}
|
||||||
if max := t.maxHeaderListSize(); max != 0 {
|
if max := t.maxHeaderListSize(); max != 0 {
|
||||||
initialSettings = append(initialSettings, Setting{ID: SettingMaxHeaderListSize, Val: max})
|
initialSettings = append(initialSettings, Setting{ID: SettingMaxHeaderListSize, Val: max})
|
||||||
}
|
}
|
||||||
|
if maxHeaderTableSize != initialHeaderTableSize {
|
||||||
|
initialSettings = append(initialSettings, Setting{ID: SettingHeaderTableSize, Val: maxHeaderTableSize})
|
||||||
|
}
|
||||||
|
|
||||||
cc.bw.Write(clientPreface)
|
cc.bw.Write(clientPreface)
|
||||||
cc.fr.WriteSettings(initialSettings...)
|
cc.fr.WriteSettings(initialSettings...)
|
||||||
cc.fr.WriteWindowUpdate(0, transportDefaultConnFlow)
|
cc.fr.WriteWindowUpdate(0, transportDefaultConnFlow)
|
||||||
cc.inflow.add(transportDefaultConnFlow + initialWindowSize)
|
cc.inflow.init(transportDefaultConnFlow + initialWindowSize)
|
||||||
cc.bw.Flush()
|
cc.bw.Flush()
|
||||||
if cc.werr != nil {
|
if cc.werr != nil {
|
||||||
cc.Close()
|
cc.Close()
|
||||||
@ -910,10 +1001,10 @@ func (cc *ClientConn) onIdleTimeout() {
|
|||||||
cc.closeIfIdle()
|
cc.closeIfIdle()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *ClientConn) closeConn() error {
|
func (cc *ClientConn) closeConn() {
|
||||||
t := time.AfterFunc(250*time.Millisecond, cc.forceCloseConn)
|
t := time.AfterFunc(250*time.Millisecond, cc.forceCloseConn)
|
||||||
defer t.Stop()
|
defer t.Stop()
|
||||||
return cc.tconn.Close()
|
cc.tconn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A tls.Conn.Close can hang for a long time if the peer is unresponsive.
|
// A tls.Conn.Close can hang for a long time if the peer is unresponsive.
|
||||||
@ -979,7 +1070,8 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
|
|||||||
shutdownEnterWaitStateHook()
|
shutdownEnterWaitStateHook()
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
return cc.closeConn()
|
cc.closeConn()
|
||||||
|
return nil
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
// Free the goroutine above
|
// Free the goroutine above
|
||||||
@ -1016,7 +1108,7 @@ func (cc *ClientConn) sendGoAway() error {
|
|||||||
|
|
||||||
// closes the client connection immediately. In-flight requests are interrupted.
|
// closes the client connection immediately. In-flight requests are interrupted.
|
||||||
// err is sent to streams.
|
// err is sent to streams.
|
||||||
func (cc *ClientConn) closeForError(err error) error {
|
func (cc *ClientConn) closeForError(err error) {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
cc.closed = true
|
cc.closed = true
|
||||||
for _, cs := range cc.streams {
|
for _, cs := range cc.streams {
|
||||||
@ -1024,7 +1116,7 @@ func (cc *ClientConn) closeForError(err error) error {
|
|||||||
}
|
}
|
||||||
cc.cond.Broadcast()
|
cc.cond.Broadcast()
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
return cc.closeConn()
|
cc.closeConn()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the client connection immediately.
|
// Close closes the client connection immediately.
|
||||||
@ -1032,16 +1124,17 @@ func (cc *ClientConn) closeForError(err error) error {
|
|||||||
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
|
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
|
||||||
func (cc *ClientConn) Close() error {
|
func (cc *ClientConn) Close() error {
|
||||||
err := errors.New("http2: client connection force closed via ClientConn.Close")
|
err := errors.New("http2: client connection force closed via ClientConn.Close")
|
||||||
return cc.closeForError(err)
|
cc.closeForError(err)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// closes the client connection immediately. In-flight requests are interrupted.
|
// closes the client connection immediately. In-flight requests are interrupted.
|
||||||
func (cc *ClientConn) closeForLostPing() error {
|
func (cc *ClientConn) closeForLostPing() {
|
||||||
err := errors.New("http2: client connection lost")
|
err := errors.New("http2: client connection lost")
|
||||||
if f := cc.t.CountError; f != nil {
|
if f := cc.t.CountError; f != nil {
|
||||||
f("conn_close_lost_ping")
|
f("conn_close_lost_ping")
|
||||||
}
|
}
|
||||||
return cc.closeForError(err)
|
cc.closeForError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// errRequestCanceled is a copy of net/http's errRequestCanceled because it's not
|
// errRequestCanceled is a copy of net/http's errRequestCanceled because it's not
|
||||||
@ -1051,7 +1144,7 @@ var errRequestCanceled = errors.New("net/http: request canceled")
|
|||||||
func commaSeparatedTrailers(req *http.Request) (string, error) {
|
func commaSeparatedTrailers(req *http.Request) (string, error) {
|
||||||
keys := make([]string, 0, len(req.Trailer))
|
keys := make([]string, 0, len(req.Trailer))
|
||||||
for k := range req.Trailer {
|
for k := range req.Trailer {
|
||||||
k = http.CanonicalHeaderKey(k)
|
k = canonicalHeader(k)
|
||||||
switch k {
|
switch k {
|
||||||
case "Transfer-Encoding", "Trailer", "Content-Length":
|
case "Transfer-Encoding", "Trailer", "Content-Length":
|
||||||
return "", fmt.Errorf("invalid Trailer key %q", k)
|
return "", fmt.Errorf("invalid Trailer key %q", k)
|
||||||
@ -1419,11 +1512,19 @@ func (cs *clientStream) cleanupWriteRequest(err error) {
|
|||||||
// and in multiple cases: server replies <=299 and >299
|
// and in multiple cases: server replies <=299 and >299
|
||||||
// while still writing request body
|
// while still writing request body
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
|
mustCloseBody := false
|
||||||
|
if cs.reqBody != nil && cs.reqBodyClosed == nil {
|
||||||
|
mustCloseBody = true
|
||||||
|
cs.reqBodyClosed = make(chan struct{})
|
||||||
|
}
|
||||||
bodyClosed := cs.reqBodyClosed
|
bodyClosed := cs.reqBodyClosed
|
||||||
cs.reqBodyClosed = true
|
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
if !bodyClosed && cs.reqBody != nil {
|
if mustCloseBody {
|
||||||
cs.reqBody.Close()
|
cs.reqBody.Close()
|
||||||
|
close(bodyClosed)
|
||||||
|
}
|
||||||
|
if bodyClosed != nil {
|
||||||
|
<-bodyClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil && cs.sentEndStream {
|
if err != nil && cs.sentEndStream {
|
||||||
@ -1580,7 +1681,7 @@ func (cs *clientStream) writeRequestBody(req *http.Request) (err error) {
|
|||||||
|
|
||||||
var sawEOF bool
|
var sawEOF bool
|
||||||
for !sawEOF {
|
for !sawEOF {
|
||||||
n, err := body.Read(buf[:len(buf)])
|
n, err := body.Read(buf)
|
||||||
if hasContentLen {
|
if hasContentLen {
|
||||||
remainLen -= int64(n)
|
remainLen -= int64(n)
|
||||||
if remainLen == 0 && err == nil {
|
if remainLen == 0 && err == nil {
|
||||||
@ -1603,7 +1704,7 @@ func (cs *clientStream) writeRequestBody(req *http.Request) (err error) {
|
|||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
bodyClosed := cs.reqBodyClosed
|
bodyClosed := cs.reqBodyClosed != nil
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
switch {
|
switch {
|
||||||
case bodyClosed:
|
case bodyClosed:
|
||||||
@ -1698,7 +1799,7 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error)
|
|||||||
if cc.closed {
|
if cc.closed {
|
||||||
return 0, errClientConnClosed
|
return 0, errClientConnClosed
|
||||||
}
|
}
|
||||||
if cs.reqBodyClosed {
|
if cs.reqBodyClosed != nil {
|
||||||
return 0, errStopReqBodyWrite
|
return 0, errStopReqBodyWrite
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
@ -1883,7 +1984,7 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
|
|||||||
|
|
||||||
// Header list size is ok. Write the headers.
|
// Header list size is ok. Write the headers.
|
||||||
enumerateHeaders(func(name, value string) {
|
enumerateHeaders(func(name, value string) {
|
||||||
name, ascii := asciiToLower(name)
|
name, ascii := lowerHeader(name)
|
||||||
if !ascii {
|
if !ascii {
|
||||||
// Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
|
// Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
|
||||||
// field names have to be ASCII characters (just as in HTTP/1.x).
|
// field names have to be ASCII characters (just as in HTTP/1.x).
|
||||||
@ -1936,7 +2037,7 @@ func (cc *ClientConn) encodeTrailers(trailer http.Header) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for k, vv := range trailer {
|
for k, vv := range trailer {
|
||||||
lowKey, ascii := asciiToLower(k)
|
lowKey, ascii := lowerHeader(k)
|
||||||
if !ascii {
|
if !ascii {
|
||||||
// Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
|
// Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
|
||||||
// field names have to be ASCII characters (just as in HTTP/1.x).
|
// field names have to be ASCII characters (just as in HTTP/1.x).
|
||||||
@ -1968,8 +2069,7 @@ type resAndError struct {
|
|||||||
func (cc *ClientConn) addStreamLocked(cs *clientStream) {
|
func (cc *ClientConn) addStreamLocked(cs *clientStream) {
|
||||||
cs.flow.add(int32(cc.initialWindowSize))
|
cs.flow.add(int32(cc.initialWindowSize))
|
||||||
cs.flow.setConnFlow(&cc.flow)
|
cs.flow.setConnFlow(&cc.flow)
|
||||||
cs.inflow.add(transportDefaultStreamFlow)
|
cs.inflow.init(transportDefaultStreamFlow)
|
||||||
cs.inflow.setConnFlow(&cc.inflow)
|
|
||||||
cs.ID = cc.nextStreamID
|
cs.ID = cc.nextStreamID
|
||||||
cc.nextStreamID += 2
|
cc.nextStreamID += 2
|
||||||
cc.streams[cs.ID] = cs
|
cc.streams[cs.ID] = cs
|
||||||
@ -1994,7 +2094,7 @@ func (cc *ClientConn) forgetStreamID(id uint32) {
|
|||||||
// wake up RoundTrip if there is a pending request.
|
// wake up RoundTrip if there is a pending request.
|
||||||
cc.cond.Broadcast()
|
cc.cond.Broadcast()
|
||||||
|
|
||||||
closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives()
|
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 {
|
||||||
if VerboseLogs {
|
if VerboseLogs {
|
||||||
cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, cc.nextStreamID-2)
|
cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, cc.nextStreamID-2)
|
||||||
@ -2070,6 +2170,7 @@ func (rl *clientConnReadLoop) cleanup() {
|
|||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
cc.closed = true
|
cc.closed = true
|
||||||
|
|
||||||
for _, cs := range cc.streams {
|
for _, cs := range cc.streams {
|
||||||
select {
|
select {
|
||||||
case <-cs.peerClosed:
|
case <-cs.peerClosed:
|
||||||
@ -2268,7 +2369,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
|
|||||||
Status: status + " " + http.StatusText(statusCode),
|
Status: status + " " + http.StatusText(statusCode),
|
||||||
}
|
}
|
||||||
for _, hf := range regularFields {
|
for _, hf := range regularFields {
|
||||||
key := http.CanonicalHeaderKey(hf.Name)
|
key := canonicalHeader(hf.Name)
|
||||||
if key == "Trailer" {
|
if key == "Trailer" {
|
||||||
t := res.Trailer
|
t := res.Trailer
|
||||||
if t == nil {
|
if t == nil {
|
||||||
@ -2276,7 +2377,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
|
|||||||
res.Trailer = t
|
res.Trailer = t
|
||||||
}
|
}
|
||||||
foreachHeaderElement(hf.Value, func(v string) {
|
foreachHeaderElement(hf.Value, func(v string) {
|
||||||
t[http.CanonicalHeaderKey(v)] = nil
|
t[canonicalHeader(v)] = nil
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
vv := header[key]
|
vv := header[key]
|
||||||
@ -2381,7 +2482,7 @@ func (rl *clientConnReadLoop) processTrailers(cs *clientStream, f *MetaHeadersFr
|
|||||||
|
|
||||||
trailer := make(http.Header)
|
trailer := make(http.Header)
|
||||||
for _, hf := range f.RegularFields() {
|
for _, hf := range f.RegularFields() {
|
||||||
key := http.CanonicalHeaderKey(hf.Name)
|
key := canonicalHeader(hf.Name)
|
||||||
trailer[key] = append(trailer[key], hf.Value)
|
trailer[key] = append(trailer[key], hf.Value)
|
||||||
}
|
}
|
||||||
cs.trailer = trailer
|
cs.trailer = trailer
|
||||||
@ -2427,21 +2528,10 @@ func (b transportResponseBody) Read(p []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
var connAdd, streamAdd int32
|
connAdd := cc.inflow.add(n)
|
||||||
// Check the conn-level first, before the stream-level.
|
var streamAdd int32
|
||||||
if v := cc.inflow.available(); v < transportDefaultConnFlow/2 {
|
|
||||||
connAdd = transportDefaultConnFlow - v
|
|
||||||
cc.inflow.add(connAdd)
|
|
||||||
}
|
|
||||||
if err == nil { // No need to refresh if the stream is over or failed.
|
if err == nil { // No need to refresh if the stream is over or failed.
|
||||||
// Consider any buffered body data (read from the conn but not
|
streamAdd = cs.inflow.add(n)
|
||||||
// consumed by the client) when computing flow control for this
|
|
||||||
// stream.
|
|
||||||
v := int(cs.inflow.available()) + cs.bufPipe.Len()
|
|
||||||
if v < transportDefaultStreamFlow-transportDefaultStreamMinRefresh {
|
|
||||||
streamAdd = int32(transportDefaultStreamFlow - v)
|
|
||||||
cs.inflow.add(streamAdd)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
|
||||||
@ -2469,17 +2559,15 @@ func (b transportResponseBody) Close() error {
|
|||||||
if unread > 0 {
|
if unread > 0 {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
// Return connection-level flow control.
|
// Return connection-level flow control.
|
||||||
if unread > 0 {
|
connAdd := cc.inflow.add(unread)
|
||||||
cc.inflow.add(int32(unread))
|
|
||||||
}
|
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
|
||||||
// TODO(dneil): Acquiring this mutex can block indefinitely.
|
// TODO(dneil): Acquiring this mutex can block indefinitely.
|
||||||
// Move flow control return to a goroutine?
|
// Move flow control return to a goroutine?
|
||||||
cc.wmu.Lock()
|
cc.wmu.Lock()
|
||||||
// Return connection-level flow control.
|
// Return connection-level flow control.
|
||||||
if unread > 0 {
|
if connAdd > 0 {
|
||||||
cc.fr.WriteWindowUpdate(0, uint32(unread))
|
cc.fr.WriteWindowUpdate(0, uint32(connAdd))
|
||||||
}
|
}
|
||||||
cc.bw.Flush()
|
cc.bw.Flush()
|
||||||
cc.wmu.Unlock()
|
cc.wmu.Unlock()
|
||||||
@ -2522,13 +2610,18 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
|||||||
// But at least return their flow control:
|
// But at least return their flow control:
|
||||||
if f.Length > 0 {
|
if f.Length > 0 {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
cc.inflow.add(int32(f.Length))
|
ok := cc.inflow.take(f.Length)
|
||||||
|
connAdd := cc.inflow.add(int(f.Length))
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
if !ok {
|
||||||
cc.wmu.Lock()
|
return ConnectionError(ErrCodeFlowControl)
|
||||||
cc.fr.WriteWindowUpdate(0, uint32(f.Length))
|
}
|
||||||
cc.bw.Flush()
|
if connAdd > 0 {
|
||||||
cc.wmu.Unlock()
|
cc.wmu.Lock()
|
||||||
|
cc.fr.WriteWindowUpdate(0, uint32(connAdd))
|
||||||
|
cc.bw.Flush()
|
||||||
|
cc.wmu.Unlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -2559,9 +2652,7 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
|||||||
}
|
}
|
||||||
// Check connection-level flow control.
|
// Check connection-level flow control.
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
if cs.inflow.available() >= int32(f.Length) {
|
if !takeInflows(&cc.inflow, &cs.inflow, f.Length) {
|
||||||
cs.inflow.take(int32(f.Length))
|
|
||||||
} else {
|
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
return ConnectionError(ErrCodeFlowControl)
|
return ConnectionError(ErrCodeFlowControl)
|
||||||
}
|
}
|
||||||
@ -2583,19 +2674,20 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if refund > 0 {
|
sendConn := cc.inflow.add(refund)
|
||||||
cc.inflow.add(int32(refund))
|
var sendStream int32
|
||||||
if !didReset {
|
if !didReset {
|
||||||
cs.inflow.add(int32(refund))
|
sendStream = cs.inflow.add(refund)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
|
||||||
if refund > 0 {
|
if sendConn > 0 || sendStream > 0 {
|
||||||
cc.wmu.Lock()
|
cc.wmu.Lock()
|
||||||
cc.fr.WriteWindowUpdate(0, uint32(refund))
|
if sendConn > 0 {
|
||||||
if !didReset {
|
cc.fr.WriteWindowUpdate(0, uint32(sendConn))
|
||||||
cc.fr.WriteWindowUpdate(cs.ID, uint32(refund))
|
}
|
||||||
|
if sendStream > 0 {
|
||||||
|
cc.fr.WriteWindowUpdate(cs.ID, uint32(sendStream))
|
||||||
}
|
}
|
||||||
cc.bw.Flush()
|
cc.bw.Flush()
|
||||||
cc.wmu.Unlock()
|
cc.wmu.Unlock()
|
||||||
@ -2663,7 +2755,6 @@ func (rl *clientConnReadLoop) processGoAway(f *GoAwayFrame) error {
|
|||||||
if fn := cc.t.CountError; fn != nil {
|
if fn := cc.t.CountError; fn != nil {
|
||||||
fn("recv_goaway_" + f.ErrCode.stringToken())
|
fn("recv_goaway_" + f.ErrCode.stringToken())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
cc.setGoAway(f)
|
cc.setGoAway(f)
|
||||||
return nil
|
return nil
|
||||||
@ -2728,8 +2819,10 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
|
|||||||
cc.cond.Broadcast()
|
cc.cond.Broadcast()
|
||||||
|
|
||||||
cc.initialWindowSize = s.Val
|
cc.initialWindowSize = s.Val
|
||||||
|
case SettingHeaderTableSize:
|
||||||
|
cc.henc.SetMaxDynamicTableSize(s.Val)
|
||||||
|
cc.peerMaxHeaderTableSize = s.Val
|
||||||
default:
|
default:
|
||||||
// TODO(bradfitz): handle more settings? SETTINGS_HEADER_TABLE_SIZE probably.
|
|
||||||
cc.vlogf("Unhandled Setting: %v", s)
|
cc.vlogf("Unhandled Setting: %v", s)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -2953,7 +3046,11 @@ func (gz *gzipReader) Read(p []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gz *gzipReader) Close() error {
|
func (gz *gzipReader) Close() error {
|
||||||
return gz.body.Close()
|
if err := gz.body.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gz.zerr = fs.ErrClosed
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type errorReader struct{ err error }
|
type errorReader struct{ err error }
|
||||||
@ -3017,7 +3114,7 @@ func traceGotConn(req *http.Request, cc *ClientConn, reused bool) {
|
|||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
ci.WasIdle = len(cc.streams) == 0 && reused
|
ci.WasIdle = len(cc.streams) == 0 && reused
|
||||||
if ci.WasIdle && !cc.lastActive.IsZero() {
|
if ci.WasIdle && !cc.lastActive.IsZero() {
|
||||||
ci.IdleTime = time.Now().Sub(cc.lastActive)
|
ci.IdleTime = time.Since(cc.lastActive)
|
||||||
}
|
}
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/sys/AUTHORS
generated
vendored
3
vendor/golang.org/x/sys/AUTHORS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# This source code refers to The Go Authors for copyright purposes.
|
|
||||||
# The master list of authors is in the main Go distribution,
|
|
||||||
# visible at http://tip.golang.org/AUTHORS.
|
|
3
vendor/golang.org/x/sys/CONTRIBUTORS
generated
vendored
3
vendor/golang.org/x/sys/CONTRIBUTORS
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
# This source code was written by the Go contributors.
|
|
||||||
# The master list of contributors is in the main Go distribution,
|
|
||||||
# visible at http://tip.golang.org/CONTRIBUTORS.
|
|
30
vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
generated
vendored
30
vendor/golang.org/x/sys/internal/unsafeheader/unsafeheader.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
// Copyright 2020 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 unsafeheader contains header declarations for the Go runtime's
|
|
||||||
// slice and string implementations.
|
|
||||||
//
|
|
||||||
// This package allows x/sys to use types equivalent to
|
|
||||||
// reflect.SliceHeader and reflect.StringHeader without introducing
|
|
||||||
// a dependency on the (relatively heavy) "reflect" package.
|
|
||||||
package unsafeheader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Slice is the runtime representation of a slice.
|
|
||||||
// It cannot be used safely or portably and its representation may change in a later release.
|
|
||||||
type Slice struct {
|
|
||||||
Data unsafe.Pointer
|
|
||||||
Len int
|
|
||||||
Cap int
|
|
||||||
}
|
|
||||||
|
|
||||||
// String is the runtime representation of a string.
|
|
||||||
// It cannot be used safely or portably and its representation may change in a later release.
|
|
||||||
type String struct {
|
|
||||||
Data unsafe.Pointer
|
|
||||||
Len int
|
|
||||||
}
|
|
31
vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s
generated
vendored
Normal file
31
vendor/golang.org/x/sys/unix/asm_bsd_ppc64.s
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2022 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 (darwin || freebsd || netbsd || openbsd) && gc
|
||||||
|
// +build darwin freebsd netbsd openbsd
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// System call support for ppc64, BSD
|
||||||
|
//
|
||||||
|
|
||||||
|
// Just jump to package syscall's implementation for all these functions.
|
||||||
|
// The runtime may know about them.
|
||||||
|
|
||||||
|
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·Syscall(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·Syscall6(SB)
|
||||||
|
|
||||||
|
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||||
|
JMP syscall·Syscall9(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||||
|
JMP syscall·RawSyscall(SB)
|
||||||
|
|
||||||
|
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||||
|
JMP syscall·RawSyscall6(SB)
|
4
vendor/golang.org/x/sys/unix/dirent.go
generated
vendored
4
vendor/golang.org/x/sys/unix/dirent.go
generated
vendored
@ -2,8 +2,8 @@
|
|||||||
// 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
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
4
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
4
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
@ -2,8 +2,8 @@
|
|||||||
// 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 gccgo && !aix
|
//go:build gccgo && !aix && !hurd
|
||||||
// +build gccgo,!aix
|
// +build gccgo,!aix,!hurd
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
4
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
4
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
@ -2,8 +2,8 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
// +build gccgo
|
// +build gccgo,!hurd
|
||||||
// +build !aix
|
// +build !aix,!hurd
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
4
vendor/golang.org/x/sys/unix/ioctl.go
generated
vendored
4
vendor/golang.org/x/sys/unix/ioctl.go
generated
vendored
@ -2,8 +2,8 @@
|
|||||||
// 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
|
//go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
20
vendor/golang.org/x/sys/unix/ioctl_linux.go
generated
vendored
20
vendor/golang.org/x/sys/unix/ioctl_linux.go
generated
vendored
@ -4,9 +4,7 @@
|
|||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import (
|
import "unsafe"
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IoctlRetInt performs an ioctl operation specified by req on a device
|
// IoctlRetInt performs an ioctl operation specified by req on a device
|
||||||
// associated with opened file descriptor fd, and returns a non-negative
|
// associated with opened file descriptor fd, and returns a non-negative
|
||||||
@ -217,3 +215,19 @@ func IoctlKCMAttach(fd int, info KCMAttach) error {
|
|||||||
func IoctlKCMUnattach(fd int, info KCMUnattach) error {
|
func IoctlKCMUnattach(fd int, info KCMUnattach) error {
|
||||||
return ioctlPtr(fd, SIOCKCMUNATTACH, unsafe.Pointer(&info))
|
return ioctlPtr(fd, SIOCKCMUNATTACH, unsafe.Pointer(&info))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IoctlLoopGetStatus64 gets the status of the loop device associated with the
|
||||||
|
// file descriptor fd using the LOOP_GET_STATUS64 operation.
|
||||||
|
func IoctlLoopGetStatus64(fd int) (*LoopInfo64, error) {
|
||||||
|
var value LoopInfo64
|
||||||
|
if err := ioctlPtr(fd, LOOP_GET_STATUS64, unsafe.Pointer(&value)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlLoopSetStatus64 sets the status of the loop device associated with the
|
||||||
|
// file descriptor fd using the LOOP_SET_STATUS64 operation.
|
||||||
|
func IoctlLoopSetStatus64(fd int, value *LoopInfo64) error {
|
||||||
|
return ioctlPtr(fd, LOOP_SET_STATUS64, unsafe.Pointer(value))
|
||||||
|
}
|
||||||
|
49
vendor/golang.org/x/sys/unix/mkall.sh
generated
vendored
49
vendor/golang.org/x/sys/unix/mkall.sh
generated
vendored
@ -73,12 +73,12 @@ aix_ppc64)
|
|||||||
darwin_amd64)
|
darwin_amd64)
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
mkasm="go run mkasm_darwin.go"
|
mkasm="go run mkasm.go"
|
||||||
;;
|
;;
|
||||||
darwin_arm64)
|
darwin_arm64)
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
mkasm="go run mkasm_darwin.go"
|
mkasm="go run mkasm.go"
|
||||||
;;
|
;;
|
||||||
dragonfly_amd64)
|
dragonfly_amd64)
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
@ -142,42 +142,60 @@ netbsd_arm64)
|
|||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
openbsd_386)
|
openbsd_386)
|
||||||
|
mkasm="go run mkasm.go"
|
||||||
mkerrors="$mkerrors -m32"
|
mkerrors="$mkerrors -m32"
|
||||||
mksyscall="go run mksyscall.go -l32 -openbsd"
|
mksyscall="go run mksyscall.go -l32 -openbsd -libc"
|
||||||
mksysctl="go run mksysctl_openbsd.go"
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
openbsd_amd64)
|
openbsd_amd64)
|
||||||
|
mkasm="go run mkasm.go"
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksyscall="go run mksyscall.go -openbsd"
|
mksyscall="go run mksyscall.go -openbsd -libc"
|
||||||
mksysctl="go run mksysctl_openbsd.go"
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||||
;;
|
;;
|
||||||
openbsd_arm)
|
openbsd_arm)
|
||||||
|
mkasm="go run mkasm.go"
|
||||||
mkerrors="$mkerrors"
|
mkerrors="$mkerrors"
|
||||||
mksyscall="go run mksyscall.go -l32 -openbsd -arm"
|
mksyscall="go run mksyscall.go -l32 -openbsd -arm -libc"
|
||||||
mksysctl="go run mksysctl_openbsd.go"
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
|
||||||
# Let the type of C char be signed for making the bare syscall
|
# Let the type of C char be signed for making the bare syscall
|
||||||
# API consistent across platforms.
|
# API consistent across platforms.
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
;;
|
;;
|
||||||
openbsd_arm64)
|
openbsd_arm64)
|
||||||
|
mkasm="go run mkasm.go"
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksyscall="go run mksyscall.go -openbsd"
|
mksyscall="go run mksyscall.go -openbsd -libc"
|
||||||
mksysctl="go run mksysctl_openbsd.go"
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
|
||||||
# Let the type of C char be signed for making the bare syscall
|
# Let the type of C char be signed for making the bare syscall
|
||||||
# API consistent across platforms.
|
# API consistent across platforms.
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
;;
|
;;
|
||||||
openbsd_mips64)
|
openbsd_mips64)
|
||||||
|
mkasm="go run mkasm.go"
|
||||||
mkerrors="$mkerrors -m64"
|
mkerrors="$mkerrors -m64"
|
||||||
mksyscall="go run mksyscall.go -openbsd"
|
mksyscall="go run mksyscall.go -openbsd -libc"
|
||||||
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
|
# Let the type of C char be signed for making the bare syscall
|
||||||
|
# API consistent across platforms.
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
;;
|
||||||
|
openbsd_ppc64)
|
||||||
|
mkasm="go run mkasm.go"
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksyscall="go run mksyscall.go -openbsd -libc"
|
||||||
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
|
# Let the type of C char be signed for making the bare syscall
|
||||||
|
# API consistent across platforms.
|
||||||
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
|
;;
|
||||||
|
openbsd_riscv64)
|
||||||
|
mkasm="go run mkasm.go"
|
||||||
|
mkerrors="$mkerrors -m64"
|
||||||
|
mksyscall="go run mksyscall.go -openbsd -libc"
|
||||||
mksysctl="go run mksysctl_openbsd.go"
|
mksysctl="go run mksysctl_openbsd.go"
|
||||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
|
||||||
# Let the type of C char be signed for making the bare syscall
|
# Let the type of C char be signed for making the bare syscall
|
||||||
# API consistent across platforms.
|
# API consistent across platforms.
|
||||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||||
@ -214,11 +232,6 @@ esac
|
|||||||
if [ "$GOOSARCH" == "aix_ppc64" ]; then
|
if [ "$GOOSARCH" == "aix_ppc64" ]; then
|
||||||
# aix/ppc64 script generates files instead of writing to stdin.
|
# aix/ppc64 script generates files instead of writing to stdin.
|
||||||
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
|
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
|
||||||
elif [ "$GOOS" == "darwin" ]; then
|
|
||||||
# 1.12 and later, syscalls via libSystem
|
|
||||||
echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
|
|
||||||
# 1.13 and later, syscalls via libSystem (including syscallPtr)
|
|
||||||
echo "$mksyscall -tags $GOOS,$GOARCH,go1.13 syscall_darwin.1_13.go |gofmt >zsyscall_$GOOSARCH.1_13.go";
|
|
||||||
elif [ "$GOOS" == "illumos" ]; then
|
elif [ "$GOOS" == "illumos" ]; then
|
||||||
# illumos code generation requires a --illumos switch
|
# illumos code generation requires a --illumos switch
|
||||||
echo "$mksyscall -illumos -tags illumos,$GOARCH syscall_illumos.go |gofmt > zsyscall_illumos_$GOARCH.go";
|
echo "$mksyscall -illumos -tags illumos,$GOARCH syscall_illumos.go |gofmt > zsyscall_illumos_$GOARCH.go";
|
||||||
@ -232,5 +245,5 @@ esac
|
|||||||
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
|
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
|
||||||
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
|
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
|
||||||
if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go"; fi
|
if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go"; fi
|
||||||
if [ -n "$mkasm" ]; then echo "$mkasm $GOARCH"; fi
|
if [ -n "$mkasm" ]; then echo "$mkasm $GOOS $GOARCH"; fi
|
||||||
) | $run
|
) | $run
|
||||||
|
8
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
8
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
@ -297,6 +297,10 @@ struct ltchars {
|
|||||||
#define SOL_NETLINK 270
|
#define SOL_NETLINK 270
|
||||||
#endif
|
#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
|
||||||
@ -638,7 +642,7 @@ errors=$(
|
|||||||
signals=$(
|
signals=$(
|
||||||
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
|
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
|
||||||
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
|
grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
|
||||||
sort
|
sort
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -648,7 +652,7 @@ echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
|
|||||||
sort >_error.grep
|
sort >_error.grep
|
||||||
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
||||||
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
|
grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
|
||||||
sort >_signal.grep
|
sort >_signal.grep
|
||||||
|
|
||||||
echo '// mkerrors.sh' "$@"
|
echo '// mkerrors.sh' "$@"
|
||||||
|
14
vendor/golang.org/x/sys/unix/sockcmsg_unix.go
generated
vendored
14
vendor/golang.org/x/sys/unix/sockcmsg_unix.go
generated
vendored
@ -52,6 +52,20 @@ func ParseSocketControlMessage(b []byte) ([]SocketControlMessage, error) {
|
|||||||
return msgs, nil
|
return msgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseOneSocketControlMessage parses a single socket control message from b, returning the message header,
|
||||||
|
// message data (a slice of b), and the remainder of b after that single message.
|
||||||
|
// When there are no remaining messages, len(remainder) == 0.
|
||||||
|
func ParseOneSocketControlMessage(b []byte) (hdr Cmsghdr, data []byte, remainder []byte, err error) {
|
||||||
|
h, dbuf, err := socketControlMessageHeaderAndData(b)
|
||||||
|
if err != nil {
|
||||||
|
return Cmsghdr{}, nil, nil, err
|
||||||
|
}
|
||||||
|
if i := cmsgAlignOf(int(h.Len)); i < len(b) {
|
||||||
|
remainder = b[i:]
|
||||||
|
}
|
||||||
|
return *h, dbuf, remainder, nil
|
||||||
|
}
|
||||||
|
|
||||||
func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) {
|
func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) {
|
||||||
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
|
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||||
if h.Len < SizeofCmsghdr || uint64(h.Len) > uint64(len(b)) {
|
if h.Len < SizeofCmsghdr || uint64(h.Len) > uint64(len(b)) {
|
||||||
|
27
vendor/golang.org/x/sys/unix/str.go
generated
vendored
27
vendor/golang.org/x/sys/unix/str.go
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
// Copyright 2009 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 aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
|
|
||||||
if val < 0 {
|
|
||||||
return "-" + uitoa(uint(-val))
|
|
||||||
}
|
|
||||||
return uitoa(uint(val))
|
|
||||||
}
|
|
||||||
|
|
||||||
func uitoa(val uint) string {
|
|
||||||
var buf [32]byte // big enough for int64
|
|
||||||
i := len(buf) - 1
|
|
||||||
for val >= 10 {
|
|
||||||
buf[i] = byte(val%10 + '0')
|
|
||||||
i--
|
|
||||||
val /= 10
|
|
||||||
}
|
|
||||||
buf[i] = byte(val + '0')
|
|
||||||
return string(buf[i:])
|
|
||||||
}
|
|
10
vendor/golang.org/x/sys/unix/syscall.go
generated
vendored
10
vendor/golang.org/x/sys/unix/syscall.go
generated
vendored
@ -29,8 +29,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sys/internal/unsafeheader"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
// ByteSliceFromString returns a NUL-terminated slice of bytes
|
||||||
@ -82,13 +80,7 @@ func BytePtrToString(p *byte) string {
|
|||||||
ptr = unsafe.Pointer(uintptr(ptr) + 1)
|
ptr = unsafe.Pointer(uintptr(ptr) + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var s []byte
|
return string(unsafe.Slice(p, n))
|
||||||
h := (*unsafeheader.Slice)(unsafe.Pointer(&s))
|
|
||||||
h.Data = unsafe.Pointer(p)
|
|
||||||
h.Len = n
|
|
||||||
h.Cap = n
|
|
||||||
|
|
||||||
return string(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
// Single-word zero for use when we need a valid pointer to 0 bytes.
|
||||||
|
57
vendor/golang.org/x/sys/unix/syscall_aix.go
generated
vendored
57
vendor/golang.org/x/sys/unix/syscall_aix.go
generated
vendored
@ -218,13 +218,62 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
|
func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
|
||||||
// Recvmsg not implemented on AIX
|
var msg Msghdr
|
||||||
return -1, -1, -1, ENOSYS
|
msg.Name = (*byte)(unsafe.Pointer(rsa))
|
||||||
|
msg.Namelen = uint32(SizeofSockaddrAny)
|
||||||
|
var dummy byte
|
||||||
|
if len(oob) > 0 {
|
||||||
|
// receive at least one normal byte
|
||||||
|
if emptyIovecs(iov) {
|
||||||
|
var iova [1]Iovec
|
||||||
|
iova[0].Base = &dummy
|
||||||
|
iova[0].SetLen(1)
|
||||||
|
iov = iova[:]
|
||||||
|
}
|
||||||
|
msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
|
||||||
|
msg.SetControllen(len(oob))
|
||||||
|
}
|
||||||
|
if len(iov) > 0 {
|
||||||
|
msg.Iov = &iov[0]
|
||||||
|
msg.SetIovlen(len(iov))
|
||||||
|
}
|
||||||
|
if n, err = recvmsg(fd, &msg, flags); n == -1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
oobn = int(msg.Controllen)
|
||||||
|
recvflags = int(msg.Flags)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
|
func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
|
||||||
// SendmsgN not implemented on AIX
|
var msg Msghdr
|
||||||
return -1, ENOSYS
|
msg.Name = (*byte)(unsafe.Pointer(ptr))
|
||||||
|
msg.Namelen = uint32(salen)
|
||||||
|
var dummy byte
|
||||||
|
var empty bool
|
||||||
|
if len(oob) > 0 {
|
||||||
|
// send at least one normal byte
|
||||||
|
empty = emptyIovecs(iov)
|
||||||
|
if empty {
|
||||||
|
var iova [1]Iovec
|
||||||
|
iova[0].Base = &dummy
|
||||||
|
iova[0].SetLen(1)
|
||||||
|
iov = iova[:]
|
||||||
|
}
|
||||||
|
msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
|
||||||
|
msg.SetControllen(len(oob))
|
||||||
|
}
|
||||||
|
if len(iov) > 0 {
|
||||||
|
msg.Iov = &iov[0]
|
||||||
|
msg.SetIovlen(len(iov))
|
||||||
|
}
|
||||||
|
if n, err = sendmsg(fd, &msg, flags); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if len(oob) > 0 && empty {
|
||||||
|
n = 0
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||||
|
2
vendor/golang.org/x/sys/unix/syscall_bsd.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_bsd.go
generated
vendored
@ -363,7 +363,7 @@ func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Sockle
|
|||||||
var empty bool
|
var empty bool
|
||||||
if len(oob) > 0 {
|
if len(oob) > 0 {
|
||||||
// send at least one normal byte
|
// send at least one normal byte
|
||||||
empty := emptyIovecs(iov)
|
empty = emptyIovecs(iov)
|
||||||
if empty {
|
if empty {
|
||||||
var iova [1]Iovec
|
var iova [1]Iovec
|
||||||
iova[0].Base = &dummy
|
iova[0].Base = &dummy
|
||||||
|
32
vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go
generated
vendored
32
vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go
generated
vendored
@ -1,32 +0,0 @@
|
|||||||
// Copyright 2019 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 darwin && go1.12 && !go1.13
|
|
||||||
// +build darwin,go1.12,!go1.13
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const _SYS_GETDIRENTRIES64 = 344
|
|
||||||
|
|
||||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
|
||||||
// To implement this using libSystem we'd need syscall_syscallPtr for
|
|
||||||
// fdopendir. However, syscallPtr was only added in Go 1.13, so we fall
|
|
||||||
// back to raw syscalls for this func on Go 1.12.
|
|
||||||
var p unsafe.Pointer
|
|
||||||
if len(buf) > 0 {
|
|
||||||
p = unsafe.Pointer(&buf[0])
|
|
||||||
} else {
|
|
||||||
p = unsafe.Pointer(&_zero)
|
|
||||||
}
|
|
||||||
r0, _, e1 := Syscall6(_SYS_GETDIRENTRIES64, uintptr(fd), uintptr(p), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
|
|
||||||
n = int(r0)
|
|
||||||
if e1 != 0 {
|
|
||||||
return n, errnoErr(e1)
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
108
vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go
generated
vendored
108
vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go
generated
vendored
@ -1,108 +0,0 @@
|
|||||||
// Copyright 2019 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 darwin && go1.13
|
|
||||||
// +build darwin,go1.13
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/sys/internal/unsafeheader"
|
|
||||||
)
|
|
||||||
|
|
||||||
//sys closedir(dir uintptr) (err error)
|
|
||||||
//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
|
|
||||||
|
|
||||||
func fdopendir(fd int) (dir uintptr, err error) {
|
|
||||||
r0, _, e1 := syscall_syscallPtr(libc_fdopendir_trampoline_addr, uintptr(fd), 0, 0)
|
|
||||||
dir = uintptr(r0)
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var libc_fdopendir_trampoline_addr uintptr
|
|
||||||
|
|
||||||
//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"
|
|
||||||
|
|
||||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
|
||||||
// Simulate Getdirentries using fdopendir/readdir_r/closedir.
|
|
||||||
// We store the number of entries to skip in the seek
|
|
||||||
// offset of fd. See issue #31368.
|
|
||||||
// It's not the full required semantics, but should handle the case
|
|
||||||
// of calling Getdirentries or ReadDirent repeatedly.
|
|
||||||
// It won't handle assigning the results of lseek to *basep, or handle
|
|
||||||
// the directory being edited underfoot.
|
|
||||||
skip, err := Seek(fd, 0, 1 /* SEEK_CUR */)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to duplicate the incoming file descriptor
|
|
||||||
// because the caller expects to retain control of it, but
|
|
||||||
// fdopendir expects to take control of its argument.
|
|
||||||
// Just Dup'ing the file descriptor is not enough, as the
|
|
||||||
// result shares underlying state. Use Openat to make a really
|
|
||||||
// new file descriptor referring to the same directory.
|
|
||||||
fd2, err := Openat(fd, ".", O_RDONLY, 0)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
d, err := fdopendir(fd2)
|
|
||||||
if err != nil {
|
|
||||||
Close(fd2)
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer closedir(d)
|
|
||||||
|
|
||||||
var cnt int64
|
|
||||||
for {
|
|
||||||
var entry Dirent
|
|
||||||
var entryp *Dirent
|
|
||||||
e := readdir_r(d, &entry, &entryp)
|
|
||||||
if e != 0 {
|
|
||||||
return n, errnoErr(e)
|
|
||||||
}
|
|
||||||
if entryp == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if skip > 0 {
|
|
||||||
skip--
|
|
||||||
cnt++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
reclen := int(entry.Reclen)
|
|
||||||
if reclen > len(buf) {
|
|
||||||
// Not enough room. Return for now.
|
|
||||||
// The counter will let us know where we should start up again.
|
|
||||||
// Note: this strategy for suspending in the middle and
|
|
||||||
// restarting is O(n^2) in the length of the directory. Oh well.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy entry into return buffer.
|
|
||||||
var s []byte
|
|
||||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&s))
|
|
||||||
hdr.Data = unsafe.Pointer(&entry)
|
|
||||||
hdr.Cap = reclen
|
|
||||||
hdr.Len = reclen
|
|
||||||
copy(buf, s)
|
|
||||||
|
|
||||||
buf = buf[reclen:]
|
|
||||||
n += reclen
|
|
||||||
cnt++
|
|
||||||
}
|
|
||||||
// Set the seek offset of the input fd to record
|
|
||||||
// how many files we've already returned.
|
|
||||||
_, err = Seek(fd, cnt, 0 /* SEEK_SET */)
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return n, nil
|
|
||||||
}
|
|
90
vendor/golang.org/x/sys/unix/syscall_darwin.go
generated
vendored
90
vendor/golang.org/x/sys/unix/syscall_darwin.go
generated
vendored
@ -19,6 +19,96 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//sys closedir(dir uintptr) (err error)
|
||||||
|
//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
|
||||||
|
|
||||||
|
func fdopendir(fd int) (dir uintptr, err error) {
|
||||||
|
r0, _, e1 := syscall_syscallPtr(libc_fdopendir_trampoline_addr, uintptr(fd), 0, 0)
|
||||||
|
dir = uintptr(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var libc_fdopendir_trampoline_addr uintptr
|
||||||
|
|
||||||
|
//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"
|
||||||
|
|
||||||
|
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
||||||
|
// Simulate Getdirentries using fdopendir/readdir_r/closedir.
|
||||||
|
// We store the number of entries to skip in the seek
|
||||||
|
// offset of fd. See issue #31368.
|
||||||
|
// It's not the full required semantics, but should handle the case
|
||||||
|
// of calling Getdirentries or ReadDirent repeatedly.
|
||||||
|
// It won't handle assigning the results of lseek to *basep, or handle
|
||||||
|
// the directory being edited underfoot.
|
||||||
|
skip, err := Seek(fd, 0, 1 /* SEEK_CUR */)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to duplicate the incoming file descriptor
|
||||||
|
// because the caller expects to retain control of it, but
|
||||||
|
// fdopendir expects to take control of its argument.
|
||||||
|
// Just Dup'ing the file descriptor is not enough, as the
|
||||||
|
// result shares underlying state. Use Openat to make a really
|
||||||
|
// new file descriptor referring to the same directory.
|
||||||
|
fd2, err := Openat(fd, ".", O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
d, err := fdopendir(fd2)
|
||||||
|
if err != nil {
|
||||||
|
Close(fd2)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer closedir(d)
|
||||||
|
|
||||||
|
var cnt int64
|
||||||
|
for {
|
||||||
|
var entry Dirent
|
||||||
|
var entryp *Dirent
|
||||||
|
e := readdir_r(d, &entry, &entryp)
|
||||||
|
if e != 0 {
|
||||||
|
return n, errnoErr(e)
|
||||||
|
}
|
||||||
|
if entryp == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if skip > 0 {
|
||||||
|
skip--
|
||||||
|
cnt++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
reclen := int(entry.Reclen)
|
||||||
|
if reclen > len(buf) {
|
||||||
|
// Not enough room. Return for now.
|
||||||
|
// The counter will let us know where we should start up again.
|
||||||
|
// Note: this strategy for suspending in the middle and
|
||||||
|
// restarting is O(n^2) in the length of the directory. Oh well.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy entry into return buffer.
|
||||||
|
s := unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen)
|
||||||
|
copy(buf, s)
|
||||||
|
|
||||||
|
buf = buf[reclen:]
|
||||||
|
n += reclen
|
||||||
|
cnt++
|
||||||
|
}
|
||||||
|
// Set the seek offset of the input fd to record
|
||||||
|
// how many files we've already returned.
|
||||||
|
_, err = Seek(fd, cnt, 0 /* SEEK_SET */)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets.
|
// SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets.
|
||||||
type SockaddrDatalink struct {
|
type SockaddrDatalink struct {
|
||||||
Len uint8
|
Len uint8
|
||||||
|
1
vendor/golang.org/x/sys/unix/syscall_dragonfly.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_dragonfly.go
generated
vendored
@ -255,6 +255,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
|||||||
//sys Chmod(path string, mode uint32) (err error)
|
//sys Chmod(path string, mode uint32) (err error)
|
||||||
//sys Chown(path string, uid int, gid int) (err error)
|
//sys Chown(path string, uid int, gid int) (err error)
|
||||||
//sys Chroot(path string) (err error)
|
//sys Chroot(path string) (err error)
|
||||||
|
//sys ClockGettime(clockid int32, time *Timespec) (err error)
|
||||||
//sys Close(fd int) (err error)
|
//sys Close(fd int) (err error)
|
||||||
//sys Dup(fd int) (nfd int, err error)
|
//sys Dup(fd int) (nfd int, err error)
|
||||||
//sys Dup2(from int, to int) (err error)
|
//sys Dup2(from int, to int) (err error)
|
||||||
|
1
vendor/golang.org/x/sys/unix/syscall_freebsd.go
generated
vendored
1
vendor/golang.org/x/sys/unix/syscall_freebsd.go
generated
vendored
@ -319,6 +319,7 @@ func PtraceSingleStep(pid int) (err error) {
|
|||||||
//sys Chmod(path string, mode uint32) (err error)
|
//sys Chmod(path string, mode uint32) (err error)
|
||||||
//sys Chown(path string, uid int, gid int) (err error)
|
//sys Chown(path string, uid int, gid int) (err error)
|
||||||
//sys Chroot(path string) (err error)
|
//sys Chroot(path string) (err error)
|
||||||
|
//sys ClockGettime(clockid int32, time *Timespec) (err error)
|
||||||
//sys Close(fd int) (err error)
|
//sys Close(fd int) (err error)
|
||||||
//sys Dup(fd int) (nfd int, err error)
|
//sys Dup(fd int) (nfd int, err error)
|
||||||
//sys Dup2(from int, to int) (err error)
|
//sys Dup2(from int, to int) (err error)
|
||||||
|
2
vendor/golang.org/x/sys/unix/syscall_freebsd_386.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_freebsd_386.go
generated
vendored
@ -61,7 +61,7 @@ func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)}
|
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint32(countin)}
|
||||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||||
return int(ioDesc.Len), err
|
return int(ioDesc.Len), err
|
||||||
}
|
}
|
||||||
|
2
vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go
generated
vendored
@ -61,7 +61,7 @@ func PtraceGetFsBase(pid int, fsbase *int64) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint64(countin)}
|
||||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||||
return int(ioDesc.Len), err
|
return int(ioDesc.Len), err
|
||||||
}
|
}
|
||||||
|
2
vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go
generated
vendored
2
vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go
generated
vendored
@ -57,7 +57,7 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
|||||||
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||||
|
|
||||||
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
|
||||||
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)}
|
ioDesc := PtraceIoDesc{Op: int32(req), Offs: uintptr(unsafe.Pointer(addr)), Addr: uintptr(unsafe.Pointer(&out[0])), Len: uint32(countin)}
|
||||||
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
err = ptrace(PT_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
|
||||||
return int(ioDesc.Len), err
|
return int(ioDesc.Len), err
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user