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 }