mirror of https://github.com/docker/buildx.git
vendor: google.golang.org/appengine v1.6.8
full diff: https://github.com/golang/appengine/compare/v1.6.7...v1.6.8 Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
6e433da23f
commit
d296d5d46a
2
go.mod
2
go.mod
|
@ -166,7 +166,7 @@ require (
|
||||||
golang.org/x/oauth2 v0.11.0 // indirect
|
golang.org/x/oauth2 v0.11.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.17.0 // indirect
|
golang.org/x/tools v0.17.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.8 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
|
||||||
|
|
21
go.sum
21
go.sum
|
@ -203,6 +203,7 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 h1:jc2UWq7CbdszqeH6qu1ougXMIUBfSy8Pbh/anURYbGI=
|
github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 h1:jc2UWq7CbdszqeH6qu1ougXMIUBfSy8Pbh/anURYbGI=
|
||||||
|
@ -460,6 +461,7 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/zclconf/go-cty v1.4.0/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ=
|
github.com/zclconf/go-cty v1.4.0/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ=
|
||||||
github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8=
|
github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8=
|
||||||
github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
||||||
|
@ -507,22 +509,25 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
|
||||||
golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
|
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
|
||||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
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/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
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=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
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-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
|
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
|
||||||
|
@ -533,6 +538,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -544,19 +550,26 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
|
@ -565,6 +578,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||||
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-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||||
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=
|
||||||
|
@ -572,8 +586,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
||||||
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||||
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA=
|
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA=
|
||||||
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI=
|
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k=
|
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k=
|
||||||
|
@ -584,6 +598,7 @@ google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEd
|
||||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
// Copyright 2014 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 context defines the Context type, which carries deadlines,
|
|
||||||
// cancelation signals, and other request-scoped values across API boundaries
|
|
||||||
// and between processes.
|
|
||||||
// As of Go 1.7 this package is available in the standard library under the
|
|
||||||
// name context. https://golang.org/pkg/context.
|
|
||||||
//
|
|
||||||
// Incoming requests to a server should create a Context, and outgoing calls to
|
|
||||||
// servers should accept a Context. The chain of function calls between must
|
|
||||||
// propagate the Context, optionally replacing it with a modified copy created
|
|
||||||
// using WithDeadline, WithTimeout, WithCancel, or WithValue.
|
|
||||||
//
|
|
||||||
// Programs that use Contexts should follow these rules to keep interfaces
|
|
||||||
// consistent across packages and enable static analysis tools to check context
|
|
||||||
// propagation:
|
|
||||||
//
|
|
||||||
// Do not store Contexts inside a struct type; instead, pass a Context
|
|
||||||
// explicitly to each function that needs it. The Context should be the first
|
|
||||||
// parameter, typically named ctx:
|
|
||||||
//
|
|
||||||
// func DoSomething(ctx context.Context, arg Arg) error {
|
|
||||||
// // ... use ctx ...
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
|
|
||||||
// if you are unsure about which Context to use.
|
|
||||||
//
|
|
||||||
// Use context Values only for request-scoped data that transits processes and
|
|
||||||
// APIs, not for passing optional parameters to functions.
|
|
||||||
//
|
|
||||||
// The same Context may be passed to functions running in different goroutines;
|
|
||||||
// Contexts are safe for simultaneous use by multiple goroutines.
|
|
||||||
//
|
|
||||||
// See http://blog.golang.org/context for example code for a server that uses
|
|
||||||
// Contexts.
|
|
||||||
package context // import "golang.org/x/net/context"
|
|
||||||
|
|
||||||
// Background returns a non-nil, empty Context. It is never canceled, has no
|
|
||||||
// values, and has no deadline. It is typically used by the main function,
|
|
||||||
// initialization, and tests, and as the top-level Context for incoming
|
|
||||||
// requests.
|
|
||||||
func Background() Context {
|
|
||||||
return background
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO returns a non-nil, empty Context. Code should use context.TODO when
|
|
||||||
// it's unclear which Context to use or it is not yet available (because the
|
|
||||||
// surrounding function has not yet been extended to accept a Context
|
|
||||||
// parameter). TODO is recognized by static analysis tools that determine
|
|
||||||
// whether Contexts are propagated correctly in a program.
|
|
||||||
func TODO() Context {
|
|
||||||
return todo
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build go1.7
|
|
||||||
|
|
||||||
package context
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context" // standard library's context, as of Go 1.7
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
todo = context.TODO()
|
|
||||||
background = context.Background()
|
|
||||||
)
|
|
||||||
|
|
||||||
// Canceled is the error returned by Context.Err when the context is canceled.
|
|
||||||
var Canceled = context.Canceled
|
|
||||||
|
|
||||||
// DeadlineExceeded is the error returned by Context.Err when the context's
|
|
||||||
// deadline passes.
|
|
||||||
var DeadlineExceeded = context.DeadlineExceeded
|
|
||||||
|
|
||||||
// WithCancel returns a copy of parent with a new Done channel. The returned
|
|
||||||
// context's Done channel is closed when the returned cancel function is called
|
|
||||||
// or when the parent context's Done channel is closed, whichever happens first.
|
|
||||||
//
|
|
||||||
// Canceling this context releases resources associated with it, so code should
|
|
||||||
// call cancel as soon as the operations running in this Context complete.
|
|
||||||
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
|
||||||
ctx, f := context.WithCancel(parent)
|
|
||||||
return ctx, f
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDeadline returns a copy of the parent context with the deadline adjusted
|
|
||||||
// to be no later than d. If the parent's deadline is already earlier than d,
|
|
||||||
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
|
||||||
// context's Done channel is closed when the deadline expires, when the returned
|
|
||||||
// cancel function is called, or when the parent context's Done channel is
|
|
||||||
// closed, whichever happens first.
|
|
||||||
//
|
|
||||||
// Canceling this context releases resources associated with it, so code should
|
|
||||||
// call cancel as soon as the operations running in this Context complete.
|
|
||||||
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
|
|
||||||
ctx, f := context.WithDeadline(parent, deadline)
|
|
||||||
return ctx, f
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
|
|
||||||
//
|
|
||||||
// Canceling this context releases resources associated with it, so code should
|
|
||||||
// call cancel as soon as the operations running in this Context complete:
|
|
||||||
//
|
|
||||||
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
|
|
||||||
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
|
||||||
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
|
||||||
// return slowOperation(ctx)
|
|
||||||
// }
|
|
||||||
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
|
||||||
return WithDeadline(parent, time.Now().Add(timeout))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithValue returns a copy of parent in which the value associated with key is
|
|
||||||
// val.
|
|
||||||
//
|
|
||||||
// Use context Values only for request-scoped data that transits processes and
|
|
||||||
// APIs, not for passing optional parameters to functions.
|
|
||||||
func WithValue(parent Context, key interface{}, val interface{}) Context {
|
|
||||||
return context.WithValue(parent, key, val)
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build go1.9
|
|
||||||
|
|
||||||
package context
|
|
||||||
|
|
||||||
import "context" // standard library's context, as of Go 1.7
|
|
||||||
|
|
||||||
// A Context carries a deadline, a cancelation signal, and other values across
|
|
||||||
// API boundaries.
|
|
||||||
//
|
|
||||||
// Context's methods may be called by multiple goroutines simultaneously.
|
|
||||||
type Context = context.Context
|
|
||||||
|
|
||||||
// A CancelFunc tells an operation to abandon its work.
|
|
||||||
// A CancelFunc does not wait for the work to stop.
|
|
||||||
// After the first call, subsequent calls to a CancelFunc do nothing.
|
|
||||||
type CancelFunc = context.CancelFunc
|
|
|
@ -1,300 +0,0 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !go1.7
|
|
||||||
|
|
||||||
package context
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
|
|
||||||
// struct{}, since vars of this type must have distinct addresses.
|
|
||||||
type emptyCtx int
|
|
||||||
|
|
||||||
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*emptyCtx) Done() <-chan struct{} {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*emptyCtx) Err() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*emptyCtx) Value(key interface{}) interface{} {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *emptyCtx) String() string {
|
|
||||||
switch e {
|
|
||||||
case background:
|
|
||||||
return "context.Background"
|
|
||||||
case todo:
|
|
||||||
return "context.TODO"
|
|
||||||
}
|
|
||||||
return "unknown empty Context"
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
background = new(emptyCtx)
|
|
||||||
todo = new(emptyCtx)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Canceled is the error returned by Context.Err when the context is canceled.
|
|
||||||
var Canceled = errors.New("context canceled")
|
|
||||||
|
|
||||||
// DeadlineExceeded is the error returned by Context.Err when the context's
|
|
||||||
// deadline passes.
|
|
||||||
var DeadlineExceeded = errors.New("context deadline exceeded")
|
|
||||||
|
|
||||||
// WithCancel returns a copy of parent with a new Done channel. The returned
|
|
||||||
// context's Done channel is closed when the returned cancel function is called
|
|
||||||
// or when the parent context's Done channel is closed, whichever happens first.
|
|
||||||
//
|
|
||||||
// Canceling this context releases resources associated with it, so code should
|
|
||||||
// call cancel as soon as the operations running in this Context complete.
|
|
||||||
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
|
||||||
c := newCancelCtx(parent)
|
|
||||||
propagateCancel(parent, c)
|
|
||||||
return c, func() { c.cancel(true, Canceled) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// newCancelCtx returns an initialized cancelCtx.
|
|
||||||
func newCancelCtx(parent Context) *cancelCtx {
|
|
||||||
return &cancelCtx{
|
|
||||||
Context: parent,
|
|
||||||
done: make(chan struct{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// propagateCancel arranges for child to be canceled when parent is.
|
|
||||||
func propagateCancel(parent Context, child canceler) {
|
|
||||||
if parent.Done() == nil {
|
|
||||||
return // parent is never canceled
|
|
||||||
}
|
|
||||||
if p, ok := parentCancelCtx(parent); ok {
|
|
||||||
p.mu.Lock()
|
|
||||||
if p.err != nil {
|
|
||||||
// parent has already been canceled
|
|
||||||
child.cancel(false, p.err)
|
|
||||||
} else {
|
|
||||||
if p.children == nil {
|
|
||||||
p.children = make(map[canceler]bool)
|
|
||||||
}
|
|
||||||
p.children[child] = true
|
|
||||||
}
|
|
||||||
p.mu.Unlock()
|
|
||||||
} else {
|
|
||||||
go func() {
|
|
||||||
select {
|
|
||||||
case <-parent.Done():
|
|
||||||
child.cancel(false, parent.Err())
|
|
||||||
case <-child.Done():
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// parentCancelCtx follows a chain of parent references until it finds a
|
|
||||||
// *cancelCtx. This function understands how each of the concrete types in this
|
|
||||||
// package represents its parent.
|
|
||||||
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
|
|
||||||
for {
|
|
||||||
switch c := parent.(type) {
|
|
||||||
case *cancelCtx:
|
|
||||||
return c, true
|
|
||||||
case *timerCtx:
|
|
||||||
return c.cancelCtx, true
|
|
||||||
case *valueCtx:
|
|
||||||
parent = c.Context
|
|
||||||
default:
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeChild removes a context from its parent.
|
|
||||||
func removeChild(parent Context, child canceler) {
|
|
||||||
p, ok := parentCancelCtx(parent)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.mu.Lock()
|
|
||||||
if p.children != nil {
|
|
||||||
delete(p.children, child)
|
|
||||||
}
|
|
||||||
p.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// A canceler is a context type that can be canceled directly. The
|
|
||||||
// implementations are *cancelCtx and *timerCtx.
|
|
||||||
type canceler interface {
|
|
||||||
cancel(removeFromParent bool, err error)
|
|
||||||
Done() <-chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A cancelCtx can be canceled. When canceled, it also cancels any children
|
|
||||||
// that implement canceler.
|
|
||||||
type cancelCtx struct {
|
|
||||||
Context
|
|
||||||
|
|
||||||
done chan struct{} // closed by the first cancel call.
|
|
||||||
|
|
||||||
mu sync.Mutex
|
|
||||||
children map[canceler]bool // set to nil by the first cancel call
|
|
||||||
err error // set to non-nil by the first cancel call
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cancelCtx) Done() <-chan struct{} {
|
|
||||||
return c.done
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cancelCtx) Err() error {
|
|
||||||
c.mu.Lock()
|
|
||||||
defer c.mu.Unlock()
|
|
||||||
return c.err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cancelCtx) String() string {
|
|
||||||
return fmt.Sprintf("%v.WithCancel", c.Context)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cancel closes c.done, cancels each of c's children, and, if
|
|
||||||
// removeFromParent is true, removes c from its parent's children.
|
|
||||||
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
|
|
||||||
if err == nil {
|
|
||||||
panic("context: internal error: missing cancel error")
|
|
||||||
}
|
|
||||||
c.mu.Lock()
|
|
||||||
if c.err != nil {
|
|
||||||
c.mu.Unlock()
|
|
||||||
return // already canceled
|
|
||||||
}
|
|
||||||
c.err = err
|
|
||||||
close(c.done)
|
|
||||||
for child := range c.children {
|
|
||||||
// NOTE: acquiring the child's lock while holding parent's lock.
|
|
||||||
child.cancel(false, err)
|
|
||||||
}
|
|
||||||
c.children = nil
|
|
||||||
c.mu.Unlock()
|
|
||||||
|
|
||||||
if removeFromParent {
|
|
||||||
removeChild(c.Context, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDeadline returns a copy of the parent context with the deadline adjusted
|
|
||||||
// to be no later than d. If the parent's deadline is already earlier than d,
|
|
||||||
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
|
|
||||||
// context's Done channel is closed when the deadline expires, when the returned
|
|
||||||
// cancel function is called, or when the parent context's Done channel is
|
|
||||||
// closed, whichever happens first.
|
|
||||||
//
|
|
||||||
// Canceling this context releases resources associated with it, so code should
|
|
||||||
// call cancel as soon as the operations running in this Context complete.
|
|
||||||
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
|
|
||||||
if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
|
|
||||||
// The current deadline is already sooner than the new one.
|
|
||||||
return WithCancel(parent)
|
|
||||||
}
|
|
||||||
c := &timerCtx{
|
|
||||||
cancelCtx: newCancelCtx(parent),
|
|
||||||
deadline: deadline,
|
|
||||||
}
|
|
||||||
propagateCancel(parent, c)
|
|
||||||
d := deadline.Sub(time.Now())
|
|
||||||
if d <= 0 {
|
|
||||||
c.cancel(true, DeadlineExceeded) // deadline has already passed
|
|
||||||
return c, func() { c.cancel(true, Canceled) }
|
|
||||||
}
|
|
||||||
c.mu.Lock()
|
|
||||||
defer c.mu.Unlock()
|
|
||||||
if c.err == nil {
|
|
||||||
c.timer = time.AfterFunc(d, func() {
|
|
||||||
c.cancel(true, DeadlineExceeded)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return c, func() { c.cancel(true, Canceled) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
|
|
||||||
// implement Done and Err. It implements cancel by stopping its timer then
|
|
||||||
// delegating to cancelCtx.cancel.
|
|
||||||
type timerCtx struct {
|
|
||||||
*cancelCtx
|
|
||||||
timer *time.Timer // Under cancelCtx.mu.
|
|
||||||
|
|
||||||
deadline time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
|
|
||||||
return c.deadline, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *timerCtx) String() string {
|
|
||||||
return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *timerCtx) cancel(removeFromParent bool, err error) {
|
|
||||||
c.cancelCtx.cancel(false, err)
|
|
||||||
if removeFromParent {
|
|
||||||
// Remove this timerCtx from its parent cancelCtx's children.
|
|
||||||
removeChild(c.cancelCtx.Context, c)
|
|
||||||
}
|
|
||||||
c.mu.Lock()
|
|
||||||
if c.timer != nil {
|
|
||||||
c.timer.Stop()
|
|
||||||
c.timer = nil
|
|
||||||
}
|
|
||||||
c.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
|
|
||||||
//
|
|
||||||
// Canceling this context releases resources associated with it, so code should
|
|
||||||
// call cancel as soon as the operations running in this Context complete:
|
|
||||||
//
|
|
||||||
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
|
|
||||||
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
|
|
||||||
// defer cancel() // releases resources if slowOperation completes before timeout elapses
|
|
||||||
// return slowOperation(ctx)
|
|
||||||
// }
|
|
||||||
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
|
|
||||||
return WithDeadline(parent, time.Now().Add(timeout))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithValue returns a copy of parent in which the value associated with key is
|
|
||||||
// val.
|
|
||||||
//
|
|
||||||
// Use context Values only for request-scoped data that transits processes and
|
|
||||||
// APIs, not for passing optional parameters to functions.
|
|
||||||
func WithValue(parent Context, key interface{}, val interface{}) Context {
|
|
||||||
return &valueCtx{parent, key, val}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A valueCtx carries a key-value pair. It implements Value for that key and
|
|
||||||
// delegates all other calls to the embedded Context.
|
|
||||||
type valueCtx struct {
|
|
||||||
Context
|
|
||||||
key, val interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *valueCtx) String() string {
|
|
||||||
return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *valueCtx) Value(key interface{}) interface{} {
|
|
||||||
if c.key == key {
|
|
||||||
return c.val
|
|
||||||
}
|
|
||||||
return c.Context.Value(key)
|
|
||||||
}
|
|
|
@ -1,109 +0,0 @@
|
||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !go1.9
|
|
||||||
|
|
||||||
package context
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// A Context carries a deadline, a cancelation signal, and other values across
|
|
||||||
// API boundaries.
|
|
||||||
//
|
|
||||||
// Context's methods may be called by multiple goroutines simultaneously.
|
|
||||||
type Context interface {
|
|
||||||
// Deadline returns the time when work done on behalf of this context
|
|
||||||
// should be canceled. Deadline returns ok==false when no deadline is
|
|
||||||
// set. Successive calls to Deadline return the same results.
|
|
||||||
Deadline() (deadline time.Time, ok bool)
|
|
||||||
|
|
||||||
// Done returns a channel that's closed when work done on behalf of this
|
|
||||||
// context should be canceled. Done may return nil if this context can
|
|
||||||
// never be canceled. Successive calls to Done return the same value.
|
|
||||||
//
|
|
||||||
// WithCancel arranges for Done to be closed when cancel is called;
|
|
||||||
// WithDeadline arranges for Done to be closed when the deadline
|
|
||||||
// expires; WithTimeout arranges for Done to be closed when the timeout
|
|
||||||
// elapses.
|
|
||||||
//
|
|
||||||
// Done is provided for use in select statements:
|
|
||||||
//
|
|
||||||
// // Stream generates values with DoSomething and sends them to out
|
|
||||||
// // until DoSomething returns an error or ctx.Done is closed.
|
|
||||||
// func Stream(ctx context.Context, out chan<- Value) error {
|
|
||||||
// for {
|
|
||||||
// v, err := DoSomething(ctx)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// select {
|
|
||||||
// case <-ctx.Done():
|
|
||||||
// return ctx.Err()
|
|
||||||
// case out <- v:
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// See http://blog.golang.org/pipelines for more examples of how to use
|
|
||||||
// a Done channel for cancelation.
|
|
||||||
Done() <-chan struct{}
|
|
||||||
|
|
||||||
// Err returns a non-nil error value after Done is closed. Err returns
|
|
||||||
// Canceled if the context was canceled or DeadlineExceeded if the
|
|
||||||
// context's deadline passed. No other values for Err are defined.
|
|
||||||
// After Done is closed, successive calls to Err return the same value.
|
|
||||||
Err() error
|
|
||||||
|
|
||||||
// Value returns the value associated with this context for key, or nil
|
|
||||||
// if no value is associated with key. Successive calls to Value with
|
|
||||||
// the same key returns the same result.
|
|
||||||
//
|
|
||||||
// Use context values only for request-scoped data that transits
|
|
||||||
// processes and API boundaries, not for passing optional parameters to
|
|
||||||
// functions.
|
|
||||||
//
|
|
||||||
// A key identifies a specific value in a Context. Functions that wish
|
|
||||||
// to store values in Context typically allocate a key in a global
|
|
||||||
// variable then use that key as the argument to context.WithValue and
|
|
||||||
// Context.Value. A key can be any type that supports equality;
|
|
||||||
// packages should define keys as an unexported type to avoid
|
|
||||||
// collisions.
|
|
||||||
//
|
|
||||||
// Packages that define a Context key should provide type-safe accessors
|
|
||||||
// for the values stores using that key:
|
|
||||||
//
|
|
||||||
// // Package user defines a User type that's stored in Contexts.
|
|
||||||
// package user
|
|
||||||
//
|
|
||||||
// import "golang.org/x/net/context"
|
|
||||||
//
|
|
||||||
// // User is the type of value stored in the Contexts.
|
|
||||||
// type User struct {...}
|
|
||||||
//
|
|
||||||
// // key is an unexported type for keys defined in this package.
|
|
||||||
// // This prevents collisions with keys defined in other packages.
|
|
||||||
// type key int
|
|
||||||
//
|
|
||||||
// // userKey is the key for user.User values in Contexts. It is
|
|
||||||
// // unexported; clients use user.NewContext and user.FromContext
|
|
||||||
// // instead of using this key directly.
|
|
||||||
// var userKey key = 0
|
|
||||||
//
|
|
||||||
// // NewContext returns a new Context that carries value u.
|
|
||||||
// func NewContext(ctx context.Context, u *User) context.Context {
|
|
||||||
// return context.WithValue(ctx, userKey, u)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // FromContext returns the User value stored in ctx, if any.
|
|
||||||
// func FromContext(ctx context.Context) (*User, bool) {
|
|
||||||
// u, ok := ctx.Value(userKey).(*User)
|
|
||||||
// return u, ok
|
|
||||||
// }
|
|
||||||
Value(key interface{}) interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A CancelFunc tells an operation to abandon its work.
|
|
||||||
// A CancelFunc does not wait for the work to stop.
|
|
||||||
// After the first call, subsequent calls to a CancelFunc do nothing.
|
|
||||||
type CancelFunc func()
|
|
|
@ -2,12 +2,14 @@
|
||||||
// Use of this source code is governed by the Apache 2.0
|
// Use of this source code is governed by the Apache 2.0
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !appengine
|
||||||
// +build !appengine
|
// +build !appengine
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -24,7 +26,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
netcontext "golang.org/x/net/context"
|
|
||||||
|
|
||||||
basepb "google.golang.org/appengine/internal/base"
|
basepb "google.golang.org/appengine/internal/base"
|
||||||
logpb "google.golang.org/appengine/internal/log"
|
logpb "google.golang.org/appengine/internal/log"
|
||||||
|
@ -32,8 +33,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
apiPath = "/rpc_http"
|
apiPath = "/rpc_http"
|
||||||
defaultTicketSuffix = "/default.20150612t184001.0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -65,21 +65,22 @@ var (
|
||||||
IdleConnTimeout: 90 * time.Second,
|
IdleConnTimeout: 90 * time.Second,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultTicketOnce sync.Once
|
|
||||||
defaultTicket string
|
|
||||||
backgroundContextOnce sync.Once
|
|
||||||
backgroundContext netcontext.Context
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func apiURL() *url.URL {
|
func apiURL(ctx context.Context) *url.URL {
|
||||||
host, port := "appengine.googleapis.internal", "10001"
|
host, port := "appengine.googleapis.internal", "10001"
|
||||||
if h := os.Getenv("API_HOST"); h != "" {
|
if h := os.Getenv("API_HOST"); h != "" {
|
||||||
host = h
|
host = h
|
||||||
}
|
}
|
||||||
|
if hostOverride := ctx.Value(apiHostOverrideKey); hostOverride != nil {
|
||||||
|
host = hostOverride.(string)
|
||||||
|
}
|
||||||
if p := os.Getenv("API_PORT"); p != "" {
|
if p := os.Getenv("API_PORT"); p != "" {
|
||||||
port = p
|
port = p
|
||||||
}
|
}
|
||||||
|
if portOverride := ctx.Value(apiPortOverrideKey); portOverride != nil {
|
||||||
|
port = portOverride.(string)
|
||||||
|
}
|
||||||
return &url.URL{
|
return &url.URL{
|
||||||
Scheme: "http",
|
Scheme: "http",
|
||||||
Host: host + ":" + port,
|
Host: host + ":" + port,
|
||||||
|
@ -87,82 +88,97 @@ func apiURL() *url.URL {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleHTTP(w http.ResponseWriter, r *http.Request) {
|
// Middleware wraps an http handler so that it can make GAE API calls
|
||||||
c := &context{
|
func Middleware(next http.Handler) http.Handler {
|
||||||
req: r,
|
return handleHTTPMiddleware(executeRequestSafelyMiddleware(next))
|
||||||
outHeader: w.Header(),
|
|
||||||
apiURL: apiURL(),
|
|
||||||
}
|
|
||||||
r = r.WithContext(withContext(r.Context(), c))
|
|
||||||
c.req = r
|
|
||||||
|
|
||||||
stopFlushing := make(chan int)
|
|
||||||
|
|
||||||
// Patch up RemoteAddr so it looks reasonable.
|
|
||||||
if addr := r.Header.Get(userIPHeader); addr != "" {
|
|
||||||
r.RemoteAddr = addr
|
|
||||||
} else if addr = r.Header.Get(remoteAddrHeader); addr != "" {
|
|
||||||
r.RemoteAddr = addr
|
|
||||||
} else {
|
|
||||||
// Should not normally reach here, but pick a sensible default anyway.
|
|
||||||
r.RemoteAddr = "127.0.0.1"
|
|
||||||
}
|
|
||||||
// The address in the headers will most likely be of these forms:
|
|
||||||
// 123.123.123.123
|
|
||||||
// 2001:db8::1
|
|
||||||
// net/http.Request.RemoteAddr is specified to be in "IP:port" form.
|
|
||||||
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
|
|
||||||
// Assume the remote address is only a host; add a default port.
|
|
||||||
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start goroutine responsible for flushing app logs.
|
|
||||||
// This is done after adding c to ctx.m (and stopped before removing it)
|
|
||||||
// because flushing logs requires making an API call.
|
|
||||||
go c.logFlusher(stopFlushing)
|
|
||||||
|
|
||||||
executeRequestSafely(c, r)
|
|
||||||
c.outHeader = nil // make sure header changes aren't respected any more
|
|
||||||
|
|
||||||
stopFlushing <- 1 // any logging beyond this point will be dropped
|
|
||||||
|
|
||||||
// Flush any pending logs asynchronously.
|
|
||||||
c.pendingLogs.Lock()
|
|
||||||
flushes := c.pendingLogs.flushes
|
|
||||||
if len(c.pendingLogs.lines) > 0 {
|
|
||||||
flushes++
|
|
||||||
}
|
|
||||||
c.pendingLogs.Unlock()
|
|
||||||
flushed := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
defer close(flushed)
|
|
||||||
// Force a log flush, because with very short requests we
|
|
||||||
// may not ever flush logs.
|
|
||||||
c.flushLog(true)
|
|
||||||
}()
|
|
||||||
w.Header().Set(logFlushHeader, strconv.Itoa(flushes))
|
|
||||||
|
|
||||||
// Avoid nil Write call if c.Write is never called.
|
|
||||||
if c.outCode != 0 {
|
|
||||||
w.WriteHeader(c.outCode)
|
|
||||||
}
|
|
||||||
if c.outBody != nil {
|
|
||||||
w.Write(c.outBody)
|
|
||||||
}
|
|
||||||
// Wait for the last flush to complete before returning,
|
|
||||||
// otherwise the security ticket will not be valid.
|
|
||||||
<-flushed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeRequestSafely(c *context, r *http.Request) {
|
func handleHTTPMiddleware(next http.Handler) http.Handler {
|
||||||
defer func() {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if x := recover(); x != nil {
|
c := &aeContext{
|
||||||
logf(c, 4, "%s", renderPanic(x)) // 4 == critical
|
req: r,
|
||||||
c.outCode = 500
|
outHeader: w.Header(),
|
||||||
}
|
}
|
||||||
}()
|
r = r.WithContext(withContext(r.Context(), c))
|
||||||
|
c.req = r
|
||||||
|
|
||||||
http.DefaultServeMux.ServeHTTP(c, r)
|
stopFlushing := make(chan int)
|
||||||
|
|
||||||
|
// Patch up RemoteAddr so it looks reasonable.
|
||||||
|
if addr := r.Header.Get(userIPHeader); addr != "" {
|
||||||
|
r.RemoteAddr = addr
|
||||||
|
} else if addr = r.Header.Get(remoteAddrHeader); addr != "" {
|
||||||
|
r.RemoteAddr = addr
|
||||||
|
} else {
|
||||||
|
// Should not normally reach here, but pick a sensible default anyway.
|
||||||
|
r.RemoteAddr = "127.0.0.1"
|
||||||
|
}
|
||||||
|
// The address in the headers will most likely be of these forms:
|
||||||
|
// 123.123.123.123
|
||||||
|
// 2001:db8::1
|
||||||
|
// net/http.Request.RemoteAddr is specified to be in "IP:port" form.
|
||||||
|
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
|
||||||
|
// Assume the remote address is only a host; add a default port.
|
||||||
|
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
|
||||||
|
}
|
||||||
|
|
||||||
|
if logToLogservice() {
|
||||||
|
// Start goroutine responsible for flushing app logs.
|
||||||
|
// This is done after adding c to ctx.m (and stopped before removing it)
|
||||||
|
// because flushing logs requires making an API call.
|
||||||
|
go c.logFlusher(stopFlushing)
|
||||||
|
}
|
||||||
|
|
||||||
|
next.ServeHTTP(c, r)
|
||||||
|
c.outHeader = nil // make sure header changes aren't respected any more
|
||||||
|
|
||||||
|
flushed := make(chan struct{})
|
||||||
|
if logToLogservice() {
|
||||||
|
stopFlushing <- 1 // any logging beyond this point will be dropped
|
||||||
|
|
||||||
|
// Flush any pending logs asynchronously.
|
||||||
|
c.pendingLogs.Lock()
|
||||||
|
flushes := c.pendingLogs.flushes
|
||||||
|
if len(c.pendingLogs.lines) > 0 {
|
||||||
|
flushes++
|
||||||
|
}
|
||||||
|
c.pendingLogs.Unlock()
|
||||||
|
go func() {
|
||||||
|
defer close(flushed)
|
||||||
|
// Force a log flush, because with very short requests we
|
||||||
|
// may not ever flush logs.
|
||||||
|
c.flushLog(true)
|
||||||
|
}()
|
||||||
|
w.Header().Set(logFlushHeader, strconv.Itoa(flushes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid nil Write call if c.Write is never called.
|
||||||
|
if c.outCode != 0 {
|
||||||
|
w.WriteHeader(c.outCode)
|
||||||
|
}
|
||||||
|
if c.outBody != nil {
|
||||||
|
w.Write(c.outBody)
|
||||||
|
}
|
||||||
|
if logToLogservice() {
|
||||||
|
// Wait for the last flush to complete before returning,
|
||||||
|
// otherwise the security ticket will not be valid.
|
||||||
|
<-flushed
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeRequestSafelyMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
defer func() {
|
||||||
|
if x := recover(); x != nil {
|
||||||
|
c := w.(*aeContext)
|
||||||
|
logf(c, 4, "%s", renderPanic(x)) // 4 == critical
|
||||||
|
c.outCode = 500
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderPanic(x interface{}) string {
|
func renderPanic(x interface{}) string {
|
||||||
|
@ -204,9 +220,9 @@ func renderPanic(x interface{}) string {
|
||||||
return string(buf)
|
return string(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// context represents the context of an in-flight HTTP request.
|
// aeContext represents the aeContext of an in-flight HTTP request.
|
||||||
// It implements the appengine.Context and http.ResponseWriter interfaces.
|
// It implements the appengine.Context and http.ResponseWriter interfaces.
|
||||||
type context struct {
|
type aeContext struct {
|
||||||
req *http.Request
|
req *http.Request
|
||||||
|
|
||||||
outCode int
|
outCode int
|
||||||
|
@ -218,8 +234,6 @@ type context struct {
|
||||||
lines []*logpb.UserAppLogLine
|
lines []*logpb.UserAppLogLine
|
||||||
flushes int
|
flushes int
|
||||||
}
|
}
|
||||||
|
|
||||||
apiURL *url.URL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var contextKey = "holds a *context"
|
var contextKey = "holds a *context"
|
||||||
|
@ -227,8 +241,8 @@ var contextKey = "holds a *context"
|
||||||
// jointContext joins two contexts in a superficial way.
|
// jointContext joins two contexts in a superficial way.
|
||||||
// It takes values and timeouts from a base context, and only values from another context.
|
// It takes values and timeouts from a base context, and only values from another context.
|
||||||
type jointContext struct {
|
type jointContext struct {
|
||||||
base netcontext.Context
|
base context.Context
|
||||||
valuesOnly netcontext.Context
|
valuesOnly context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c jointContext) Deadline() (time.Time, bool) {
|
func (c jointContext) Deadline() (time.Time, bool) {
|
||||||
|
@ -252,94 +266,54 @@ func (c jointContext) Value(key interface{}) interface{} {
|
||||||
|
|
||||||
// fromContext returns the App Engine context or nil if ctx is not
|
// fromContext returns the App Engine context or nil if ctx is not
|
||||||
// derived from an App Engine context.
|
// derived from an App Engine context.
|
||||||
func fromContext(ctx netcontext.Context) *context {
|
func fromContext(ctx context.Context) *aeContext {
|
||||||
c, _ := ctx.Value(&contextKey).(*context)
|
c, _ := ctx.Value(&contextKey).(*aeContext)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func withContext(parent netcontext.Context, c *context) netcontext.Context {
|
func withContext(parent context.Context, c *aeContext) context.Context {
|
||||||
ctx := netcontext.WithValue(parent, &contextKey, c)
|
ctx := context.WithValue(parent, &contextKey, c)
|
||||||
if ns := c.req.Header.Get(curNamespaceHeader); ns != "" {
|
if ns := c.req.Header.Get(curNamespaceHeader); ns != "" {
|
||||||
ctx = withNamespace(ctx, ns)
|
ctx = withNamespace(ctx, ns)
|
||||||
}
|
}
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
func toContext(c *context) netcontext.Context {
|
func toContext(c *aeContext) context.Context {
|
||||||
return withContext(netcontext.Background(), c)
|
return withContext(context.Background(), c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IncomingHeaders(ctx netcontext.Context) http.Header {
|
func IncomingHeaders(ctx context.Context) http.Header {
|
||||||
if c := fromContext(ctx); c != nil {
|
if c := fromContext(ctx); c != nil {
|
||||||
return c.req.Header
|
return c.req.Header
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReqContext(req *http.Request) netcontext.Context {
|
func ReqContext(req *http.Request) context.Context {
|
||||||
return req.Context()
|
return req.Context()
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
|
func WithContext(parent context.Context, req *http.Request) context.Context {
|
||||||
return jointContext{
|
return jointContext{
|
||||||
base: parent,
|
base: parent,
|
||||||
valuesOnly: req.Context(),
|
valuesOnly: req.Context(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultTicket returns a ticket used for background context or dev_appserver.
|
|
||||||
func DefaultTicket() string {
|
|
||||||
defaultTicketOnce.Do(func() {
|
|
||||||
if IsDevAppServer() {
|
|
||||||
defaultTicket = "testapp" + defaultTicketSuffix
|
|
||||||
return
|
|
||||||
}
|
|
||||||
appID := partitionlessAppID()
|
|
||||||
escAppID := strings.Replace(strings.Replace(appID, ":", "_", -1), ".", "_", -1)
|
|
||||||
majVersion := VersionID(nil)
|
|
||||||
if i := strings.Index(majVersion, "."); i > 0 {
|
|
||||||
majVersion = majVersion[:i]
|
|
||||||
}
|
|
||||||
defaultTicket = fmt.Sprintf("%s/%s.%s.%s", escAppID, ModuleName(nil), majVersion, InstanceID())
|
|
||||||
})
|
|
||||||
return defaultTicket
|
|
||||||
}
|
|
||||||
|
|
||||||
func BackgroundContext() netcontext.Context {
|
|
||||||
backgroundContextOnce.Do(func() {
|
|
||||||
// Compute background security ticket.
|
|
||||||
ticket := DefaultTicket()
|
|
||||||
|
|
||||||
c := &context{
|
|
||||||
req: &http.Request{
|
|
||||||
Header: http.Header{
|
|
||||||
ticketHeader: []string{ticket},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
apiURL: apiURL(),
|
|
||||||
}
|
|
||||||
backgroundContext = toContext(c)
|
|
||||||
|
|
||||||
// TODO(dsymonds): Wire up the shutdown handler to do a final flush.
|
|
||||||
go c.logFlusher(make(chan int))
|
|
||||||
})
|
|
||||||
|
|
||||||
return backgroundContext
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterTestRequest registers the HTTP request req for testing, such that
|
// RegisterTestRequest registers the HTTP request req for testing, such that
|
||||||
// any API calls are sent to the provided URL. It returns a closure to delete
|
// any API calls are sent to the provided URL.
|
||||||
// the registration.
|
|
||||||
// It should only be used by aetest package.
|
// It should only be used by aetest package.
|
||||||
func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netcontext.Context) netcontext.Context) (*http.Request, func()) {
|
func RegisterTestRequest(req *http.Request, apiURL *url.URL, appID string) *http.Request {
|
||||||
c := &context{
|
ctx := req.Context()
|
||||||
req: req,
|
ctx = withAPIHostOverride(ctx, apiURL.Hostname())
|
||||||
apiURL: apiURL,
|
ctx = withAPIPortOverride(ctx, apiURL.Port())
|
||||||
}
|
ctx = WithAppIDOverride(ctx, appID)
|
||||||
ctx := withContext(decorate(req.Context()), c)
|
|
||||||
req = req.WithContext(ctx)
|
// use the unregistered request as a placeholder so that withContext can read the headers
|
||||||
c.req = req
|
c := &aeContext{req: req}
|
||||||
return req, func() {}
|
c.req = req.WithContext(withContext(ctx, c))
|
||||||
|
return c.req
|
||||||
}
|
}
|
||||||
|
|
||||||
var errTimeout = &CallError{
|
var errTimeout = &CallError{
|
||||||
|
@ -348,7 +322,7 @@ var errTimeout = &CallError{
|
||||||
Timeout: true,
|
Timeout: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Header() http.Header { return c.outHeader }
|
func (c *aeContext) Header() http.Header { return c.outHeader }
|
||||||
|
|
||||||
// Copied from $GOROOT/src/pkg/net/http/transfer.go. Some response status
|
// Copied from $GOROOT/src/pkg/net/http/transfer.go. Some response status
|
||||||
// codes do not permit a response body (nor response entity headers such as
|
// codes do not permit a response body (nor response entity headers such as
|
||||||
|
@ -365,7 +339,7 @@ func bodyAllowedForStatus(status int) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Write(b []byte) (int, error) {
|
func (c *aeContext) Write(b []byte) (int, error) {
|
||||||
if c.outCode == 0 {
|
if c.outCode == 0 {
|
||||||
c.WriteHeader(http.StatusOK)
|
c.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
@ -376,7 +350,7 @@ func (c *context) Write(b []byte) (int, error) {
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) WriteHeader(code int) {
|
func (c *aeContext) WriteHeader(code int) {
|
||||||
if c.outCode != 0 {
|
if c.outCode != 0 {
|
||||||
logf(c, 3, "WriteHeader called multiple times on request.") // error level
|
logf(c, 3, "WriteHeader called multiple times on request.") // error level
|
||||||
return
|
return
|
||||||
|
@ -384,10 +358,11 @@ func (c *context) WriteHeader(code int) {
|
||||||
c.outCode = code
|
c.outCode = code
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) {
|
func post(ctx context.Context, body []byte, timeout time.Duration) (b []byte, err error) {
|
||||||
|
apiURL := apiURL(ctx)
|
||||||
hreq := &http.Request{
|
hreq := &http.Request{
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
URL: c.apiURL,
|
URL: apiURL,
|
||||||
Header: http.Header{
|
Header: http.Header{
|
||||||
apiEndpointHeader: apiEndpointHeaderValue,
|
apiEndpointHeader: apiEndpointHeaderValue,
|
||||||
apiMethodHeader: apiMethodHeaderValue,
|
apiMethodHeader: apiMethodHeaderValue,
|
||||||
|
@ -396,13 +371,16 @@ func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error)
|
||||||
},
|
},
|
||||||
Body: ioutil.NopCloser(bytes.NewReader(body)),
|
Body: ioutil.NopCloser(bytes.NewReader(body)),
|
||||||
ContentLength: int64(len(body)),
|
ContentLength: int64(len(body)),
|
||||||
Host: c.apiURL.Host,
|
Host: apiURL.Host,
|
||||||
}
|
}
|
||||||
if info := c.req.Header.Get(dapperHeader); info != "" {
|
c := fromContext(ctx)
|
||||||
hreq.Header.Set(dapperHeader, info)
|
if c != nil {
|
||||||
}
|
if info := c.req.Header.Get(dapperHeader); info != "" {
|
||||||
if info := c.req.Header.Get(traceHeader); info != "" {
|
hreq.Header.Set(dapperHeader, info)
|
||||||
hreq.Header.Set(traceHeader, info)
|
}
|
||||||
|
if info := c.req.Header.Get(traceHeader); info != "" {
|
||||||
|
hreq.Header.Set(traceHeader, info)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tr := apiHTTPClient.Transport.(*http.Transport)
|
tr := apiHTTPClient.Transport.(*http.Transport)
|
||||||
|
@ -444,7 +422,7 @@ func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error)
|
||||||
return hrespBody, nil
|
return hrespBody, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
|
func Call(ctx context.Context, service, method string, in, out proto.Message) error {
|
||||||
if ns := NamespaceFromContext(ctx); ns != "" {
|
if ns := NamespaceFromContext(ctx); ns != "" {
|
||||||
if fn, ok := NamespaceMods[service]; ok {
|
if fn, ok := NamespaceMods[service]; ok {
|
||||||
fn(in, ns)
|
fn(in, ns)
|
||||||
|
@ -463,15 +441,11 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := fromContext(ctx)
|
c := fromContext(ctx)
|
||||||
if c == nil {
|
|
||||||
// Give a good error message rather than a panic lower down.
|
|
||||||
return errNotAppEngineContext
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply transaction modifications if we're in a transaction.
|
// Apply transaction modifications if we're in a transaction.
|
||||||
if t := transactionFromContext(ctx); t != nil {
|
if t := transactionFromContext(ctx); t != nil {
|
||||||
if t.finished {
|
if t.finished {
|
||||||
return errors.New("transaction context has expired")
|
return errors.New("transaction aeContext has expired")
|
||||||
}
|
}
|
||||||
applyTransaction(in, &t.transaction)
|
applyTransaction(in, &t.transaction)
|
||||||
}
|
}
|
||||||
|
@ -487,20 +461,13 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ticket := c.req.Header.Get(ticketHeader)
|
ticket := ""
|
||||||
// Use a test ticket under test environment.
|
if c != nil {
|
||||||
if ticket == "" {
|
ticket = c.req.Header.Get(ticketHeader)
|
||||||
if appid := ctx.Value(&appIDOverrideKey); appid != nil {
|
if dri := c.req.Header.Get(devRequestIdHeader); IsDevAppServer() && dri != "" {
|
||||||
ticket = appid.(string) + defaultTicketSuffix
|
ticket = dri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fall back to use background ticket when the request ticket is not available in Flex or dev_appserver.
|
|
||||||
if ticket == "" {
|
|
||||||
ticket = DefaultTicket()
|
|
||||||
}
|
|
||||||
if dri := c.req.Header.Get(devRequestIdHeader); IsDevAppServer() && dri != "" {
|
|
||||||
ticket = dri
|
|
||||||
}
|
|
||||||
req := &remotepb.Request{
|
req := &remotepb.Request{
|
||||||
ServiceName: &service,
|
ServiceName: &service,
|
||||||
Method: &method,
|
Method: &method,
|
||||||
|
@ -512,7 +479,7 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
hrespBody, err := c.post(hreqBody, timeout)
|
hrespBody, err := post(ctx, hreqBody, timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -549,11 +516,11 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message)
|
||||||
return proto.Unmarshal(res.Response, out)
|
return proto.Unmarshal(res.Response, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Request() *http.Request {
|
func (c *aeContext) Request() *http.Request {
|
||||||
return c.req
|
return c.req
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) addLogLine(ll *logpb.UserAppLogLine) {
|
func (c *aeContext) addLogLine(ll *logpb.UserAppLogLine) {
|
||||||
// Truncate long log lines.
|
// Truncate long log lines.
|
||||||
// TODO(dsymonds): Check if this is still necessary.
|
// TODO(dsymonds): Check if this is still necessary.
|
||||||
const lim = 8 << 10
|
const lim = 8 << 10
|
||||||
|
@ -575,18 +542,20 @@ var logLevelName = map[int64]string{
|
||||||
4: "CRITICAL",
|
4: "CRITICAL",
|
||||||
}
|
}
|
||||||
|
|
||||||
func logf(c *context, level int64, format string, args ...interface{}) {
|
func logf(c *aeContext, level int64, format string, args ...interface{}) {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
panic("not an App Engine context")
|
panic("not an App Engine aeContext")
|
||||||
}
|
}
|
||||||
s := fmt.Sprintf(format, args...)
|
s := fmt.Sprintf(format, args...)
|
||||||
s = strings.TrimRight(s, "\n") // Remove any trailing newline characters.
|
s = strings.TrimRight(s, "\n") // Remove any trailing newline characters.
|
||||||
c.addLogLine(&logpb.UserAppLogLine{
|
if logToLogservice() {
|
||||||
TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3),
|
c.addLogLine(&logpb.UserAppLogLine{
|
||||||
Level: &level,
|
TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3),
|
||||||
Message: &s,
|
Level: &level,
|
||||||
})
|
Message: &s,
|
||||||
// Only duplicate log to stderr if not running on App Engine second generation
|
})
|
||||||
|
}
|
||||||
|
// Log to stdout if not deployed
|
||||||
if !IsSecondGen() {
|
if !IsSecondGen() {
|
||||||
log.Print(logLevelName[level] + ": " + s)
|
log.Print(logLevelName[level] + ": " + s)
|
||||||
}
|
}
|
||||||
|
@ -594,7 +563,7 @@ func logf(c *context, level int64, format string, args ...interface{}) {
|
||||||
|
|
||||||
// flushLog attempts to flush any pending logs to the appserver.
|
// flushLog attempts to flush any pending logs to the appserver.
|
||||||
// It should not be called concurrently.
|
// It should not be called concurrently.
|
||||||
func (c *context) flushLog(force bool) (flushed bool) {
|
func (c *aeContext) flushLog(force bool) (flushed bool) {
|
||||||
c.pendingLogs.Lock()
|
c.pendingLogs.Lock()
|
||||||
// Grab up to 30 MB. We can get away with up to 32 MB, but let's be cautious.
|
// Grab up to 30 MB. We can get away with up to 32 MB, but let's be cautious.
|
||||||
n, rem := 0, 30<<20
|
n, rem := 0, 30<<20
|
||||||
|
@ -655,7 +624,7 @@ const (
|
||||||
forceFlushInterval = 60 * time.Second
|
forceFlushInterval = 60 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *context) logFlusher(stop <-chan int) {
|
func (c *aeContext) logFlusher(stop <-chan int) {
|
||||||
lastFlush := time.Now()
|
lastFlush := time.Now()
|
||||||
tick := time.NewTicker(flushInterval)
|
tick := time.NewTicker(flushInterval)
|
||||||
for {
|
for {
|
||||||
|
@ -673,6 +642,12 @@ func (c *context) logFlusher(stop <-chan int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ContextForTesting(req *http.Request) netcontext.Context {
|
func ContextForTesting(req *http.Request) context.Context {
|
||||||
return toContext(&context{req: req})
|
return toContext(&aeContext{req: req})
|
||||||
|
}
|
||||||
|
|
||||||
|
func logToLogservice() bool {
|
||||||
|
// TODO: replace logservice with json structured logs to $LOG_DIR/app.log.json
|
||||||
|
// where $LOG_DIR is /var/log in prod and some tmpdir in dev
|
||||||
|
return os.Getenv("LOG_TO_LOGSERVICE") != "0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,13 @@
|
||||||
// Use of this source code is governed by the Apache 2.0
|
// Use of this source code is governed by the Apache 2.0
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build appengine
|
||||||
// +build appengine
|
// +build appengine
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -17,20 +19,19 @@ import (
|
||||||
basepb "appengine_internal/base"
|
basepb "appengine_internal/base"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
netcontext "golang.org/x/net/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var contextKey = "holds an appengine.Context"
|
var contextKey = "holds an appengine.Context"
|
||||||
|
|
||||||
// fromContext returns the App Engine context or nil if ctx is not
|
// fromContext returns the App Engine context or nil if ctx is not
|
||||||
// derived from an App Engine context.
|
// derived from an App Engine context.
|
||||||
func fromContext(ctx netcontext.Context) appengine.Context {
|
func fromContext(ctx context.Context) appengine.Context {
|
||||||
c, _ := ctx.Value(&contextKey).(appengine.Context)
|
c, _ := ctx.Value(&contextKey).(appengine.Context)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only for classic App Engine adapters.
|
// This is only for classic App Engine adapters.
|
||||||
func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error) {
|
func ClassicContextFromContext(ctx context.Context) (appengine.Context, error) {
|
||||||
c := fromContext(ctx)
|
c := fromContext(ctx)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return nil, errNotAppEngineContext
|
return nil, errNotAppEngineContext
|
||||||
|
@ -38,8 +39,8 @@ func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context {
|
func withContext(parent context.Context, c appengine.Context) context.Context {
|
||||||
ctx := netcontext.WithValue(parent, &contextKey, c)
|
ctx := context.WithValue(parent, &contextKey, c)
|
||||||
|
|
||||||
s := &basepb.StringProto{}
|
s := &basepb.StringProto{}
|
||||||
c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil)
|
c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil)
|
||||||
|
@ -50,7 +51,7 @@ func withContext(parent netcontext.Context, c appengine.Context) netcontext.Cont
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
func IncomingHeaders(ctx netcontext.Context) http.Header {
|
func IncomingHeaders(ctx context.Context) http.Header {
|
||||||
if c := fromContext(ctx); c != nil {
|
if c := fromContext(ctx); c != nil {
|
||||||
if req, ok := c.Request().(*http.Request); ok {
|
if req, ok := c.Request().(*http.Request); ok {
|
||||||
return req.Header
|
return req.Header
|
||||||
|
@ -59,11 +60,11 @@ func IncomingHeaders(ctx netcontext.Context) http.Header {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReqContext(req *http.Request) netcontext.Context {
|
func ReqContext(req *http.Request) context.Context {
|
||||||
return WithContext(netcontext.Background(), req)
|
return WithContext(context.Background(), req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
|
func WithContext(parent context.Context, req *http.Request) context.Context {
|
||||||
c := appengine.NewContext(req)
|
c := appengine.NewContext(req)
|
||||||
return withContext(parent, c)
|
return withContext(parent, c)
|
||||||
}
|
}
|
||||||
|
@ -83,11 +84,11 @@ func (t *testingContext) Call(service, method string, _, _ appengine_internal.Pr
|
||||||
}
|
}
|
||||||
func (t *testingContext) Request() interface{} { return t.req }
|
func (t *testingContext) Request() interface{} { return t.req }
|
||||||
|
|
||||||
func ContextForTesting(req *http.Request) netcontext.Context {
|
func ContextForTesting(req *http.Request) context.Context {
|
||||||
return withContext(netcontext.Background(), &testingContext{req: req})
|
return withContext(context.Background(), &testingContext{req: req})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
|
func Call(ctx context.Context, service, method string, in, out proto.Message) error {
|
||||||
if ns := NamespaceFromContext(ctx); ns != "" {
|
if ns := NamespaceFromContext(ctx); ns != "" {
|
||||||
if fn, ok := NamespaceMods[service]; ok {
|
if fn, ok := NamespaceMods[service]; ok {
|
||||||
fn(in, ns)
|
fn(in, ns)
|
||||||
|
@ -144,8 +145,8 @@ func Call(ctx netcontext.Context, service, method string, in, out proto.Message)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleHTTP(w http.ResponseWriter, r *http.Request) {
|
func Middleware(next http.Handler) http.Handler {
|
||||||
panic("handleHTTP called; this should be impossible")
|
panic("Middleware called; this should be impossible")
|
||||||
}
|
}
|
||||||
|
|
||||||
func logf(c appengine.Context, level int64, format string, args ...interface{}) {
|
func logf(c appengine.Context, level int64, format string, args ...interface{}) {
|
||||||
|
|
|
@ -5,20 +5,26 @@
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
netcontext "golang.org/x/net/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ctxKey string
|
||||||
|
|
||||||
|
func (c ctxKey) String() string {
|
||||||
|
return "appengine context key: " + string(c)
|
||||||
|
}
|
||||||
|
|
||||||
var errNotAppEngineContext = errors.New("not an App Engine context")
|
var errNotAppEngineContext = errors.New("not an App Engine context")
|
||||||
|
|
||||||
type CallOverrideFunc func(ctx netcontext.Context, service, method string, in, out proto.Message) error
|
type CallOverrideFunc func(ctx context.Context, service, method string, in, out proto.Message) error
|
||||||
|
|
||||||
var callOverrideKey = "holds []CallOverrideFunc"
|
var callOverrideKey = "holds []CallOverrideFunc"
|
||||||
|
|
||||||
func WithCallOverride(ctx netcontext.Context, f CallOverrideFunc) netcontext.Context {
|
func WithCallOverride(ctx context.Context, f CallOverrideFunc) context.Context {
|
||||||
// We avoid appending to any existing call override
|
// We avoid appending to any existing call override
|
||||||
// so we don't risk overwriting a popped stack below.
|
// so we don't risk overwriting a popped stack below.
|
||||||
var cofs []CallOverrideFunc
|
var cofs []CallOverrideFunc
|
||||||
|
@ -26,10 +32,10 @@ func WithCallOverride(ctx netcontext.Context, f CallOverrideFunc) netcontext.Con
|
||||||
cofs = append(cofs, uf...)
|
cofs = append(cofs, uf...)
|
||||||
}
|
}
|
||||||
cofs = append(cofs, f)
|
cofs = append(cofs, f)
|
||||||
return netcontext.WithValue(ctx, &callOverrideKey, cofs)
|
return context.WithValue(ctx, &callOverrideKey, cofs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func callOverrideFromContext(ctx netcontext.Context) (CallOverrideFunc, netcontext.Context, bool) {
|
func callOverrideFromContext(ctx context.Context) (CallOverrideFunc, context.Context, bool) {
|
||||||
cofs, _ := ctx.Value(&callOverrideKey).([]CallOverrideFunc)
|
cofs, _ := ctx.Value(&callOverrideKey).([]CallOverrideFunc)
|
||||||
if len(cofs) == 0 {
|
if len(cofs) == 0 {
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
|
@ -37,7 +43,7 @@ func callOverrideFromContext(ctx netcontext.Context) (CallOverrideFunc, netconte
|
||||||
// We found a list of overrides; grab the last, and reconstitute a
|
// We found a list of overrides; grab the last, and reconstitute a
|
||||||
// context that will hide it.
|
// context that will hide it.
|
||||||
f := cofs[len(cofs)-1]
|
f := cofs[len(cofs)-1]
|
||||||
ctx = netcontext.WithValue(ctx, &callOverrideKey, cofs[:len(cofs)-1])
|
ctx = context.WithValue(ctx, &callOverrideKey, cofs[:len(cofs)-1])
|
||||||
return f, ctx, true
|
return f, ctx, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,23 +51,35 @@ type logOverrideFunc func(level int64, format string, args ...interface{})
|
||||||
|
|
||||||
var logOverrideKey = "holds a logOverrideFunc"
|
var logOverrideKey = "holds a logOverrideFunc"
|
||||||
|
|
||||||
func WithLogOverride(ctx netcontext.Context, f logOverrideFunc) netcontext.Context {
|
func WithLogOverride(ctx context.Context, f logOverrideFunc) context.Context {
|
||||||
return netcontext.WithValue(ctx, &logOverrideKey, f)
|
return context.WithValue(ctx, &logOverrideKey, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
var appIDOverrideKey = "holds a string, being the full app ID"
|
var appIDOverrideKey = "holds a string, being the full app ID"
|
||||||
|
|
||||||
func WithAppIDOverride(ctx netcontext.Context, appID string) netcontext.Context {
|
func WithAppIDOverride(ctx context.Context, appID string) context.Context {
|
||||||
return netcontext.WithValue(ctx, &appIDOverrideKey, appID)
|
return context.WithValue(ctx, &appIDOverrideKey, appID)
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiHostOverrideKey = ctxKey("holds a string, being the alternate API_HOST")
|
||||||
|
|
||||||
|
func withAPIHostOverride(ctx context.Context, apiHost string) context.Context {
|
||||||
|
return context.WithValue(ctx, apiHostOverrideKey, apiHost)
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiPortOverrideKey = ctxKey("holds a string, being the alternate API_PORT")
|
||||||
|
|
||||||
|
func withAPIPortOverride(ctx context.Context, apiPort string) context.Context {
|
||||||
|
return context.WithValue(ctx, apiPortOverrideKey, apiPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
var namespaceKey = "holds the namespace string"
|
var namespaceKey = "holds the namespace string"
|
||||||
|
|
||||||
func withNamespace(ctx netcontext.Context, ns string) netcontext.Context {
|
func withNamespace(ctx context.Context, ns string) context.Context {
|
||||||
return netcontext.WithValue(ctx, &namespaceKey, ns)
|
return context.WithValue(ctx, &namespaceKey, ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NamespaceFromContext(ctx netcontext.Context) string {
|
func NamespaceFromContext(ctx context.Context) string {
|
||||||
// If there's no namespace, return the empty string.
|
// If there's no namespace, return the empty string.
|
||||||
ns, _ := ctx.Value(&namespaceKey).(string)
|
ns, _ := ctx.Value(&namespaceKey).(string)
|
||||||
return ns
|
return ns
|
||||||
|
@ -70,14 +88,14 @@ func NamespaceFromContext(ctx netcontext.Context) string {
|
||||||
// FullyQualifiedAppID returns the fully-qualified application ID.
|
// FullyQualifiedAppID returns the fully-qualified application ID.
|
||||||
// This may contain a partition prefix (e.g. "s~" for High Replication apps),
|
// This may contain a partition prefix (e.g. "s~" for High Replication apps),
|
||||||
// or a domain prefix (e.g. "example.com:").
|
// or a domain prefix (e.g. "example.com:").
|
||||||
func FullyQualifiedAppID(ctx netcontext.Context) string {
|
func FullyQualifiedAppID(ctx context.Context) string {
|
||||||
if id, ok := ctx.Value(&appIDOverrideKey).(string); ok {
|
if id, ok := ctx.Value(&appIDOverrideKey).(string); ok {
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
return fullyQualifiedAppID(ctx)
|
return fullyQualifiedAppID(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Logf(ctx netcontext.Context, level int64, format string, args ...interface{}) {
|
func Logf(ctx context.Context, level int64, format string, args ...interface{}) {
|
||||||
if f, ok := ctx.Value(&logOverrideKey).(logOverrideFunc); ok {
|
if f, ok := ctx.Value(&logOverrideKey).(logOverrideFunc); ok {
|
||||||
f(level, format, args...)
|
f(level, format, args...)
|
||||||
return
|
return
|
||||||
|
@ -90,7 +108,7 @@ func Logf(ctx netcontext.Context, level int64, format string, args ...interface{
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamespacedContext wraps a Context to support namespaces.
|
// NamespacedContext wraps a Context to support namespaces.
|
||||||
func NamespacedContext(ctx netcontext.Context, namespace string) netcontext.Context {
|
func NamespacedContext(ctx context.Context, namespace string) context.Context {
|
||||||
return withNamespace(ctx, namespace)
|
return withNamespace(ctx, namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
netcontext "golang.org/x/net/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -23,7 +22,7 @@ var (
|
||||||
|
|
||||||
// AppID is the implementation of the wrapper function of the same name in
|
// AppID is the implementation of the wrapper function of the same name in
|
||||||
// ../identity.go. See that file for commentary.
|
// ../identity.go. See that file for commentary.
|
||||||
func AppID(c netcontext.Context) string {
|
func AppID(c context.Context) string {
|
||||||
return appID(FullyQualifiedAppID(c))
|
return appID(FullyQualifiedAppID(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ func IsStandard() bool {
|
||||||
return appengineStandard || IsSecondGen()
|
return appengineStandard || IsSecondGen()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsStandard is the implementation of the wrapper function of the same name in
|
// IsSecondGen is the implementation of the wrapper function of the same name in
|
||||||
// ../appengine.go. See that file for commentary.
|
// ../appengine.go. See that file for commentary.
|
||||||
func IsSecondGen() bool {
|
func IsSecondGen() bool {
|
||||||
// Second-gen runtimes set $GAE_ENV so we use that to check if we're on a second-gen runtime.
|
// Second-gen runtimes set $GAE_ENV so we use that to check if we're on a second-gen runtime.
|
||||||
|
|
|
@ -2,21 +2,22 @@
|
||||||
// Use of this source code is governed by the Apache 2.0
|
// Use of this source code is governed by the Apache 2.0
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build appengine
|
||||||
// +build appengine
|
// +build appengine
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"appengine"
|
"context"
|
||||||
|
|
||||||
netcontext "golang.org/x/net/context"
|
"appengine"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
appengineStandard = true
|
appengineStandard = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultVersionHostname(ctx netcontext.Context) string {
|
func DefaultVersionHostname(ctx context.Context) string {
|
||||||
c := fromContext(ctx)
|
c := fromContext(ctx)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
panic(errNotAppEngineContext)
|
panic(errNotAppEngineContext)
|
||||||
|
@ -24,12 +25,12 @@ func DefaultVersionHostname(ctx netcontext.Context) string {
|
||||||
return appengine.DefaultVersionHostname(c)
|
return appengine.DefaultVersionHostname(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Datacenter(_ netcontext.Context) string { return appengine.Datacenter() }
|
func Datacenter(_ context.Context) string { return appengine.Datacenter() }
|
||||||
func ServerSoftware() string { return appengine.ServerSoftware() }
|
func ServerSoftware() string { return appengine.ServerSoftware() }
|
||||||
func InstanceID() string { return appengine.InstanceID() }
|
func InstanceID() string { return appengine.InstanceID() }
|
||||||
func IsDevAppServer() bool { return appengine.IsDevAppServer() }
|
func IsDevAppServer() bool { return appengine.IsDevAppServer() }
|
||||||
|
|
||||||
func RequestID(ctx netcontext.Context) string {
|
func RequestID(ctx context.Context) string {
|
||||||
c := fromContext(ctx)
|
c := fromContext(ctx)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
panic(errNotAppEngineContext)
|
panic(errNotAppEngineContext)
|
||||||
|
@ -37,14 +38,14 @@ func RequestID(ctx netcontext.Context) string {
|
||||||
return appengine.RequestID(c)
|
return appengine.RequestID(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ModuleName(ctx netcontext.Context) string {
|
func ModuleName(ctx context.Context) string {
|
||||||
c := fromContext(ctx)
|
c := fromContext(ctx)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
panic(errNotAppEngineContext)
|
panic(errNotAppEngineContext)
|
||||||
}
|
}
|
||||||
return appengine.ModuleName(c)
|
return appengine.ModuleName(c)
|
||||||
}
|
}
|
||||||
func VersionID(ctx netcontext.Context) string {
|
func VersionID(ctx context.Context) string {
|
||||||
c := fromContext(ctx)
|
c := fromContext(ctx)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
panic(errNotAppEngineContext)
|
panic(errNotAppEngineContext)
|
||||||
|
@ -52,7 +53,7 @@ func VersionID(ctx netcontext.Context) string {
|
||||||
return appengine.VersionID(c)
|
return appengine.VersionID(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fullyQualifiedAppID(ctx netcontext.Context) string {
|
func fullyQualifiedAppID(ctx context.Context) string {
|
||||||
c := fromContext(ctx)
|
c := fromContext(ctx)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
panic(errNotAppEngineContext)
|
panic(errNotAppEngineContext)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Use of this source code is governed by the Apache 2.0
|
// Use of this source code is governed by the Apache 2.0
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build appenginevm
|
||||||
// +build appenginevm
|
// +build appenginevm
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
// Use of this source code is governed by the Apache 2.0
|
// Use of this source code is governed by the Apache 2.0
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !appengine
|
||||||
// +build !appengine
|
// +build !appengine
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
netcontext "golang.org/x/net/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// These functions are implementations of the wrapper functions
|
// These functions are implementations of the wrapper functions
|
||||||
|
@ -24,7 +24,7 @@ const (
|
||||||
hDatacenter = "X-AppEngine-Datacenter"
|
hDatacenter = "X-AppEngine-Datacenter"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ctxHeaders(ctx netcontext.Context) http.Header {
|
func ctxHeaders(ctx context.Context) http.Header {
|
||||||
c := fromContext(ctx)
|
c := fromContext(ctx)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -32,15 +32,15 @@ func ctxHeaders(ctx netcontext.Context) http.Header {
|
||||||
return c.Request().Header
|
return c.Request().Header
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultVersionHostname(ctx netcontext.Context) string {
|
func DefaultVersionHostname(ctx context.Context) string {
|
||||||
return ctxHeaders(ctx).Get(hDefaultVersionHostname)
|
return ctxHeaders(ctx).Get(hDefaultVersionHostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RequestID(ctx netcontext.Context) string {
|
func RequestID(ctx context.Context) string {
|
||||||
return ctxHeaders(ctx).Get(hRequestLogId)
|
return ctxHeaders(ctx).Get(hRequestLogId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Datacenter(ctx netcontext.Context) string {
|
func Datacenter(ctx context.Context) string {
|
||||||
if dc := ctxHeaders(ctx).Get(hDatacenter); dc != "" {
|
if dc := ctxHeaders(ctx).Get(hDatacenter); dc != "" {
|
||||||
return dc
|
return dc
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ func ServerSoftware() string {
|
||||||
|
|
||||||
// TODO(dsymonds): Remove the metadata fetches.
|
// TODO(dsymonds): Remove the metadata fetches.
|
||||||
|
|
||||||
func ModuleName(_ netcontext.Context) string {
|
func ModuleName(_ context.Context) string {
|
||||||
if s := os.Getenv("GAE_MODULE_NAME"); s != "" {
|
if s := os.Getenv("GAE_MODULE_NAME"); s != "" {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ func ModuleName(_ netcontext.Context) string {
|
||||||
return string(mustGetMetadata("instance/attributes/gae_backend_name"))
|
return string(mustGetMetadata("instance/attributes/gae_backend_name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func VersionID(_ netcontext.Context) string {
|
func VersionID(_ context.Context) string {
|
||||||
if s1, s2 := os.Getenv("GAE_MODULE_VERSION"), os.Getenv("GAE_MINOR_VERSION"); s1 != "" && s2 != "" {
|
if s1, s2 := os.Getenv("GAE_MODULE_VERSION"), os.Getenv("GAE_MINOR_VERSION"); s1 != "" && s2 != "" {
|
||||||
return s1 + "." + s2
|
return s1 + "." + s2
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ func partitionlessAppID() string {
|
||||||
return string(mustGetMetadata("instance/attributes/gae_project"))
|
return string(mustGetMetadata("instance/attributes/gae_project"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func fullyQualifiedAppID(_ netcontext.Context) string {
|
func fullyQualifiedAppID(_ context.Context) string {
|
||||||
if s := os.Getenv("GAE_APPLICATION"); s != "" {
|
if s := os.Getenv("GAE_APPLICATION"); s != "" {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
@ -130,5 +130,5 @@ func fullyQualifiedAppID(_ netcontext.Context) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsDevAppServer() bool {
|
func IsDevAppServer() bool {
|
||||||
return os.Getenv("RUN_WITH_DEVAPPSERVER") != ""
|
return os.Getenv("RUN_WITH_DEVAPPSERVER") != "" || os.Getenv("GAE_ENV") == "localdev"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Use of this source code is governed by the Apache 2.0
|
// Use of this source code is governed by the Apache 2.0
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build appengine
|
||||||
// +build appengine
|
// +build appengine
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Use of this source code is governed by the Apache 2.0
|
// Use of this source code is governed by the Apache 2.0
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !appengine
|
||||||
// +build !appengine
|
// +build !appengine
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
@ -29,7 +30,7 @@ func Main() {
|
||||||
if IsDevAppServer() {
|
if IsDevAppServer() {
|
||||||
host = "127.0.0.1"
|
host = "127.0.0.1"
|
||||||
}
|
}
|
||||||
if err := http.ListenAndServe(host+":"+port, http.HandlerFunc(handleHTTP)); err != nil {
|
if err := http.ListenAndServe(host+":"+port, Middleware(http.DefaultServeMux)); err != nil {
|
||||||
log.Fatalf("http.ListenAndServe: %v", err)
|
log.Fatalf("http.ListenAndServe: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,11 @@ package internal
|
||||||
// This file implements hooks for applying datastore transactions.
|
// This file implements hooks for applying datastore transactions.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
netcontext "golang.org/x/net/context"
|
|
||||||
|
|
||||||
basepb "google.golang.org/appengine/internal/base"
|
basepb "google.golang.org/appengine/internal/base"
|
||||||
pb "google.golang.org/appengine/internal/datastore"
|
pb "google.golang.org/appengine/internal/datastore"
|
||||||
|
@ -38,13 +38,13 @@ func applyTransaction(pb proto.Message, t *pb.Transaction) {
|
||||||
|
|
||||||
var transactionKey = "used for *Transaction"
|
var transactionKey = "used for *Transaction"
|
||||||
|
|
||||||
func transactionFromContext(ctx netcontext.Context) *transaction {
|
func transactionFromContext(ctx context.Context) *transaction {
|
||||||
t, _ := ctx.Value(&transactionKey).(*transaction)
|
t, _ := ctx.Value(&transactionKey).(*transaction)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func withTransaction(ctx netcontext.Context, t *transaction) netcontext.Context {
|
func withTransaction(ctx context.Context, t *transaction) context.Context {
|
||||||
return netcontext.WithValue(ctx, &transactionKey, t)
|
return context.WithValue(ctx, &transactionKey, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
type transaction struct {
|
type transaction struct {
|
||||||
|
@ -54,7 +54,7 @@ type transaction struct {
|
||||||
|
|
||||||
var ErrConcurrentTransaction = errors.New("internal: concurrent transaction")
|
var ErrConcurrentTransaction = errors.New("internal: concurrent transaction")
|
||||||
|
|
||||||
func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, xg bool, readOnly bool, previousTransaction *pb.Transaction) (*pb.Transaction, error) {
|
func RunTransactionOnce(c context.Context, f func(context.Context) error, xg bool, readOnly bool, previousTransaction *pb.Transaction) (*pb.Transaction, error) {
|
||||||
if transactionFromContext(c) != nil {
|
if transactionFromContext(c) != nil {
|
||||||
return nil, errors.New("nested transactions are not supported")
|
return nil, errors.New("nested transactions are not supported")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package urlfetch // import "google.golang.org/appengine/urlfetch"
|
package urlfetch // import "google.golang.org/appengine/urlfetch"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -18,7 +19,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"golang.org/x/net/context"
|
|
||||||
|
|
||||||
"google.golang.org/appengine/internal"
|
"google.golang.org/appengine/internal"
|
||||||
pb "google.golang.org/appengine/internal/urlfetch"
|
pb "google.golang.org/appengine/internal/urlfetch"
|
||||||
|
@ -44,11 +44,10 @@ type Transport struct {
|
||||||
var _ http.RoundTripper = (*Transport)(nil)
|
var _ http.RoundTripper = (*Transport)(nil)
|
||||||
|
|
||||||
// Client returns an *http.Client using a default urlfetch Transport. This
|
// Client returns an *http.Client using a default urlfetch Transport. This
|
||||||
// client will have the default deadline of 5 seconds, and will check the
|
// client will check the validity of SSL certificates.
|
||||||
// validity of SSL certificates.
|
|
||||||
//
|
//
|
||||||
// Any deadline of the provided context will be used for requests through this client;
|
// Any deadline of the provided context will be used for requests through this client.
|
||||||
// if the client does not have a deadline then a 5 second default is used.
|
// If the client does not have a deadline, then an App Engine default of 60 second is used.
|
||||||
func Client(ctx context.Context) *http.Client {
|
func Client(ctx context.Context) *http.Client {
|
||||||
return &http.Client{
|
return &http.Client{
|
||||||
Transport: &Transport{
|
Transport: &Transport{
|
||||||
|
|
|
@ -876,7 +876,6 @@ golang.org/x/mod/module
|
||||||
golang.org/x/mod/semver
|
golang.org/x/mod/semver
|
||||||
# golang.org/x/net v0.25.0
|
# golang.org/x/net v0.25.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/net/context
|
|
||||||
golang.org/x/net/html
|
golang.org/x/net/html
|
||||||
golang.org/x/net/html/atom
|
golang.org/x/net/html/atom
|
||||||
golang.org/x/net/http/httpguts
|
golang.org/x/net/http/httpguts
|
||||||
|
@ -941,7 +940,7 @@ golang.org/x/tools/internal/tokeninternal
|
||||||
golang.org/x/tools/internal/typeparams
|
golang.org/x/tools/internal/typeparams
|
||||||
golang.org/x/tools/internal/typesinternal
|
golang.org/x/tools/internal/typesinternal
|
||||||
golang.org/x/tools/internal/versions
|
golang.org/x/tools/internal/versions
|
||||||
# google.golang.org/appengine v1.6.7
|
# google.golang.org/appengine v1.6.8
|
||||||
## explicit; go 1.11
|
## explicit; go 1.11
|
||||||
google.golang.org/appengine/internal
|
google.golang.org/appengine/internal
|
||||||
google.golang.org/appengine/internal/base
|
google.golang.org/appengine/internal/base
|
||||||
|
|
Loading…
Reference in New Issue