go.uber.org/yarpc@v1.72.1/api/transport/request.go (about)

     1  // Copyright (c) 2022 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package transport
    22  
    23  import (
    24  	"context"
    25  	"io"
    26  	"strings"
    27  
    28  	"go.uber.org/yarpc/yarpcerrors"
    29  	"go.uber.org/zap/zapcore"
    30  )
    31  
    32  // Request is the low level request representation.
    33  type Request struct {
    34  	// Name of the service making the request.
    35  	Caller string
    36  
    37  	// Name of the service to which the request is being made.
    38  	// The service refers to the canonical traffic group for the service.
    39  	Service string
    40  
    41  	// Name of the transport used for the call.
    42  	Transport string
    43  
    44  	// Name of the encoding used for the request body.
    45  	Encoding Encoding
    46  
    47  	// Name of the procedure being called.
    48  	Procedure string
    49  
    50  	// Headers for the request.
    51  	Headers Headers
    52  
    53  	// ShardKey is an opaque string that is meaningful to the destined service
    54  	// for how to relay a request within a cluster to the shard that owns the
    55  	// key.
    56  	ShardKey string
    57  
    58  	// RoutingKey refers to a traffic group for the destined service, and when
    59  	// present may override the service name for purposes of routing.
    60  	RoutingKey string
    61  
    62  	// RoutingDelegate refers to the traffic group for a service that proxies
    63  	// for the destined service for routing purposes. The routing delegate may
    64  	// override the routing key and service.
    65  	RoutingDelegate string
    66  
    67  	// CallerProcedure refers to the name of the rpc procedure from the service making this request.
    68  	CallerProcedure string
    69  
    70  	// Request payload.
    71  	Body io.Reader
    72  
    73  	// Request payload size before any compression applied by the protocol
    74  	// When using the HTTP transport, this value is set from the HTTP header
    75  	// content-length. It should be noted that this value is set manually and
    76  	// will not be updated automatically if the body is being modified
    77  	BodySize int
    78  }
    79  
    80  // ToRequestMeta converts a Request into a RequestMeta.
    81  func (r *Request) ToRequestMeta() *RequestMeta {
    82  	return &RequestMeta{
    83  		Caller:          r.Caller,
    84  		Service:         r.Service,
    85  		Transport:       r.Transport,
    86  		Encoding:        r.Encoding,
    87  		Procedure:       r.Procedure,
    88  		Headers:         r.Headers,
    89  		ShardKey:        r.ShardKey,
    90  		RoutingKey:      r.RoutingKey,
    91  		RoutingDelegate: r.RoutingDelegate,
    92  		CallerProcedure: r.CallerProcedure,
    93  	}
    94  }
    95  
    96  // MarshalLogObject implements zap.ObjectMarshaler.
    97  func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error {
    98  	// TODO (#788): Include headers once we can omit PII.
    99  	enc.AddString("caller", r.Caller)
   100  	enc.AddString("service", r.Service)
   101  	enc.AddString("transport", r.Transport)
   102  	enc.AddString("encoding", string(r.Encoding))
   103  	enc.AddString("procedure", r.Procedure)
   104  	enc.AddString("shardKey", r.ShardKey)
   105  	enc.AddString("routingKey", r.RoutingKey)
   106  	enc.AddString("routingDelegate", r.RoutingDelegate)
   107  	enc.AddString("callerProcedure", r.CallerProcedure)
   108  	return nil
   109  }
   110  
   111  // Encoding represents an encoding format for requests.
   112  type Encoding string
   113  
   114  // ValidateRequest validates the given request. An error is returned if the
   115  // request is invalid.
   116  //
   117  // Inbound transport implementations may use this to validate requests before
   118  // handling them. Outbound implementations don't need to validate requests;
   119  // they are always validated before the outbound is called.
   120  func ValidateRequest(req *Request) error {
   121  	var missingParams []string
   122  	if req.Service == "" {
   123  		missingParams = append(missingParams, "service name")
   124  	}
   125  	if req.Procedure == "" {
   126  		missingParams = append(missingParams, "procedure")
   127  	}
   128  	if req.Caller == "" {
   129  		missingParams = append(missingParams, "caller name")
   130  	}
   131  	if req.Encoding == "" {
   132  		missingParams = append(missingParams, "encoding")
   133  	}
   134  	if len(missingParams) > 0 {
   135  		return yarpcerrors.Newf(yarpcerrors.CodeInvalidArgument, "missing %s", strings.Join(missingParams, ", "))
   136  	}
   137  	return nil
   138  }
   139  
   140  // ValidateUnaryContext validates that a context for a unary request is valid
   141  // and contains all required information, and returns a YARPC error with code
   142  // yarpcerrors.CodeInvalidArgument otherwise.
   143  //
   144  // Deprecated: Use ValidateRequestContext instead.
   145  func ValidateUnaryContext(ctx context.Context) error {
   146  	if _, hasDeadline := ctx.Deadline(); !hasDeadline {
   147  		return yarpcerrors.Newf(yarpcerrors.CodeInvalidArgument, "missing TTL")
   148  	}
   149  	return nil
   150  }
   151  
   152  // ValidateRequestContext validates that a context for a request is valid
   153  // and contains all required information, and returns a YARPC error with code
   154  // yarpcerrors.CodeInvalidArgument otherwise.
   155  func ValidateRequestContext(ctx context.Context) error {
   156  	if _, hasDeadline := ctx.Deadline(); !hasDeadline {
   157  		return yarpcerrors.Newf(yarpcerrors.CodeInvalidArgument, "missing TTL")
   158  	}
   159  	return nil
   160  }
   161  
   162  // RequestMeta is the low level request metadata representation.  It does not
   163  // include any "body" information, and should only be used for information about
   164  // a connection's metadata.
   165  type RequestMeta struct {
   166  	// Name of the service making the request.
   167  	Caller string
   168  
   169  	// Name of the service to which the request is being made.
   170  	// The service refers to the canonical traffic group for the service.
   171  	Service string
   172  
   173  	// Name of the transport used for the call.
   174  	Transport string
   175  
   176  	// Name of the encoding used for the request body.
   177  	Encoding Encoding
   178  
   179  	// Name of the procedure being called.
   180  	Procedure string
   181  
   182  	// Headers for the request.
   183  	Headers Headers
   184  
   185  	// ShardKey is an opaque string that is meaningful to the destined service
   186  	// for how to relay a request within a cluster to the shard that owns the
   187  	// key.
   188  	ShardKey string
   189  
   190  	// RoutingKey refers to a traffic group for the destined service, and when
   191  	// present may override the service name for purposes of routing.
   192  	RoutingKey string
   193  
   194  	// RoutingDelegate refers to the traffic group for a service that proxies
   195  	// for the destined service for routing purposes. The routing delegate may
   196  	// override the routing key and service.
   197  	RoutingDelegate string
   198  
   199  	// CallerProcedure refers to the name of the rpc procedure of the service making this request.
   200  	CallerProcedure string
   201  }
   202  
   203  // ToRequest converts a RequestMeta into a Request.
   204  func (r *RequestMeta) ToRequest() *Request {
   205  	if r == nil {
   206  		return &Request{}
   207  	}
   208  	return &Request{
   209  		Caller:          r.Caller,
   210  		Service:         r.Service,
   211  		Transport:       r.Transport,
   212  		Encoding:        r.Encoding,
   213  		Procedure:       r.Procedure,
   214  		Headers:         r.Headers,
   215  		ShardKey:        r.ShardKey,
   216  		RoutingKey:      r.RoutingKey,
   217  		RoutingDelegate: r.RoutingDelegate,
   218  		CallerProcedure: r.CallerProcedure,
   219  	}
   220  }