mirror of
https://github.com/docker/cli.git
synced 2026-11-06 13:10:41 -04:00
Add the Docker secrets engine client, used to read the Docker Desktop session for Docker Hub. It brings in github.com/docker/secrets-engine/x v0.8.5 and connectrpc.com/connect v1.19.1. The client module requires go1.26.10, which raises the go directive in vendor.mod from 1.26.0. Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
243 lines
7.9 KiB
Go
243 lines
7.9 KiB
Go
// Copyright 2021-2025 The Connect Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package connect
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
)
|
|
|
|
// CallInfo represents information relevant to an RPC call.
|
|
type CallInfo interface {
|
|
// Spec returns a description of this call.
|
|
Spec() Spec
|
|
// Peer describes the other party for this call.
|
|
Peer() Peer
|
|
// RequestHeader returns the HTTP headers for this request. Headers beginning with
|
|
// "Connect-" and "Grpc-" are reserved for use by the Connect and gRPC
|
|
// protocols: applications may read them but shouldn't write them.
|
|
RequestHeader() http.Header
|
|
// ResponseHeader returns the HTTP headers for this response. Headers beginning with
|
|
// "Connect-" and "Grpc-" are reserved for use by the Connect and gRPC
|
|
// protocols: applications may read them but shouldn't write them.
|
|
// On the client side, this method returns nil before
|
|
// the call is actually made. After the call is made, for streaming operations,
|
|
// this method will block for the server to actually return response headers.
|
|
ResponseHeader() http.Header
|
|
// ResponseTrailer returns the trailers for this response. Depending on the underlying
|
|
// RPC protocol, trailers may be sent as HTTP trailers or a protocol-specific
|
|
// block of in-body metadata.
|
|
//
|
|
// Trailers beginning with "Connect-" and "Grpc-" are reserved for use by the
|
|
// Connect and gRPC protocols: applications may read them but shouldn't write
|
|
// them.
|
|
//
|
|
// On the client side, this method returns nil before the call is actually made.
|
|
// After the call is made, for streaming operations, this method will block
|
|
// for the server to actually return response trailers.
|
|
ResponseTrailer() http.Header
|
|
// HTTPMethod returns the HTTP method for this request. This is nearly always
|
|
// POST, but side-effect-free unary RPCs could be made via a GET.
|
|
//
|
|
// On a newly created request, via NewRequest, this will return the empty
|
|
// string until the actual request is actually sent and the HTTP method
|
|
// determined. This means that client interceptor functions will see the
|
|
// empty string until *after* they delegate to the handler they wrapped. It
|
|
// is even possible for this to return the empty string after such delegation,
|
|
// if the request was never actually sent to the server (and thus no
|
|
// determination ever made about the HTTP method).
|
|
HTTPMethod() string
|
|
|
|
internalOnly()
|
|
}
|
|
|
|
// Create a new client (i.e. outgoing) context for use from a client. When the
|
|
// returned context is passed to RPCs, the returned call info can be used to set
|
|
// request metadata before the RPC is invoked and to inspect response
|
|
// metadata after the RPC completes.
|
|
//
|
|
// The returned context may be re-used across RPCs as long as they are
|
|
// not concurrent. Results of all CallInfo methods other than
|
|
// RequestHeader() are undefined if the context is used with concurrent RPCs.
|
|
func NewClientContext(ctx context.Context) (context.Context, CallInfo) {
|
|
info := &clientCallInfo{}
|
|
return context.WithValue(ctx, clientCallInfoContextKey{}, info), info
|
|
}
|
|
|
|
// CallInfoForHandlerContext returns the CallInfo for the given handler (i.e. incoming) context, if there is one.
|
|
func CallInfoForHandlerContext(ctx context.Context) (CallInfo, bool) {
|
|
value, ok := ctx.Value(handlerCallInfoContextKey{}).(CallInfo)
|
|
return value, ok
|
|
}
|
|
|
|
// handlerCallInfo is a CallInfo implementation used for unary handlers.
|
|
type handlerCallInfo struct {
|
|
spec Spec
|
|
peer Peer
|
|
method string
|
|
requestHeader http.Header
|
|
responseHeader http.Header
|
|
responseTrailer http.Header
|
|
}
|
|
|
|
func (c *handlerCallInfo) Spec() Spec {
|
|
return c.spec
|
|
}
|
|
|
|
func (c *handlerCallInfo) Peer() Peer {
|
|
return c.peer
|
|
}
|
|
|
|
func (c *handlerCallInfo) RequestHeader() http.Header {
|
|
if c.requestHeader == nil {
|
|
c.requestHeader = make(http.Header)
|
|
}
|
|
return c.requestHeader
|
|
}
|
|
|
|
func (c *handlerCallInfo) ResponseHeader() http.Header {
|
|
if c.responseHeader == nil {
|
|
c.responseHeader = make(http.Header)
|
|
}
|
|
return c.responseHeader
|
|
}
|
|
|
|
func (c *handlerCallInfo) ResponseTrailer() http.Header {
|
|
if c.responseTrailer == nil {
|
|
c.responseTrailer = make(http.Header)
|
|
}
|
|
return c.responseTrailer
|
|
}
|
|
|
|
func (c *handlerCallInfo) HTTPMethod() string {
|
|
return c.method
|
|
}
|
|
|
|
// internalOnly implements CallInfo.
|
|
func (c *handlerCallInfo) internalOnly() {}
|
|
|
|
// streamingHandlerCallInfo is a CallInfo implementation used for streaming RPC handlers.
|
|
type streamingHandlerCallInfo struct {
|
|
conn StreamingHandlerConn
|
|
}
|
|
|
|
func (c *streamingHandlerCallInfo) Spec() Spec {
|
|
return c.conn.Spec()
|
|
}
|
|
|
|
func (c *streamingHandlerCallInfo) Peer() Peer {
|
|
return c.conn.Peer()
|
|
}
|
|
|
|
func (c *streamingHandlerCallInfo) RequestHeader() http.Header {
|
|
return c.conn.RequestHeader()
|
|
}
|
|
|
|
func (c *streamingHandlerCallInfo) ResponseHeader() http.Header {
|
|
return c.conn.ResponseHeader()
|
|
}
|
|
|
|
func (c *streamingHandlerCallInfo) ResponseTrailer() http.Header {
|
|
return c.conn.ResponseTrailer()
|
|
}
|
|
|
|
func (c *streamingHandlerCallInfo) HTTPMethod() string {
|
|
// All stream calls are POSTs
|
|
return http.MethodPost
|
|
}
|
|
|
|
// internalOnly implements CallInfo.
|
|
func (c *streamingHandlerCallInfo) internalOnly() {}
|
|
|
|
// clientCallInfo is a CallInfo implementation used for clients.
|
|
type clientCallInfo struct {
|
|
responseSource
|
|
spec Spec
|
|
peer Peer
|
|
method string
|
|
requestHeader http.Header
|
|
}
|
|
|
|
func (c *clientCallInfo) Spec() Spec {
|
|
return c.spec
|
|
}
|
|
|
|
func (c *clientCallInfo) Peer() Peer {
|
|
return c.peer
|
|
}
|
|
|
|
func (c *clientCallInfo) RequestHeader() http.Header {
|
|
if c.requestHeader == nil {
|
|
c.requestHeader = make(http.Header)
|
|
}
|
|
return c.requestHeader
|
|
}
|
|
|
|
func (c *clientCallInfo) ResponseHeader() http.Header {
|
|
if c.responseSource == nil {
|
|
return nil
|
|
}
|
|
return c.responseSource.ResponseHeader()
|
|
}
|
|
|
|
func (c *clientCallInfo) ResponseTrailer() http.Header {
|
|
if c.responseSource == nil {
|
|
return nil
|
|
}
|
|
return c.responseSource.ResponseTrailer()
|
|
}
|
|
|
|
func (c *clientCallInfo) HTTPMethod() string {
|
|
return c.method
|
|
}
|
|
|
|
// internalOnly implements CallInfo.
|
|
func (c *clientCallInfo) internalOnly() {}
|
|
|
|
// clientCallInfoContextKey is the key used to store client call info in context.
|
|
type clientCallInfoContextKey struct{}
|
|
|
|
// sentinelContextKey is the key used to store a copy of client call info in context
|
|
// when a request is made.
|
|
// Each step in an interceptor chain compares the actual call info with the
|
|
// sentinel call info. If the two values are different, the request will
|
|
// return an error in the interceptor.
|
|
// This protects against changing the call info in interceptors, which is prohibited
|
|
// as it would allow users to modify call info mid-flight independent of the actual
|
|
// request or response.
|
|
// Users who wish to modify call info data such as headers and trailers should instead
|
|
// use Connect [Request] and [Response] wrapper types.
|
|
type sentinelContextKey struct{}
|
|
|
|
// handlerCallInfoContextKey is the key used to store handler call info in context.
|
|
type handlerCallInfoContextKey struct{}
|
|
|
|
// responseSource indicates a type that manages response headers and trailers.
|
|
type responseSource interface {
|
|
ResponseHeader() http.Header
|
|
ResponseTrailer() http.Header
|
|
}
|
|
|
|
// clientCallInfoForContext gets the call info from a client/outgoing context.
|
|
func clientCallInfoForContext(ctx context.Context) (*clientCallInfo, bool) {
|
|
info, ok := ctx.Value(clientCallInfoContextKey{}).(*clientCallInfo)
|
|
return info, ok
|
|
}
|
|
|
|
// newHandlerContext creates a new handler/incoming context.
|
|
func newHandlerContext(ctx context.Context, info CallInfo) context.Context {
|
|
return context.WithValue(ctx, handlerCallInfoContextKey{}, info)
|
|
}
|