go.uber.org/yarpc@v1.72.1/api/encoding/call.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 encoding
    22  
    23  import (
    24  	"context"
    25  	"sort"
    26  
    27  	"go.uber.org/yarpc/api/transport"
    28  	"go.uber.org/yarpc/internal/inboundcall"
    29  	"go.uber.org/yarpc/yarpcerrors"
    30  )
    31  
    32  type keyValuePair struct{ k, v string }
    33  
    34  // Call provides information about the current request inside handlers.
    35  type Call struct{ md inboundcall.Metadata }
    36  
    37  // CallFromContext retrieves information about the current incoming request
    38  // from the given context. Returns nil if the context is not a valid request
    39  // context.
    40  //
    41  // The object is valid only as long as the request is ongoing.
    42  func CallFromContext(ctx context.Context) *Call {
    43  	if md, ok := inboundcall.GetMetadata(ctx); ok {
    44  		return &Call{md}
    45  	}
    46  	return nil
    47  }
    48  
    49  // WriteResponseHeader writes headers to the response of this call.
    50  func (c *Call) WriteResponseHeader(k, v string) error {
    51  	if c == nil {
    52  		return yarpcerrors.InvalidArgumentErrorf(
    53  			"failed to write response header: " +
    54  				"Call was nil, make sure CallFromContext was called with a request context")
    55  	}
    56  	return c.md.WriteResponseHeader(k, v)
    57  }
    58  
    59  // Caller returns the name of the service making this request.
    60  func (c *Call) Caller() string {
    61  	if c == nil {
    62  		return ""
    63  	}
    64  	return c.md.Caller()
    65  }
    66  
    67  // Service returns the name of the service being called.
    68  func (c *Call) Service() string {
    69  	if c == nil {
    70  		return ""
    71  	}
    72  	return c.md.Service()
    73  }
    74  
    75  // Transport returns the name of the transport being called.
    76  func (c *Call) Transport() string {
    77  	if c == nil {
    78  		return ""
    79  	}
    80  	return c.md.Transport()
    81  }
    82  
    83  // Procedure returns the name of the procedure being called.
    84  func (c *Call) Procedure() string {
    85  	if c == nil {
    86  		return ""
    87  	}
    88  	return c.md.Procedure()
    89  }
    90  
    91  // Encoding returns the encoding for this request.
    92  func (c *Call) Encoding() transport.Encoding {
    93  	if c == nil {
    94  		return ""
    95  	}
    96  	return c.md.Encoding()
    97  }
    98  
    99  // Header returns the value of the given request header provided with the
   100  // request.
   101  func (c *Call) Header(k string) string {
   102  	if c == nil {
   103  		return ""
   104  	}
   105  
   106  	if v, ok := c.md.Headers().Get(k); ok {
   107  		return v
   108  	}
   109  
   110  	return ""
   111  }
   112  
   113  // OriginalHeaders returns a copy of the given request headers provided with the request.
   114  // The header key are not canonicalized and suitable for case-sensitive transport like TChannel.
   115  func (c *Call) OriginalHeaders() map[string]string {
   116  	if c == nil {
   117  		return nil
   118  	}
   119  
   120  	items := c.md.Headers().OriginalItems()
   121  	h := make(map[string]string, len(items))
   122  	for k, v := range items {
   123  		h[k] = v
   124  	}
   125  	return h
   126  }
   127  
   128  // HeaderNames returns a sorted list of the names of user defined headers
   129  // provided with this request.
   130  func (c *Call) HeaderNames() []string {
   131  	if c == nil {
   132  		return nil
   133  	}
   134  
   135  	items := c.md.Headers().Items()
   136  	names := make([]string, 0, len(items))
   137  	for k := range items {
   138  		names = append(names, k)
   139  	}
   140  	sort.Strings(names)
   141  	return names
   142  }
   143  
   144  // ShardKey returns the shard key for this request.
   145  func (c *Call) ShardKey() string {
   146  	if c == nil {
   147  		return ""
   148  	}
   149  	return c.md.ShardKey()
   150  }
   151  
   152  // RoutingKey returns the routing key for this request.
   153  func (c *Call) RoutingKey() string {
   154  	if c == nil {
   155  		return ""
   156  	}
   157  	return c.md.RoutingKey()
   158  }
   159  
   160  // RoutingDelegate returns the routing delegate for this request.
   161  func (c *Call) RoutingDelegate() string {
   162  	if c == nil {
   163  		return ""
   164  	}
   165  	return c.md.RoutingDelegate()
   166  }
   167  
   168  // CallerProcedure returns the name of the procedure from the service making this request.
   169  func (c *Call) CallerProcedure() string {
   170  	if c == nil {
   171  		return ""
   172  	}
   173  	return c.md.CallerProcedure()
   174  }