github.com/cloudwego/kitex@v0.9.0/server/option_advanced.go (about) 1 /* 2 * Copyright 2021 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Package server defines the Options of server 18 package server 19 20 // Notice!! This file defines the advanced Options of client, normal user should not use it. 21 // It is used for customized extension. 22 23 import ( 24 "context" 25 "fmt" 26 "net" 27 "reflect" 28 29 internal_server "github.com/cloudwego/kitex/internal/server" 30 "github.com/cloudwego/kitex/pkg/acl" 31 "github.com/cloudwego/kitex/pkg/diagnosis" 32 "github.com/cloudwego/kitex/pkg/generic" 33 "github.com/cloudwego/kitex/pkg/klog" 34 "github.com/cloudwego/kitex/pkg/limiter" 35 "github.com/cloudwego/kitex/pkg/profiler" 36 "github.com/cloudwego/kitex/pkg/proxy" 37 "github.com/cloudwego/kitex/pkg/remote" 38 "github.com/cloudwego/kitex/pkg/rpcinfo" 39 "github.com/cloudwego/kitex/pkg/utils" 40 ) 41 42 // WithServerBasicInfo provides initial information for client endpoint in RPCInfo. 43 func WithServerBasicInfo(ebi *rpcinfo.EndpointBasicInfo) Option { 44 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 45 di.Push(fmt.Sprintf("WithServerBasicInfo(%+v)", ebi)) 46 47 if ebi != nil { 48 o.Svr = ebi 49 } 50 }} 51 } 52 53 // WithDiagnosisService sets the diagnosis service for gathering debug information. 54 func WithDiagnosisService(ds diagnosis.Service) Option { 55 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 56 o.Once.OnceOrPanic() 57 di.Push(fmt.Sprintf("WithDiagnosisService(%+v)", ds)) 58 59 o.DebugService = ds 60 }} 61 } 62 63 // WithACLRules sets the ACL rules. 64 func WithACLRules(rules ...acl.RejectFunc) Option { 65 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 66 var names []string 67 for _, r := range rules { 68 names = append(names, utils.GetFuncName(r)) 69 } 70 di.Push(fmt.Sprintf("WithACLRules(%+v)", names)) 71 72 o.ACLRules = append(o.ACLRules, rules...) 73 }} 74 } 75 76 // WithMetaHandler adds a MetaHandler. 77 func WithMetaHandler(h remote.MetaHandler) Option { 78 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 79 di.Push(fmt.Sprintf("WithMetaHandler(%T)", h)) 80 81 o.MetaHandlers = append(o.MetaHandlers, h) 82 }} 83 } 84 85 // WithProxy sets the backward Proxy for server. 86 func WithProxy(p proxy.ReverseProxy) Option { 87 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 88 o.Once.OnceOrPanic() 89 di.Push(fmt.Sprintf("WithProxy(%T)", p)) 90 91 if o.Proxy != nil { 92 panic(fmt.Errorf("reassignment of Proxy is not allowed: %T -> %T", o.Proxy, p)) 93 } 94 o.Proxy = p 95 }} 96 } 97 98 // WithTransHandlerFactory sets the TransHandlerFactory for server. 99 func WithTransHandlerFactory(f remote.ServerTransHandlerFactory) Option { 100 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 101 o.Once.OnceOrPanic() 102 di.Push(fmt.Sprintf("WithTransHandlerFactory(%T)", f)) 103 104 o.RemoteOpt.SvrHandlerFactory = f 105 }} 106 } 107 108 // WithTransServerFactory sets the TransServerFactory for server. 109 func WithTransServerFactory(f remote.TransServerFactory) Option { 110 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 111 o.Once.OnceOrPanic() 112 di.Push(fmt.Sprintf("WithTransServerFactory(%T)", f)) 113 114 o.RemoteOpt.TransServerFactory = f 115 }} 116 } 117 118 // WithLimitReporter do report when server limit happen 119 func WithLimitReporter(r limiter.LimitReporter) Option { 120 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 121 o.Once.OnceOrPanic() 122 di.Push(fmt.Sprintf("WithLimitReporter(%T)", r)) 123 124 o.Limit.LimitReporter = r 125 }} 126 } 127 128 // WithGeneric set Generic type for generic call 129 func WithGeneric(g generic.Generic) Option { 130 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 131 o.Once.OnceOrPanic() 132 di.Push(fmt.Sprintf("WithGeneric(%T)", g)) 133 134 if g == nil { 135 panic("invalid Generic: nil") 136 } 137 o.RemoteOpt.PayloadCodec = g.PayloadCodec() 138 }} 139 } 140 141 // WithErrorHandler sets the error handler. 142 func WithErrorHandler(f func(context.Context, error) error) Option { 143 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 144 o.Once.OnceOrPanic() 145 di.Push(fmt.Sprintf("WithErrorHandler(%+v)", utils.GetFuncName(f))) 146 147 o.ErrHandle = f 148 }} 149 } 150 151 // WithBoundHandler adds remote.BoundHandler for server. 152 func WithBoundHandler(h remote.BoundHandler) Option { 153 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 154 di.Push(fmt.Sprintf("AddBoundHandler(%T)", h)) 155 156 exist := false 157 switch handler := h.(type) { 158 case remote.InboundHandler: 159 for _, inboundHandler := range o.RemoteOpt.Inbounds { 160 if reflect.DeepEqual(inboundHandler, handler) { 161 exist = true 162 break 163 } 164 } 165 case remote.OutboundHandler: 166 for _, outboundHandler := range o.RemoteOpt.Outbounds { 167 if reflect.DeepEqual(outboundHandler, handler) { 168 exist = true 169 break 170 } 171 } 172 } 173 // prevent duplication 174 if !exist { 175 doAddBoundHandler(h, o.RemoteOpt) 176 } else { 177 klog.Warnf("KITEX: BoundHandler already exists, BoundHandler=%v", h) 178 } 179 }} 180 } 181 182 // WithExitSignal adds ExitSignal for server. 183 func WithExitSignal(f func() <-chan error) Option { 184 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 185 di.Push(fmt.Sprintf("AddExitSignal(%+v)", utils.GetFuncName(f))) 186 o.ExitSignal = f 187 }} 188 } 189 190 // WithListener sets the listener for server, the priority is higher than WithServiceAddr 191 func WithListener(ln net.Listener) Option { 192 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 193 di.Push(fmt.Sprintf("WithListener(%+v)", ln)) 194 195 o.RemoteOpt.Listener = ln 196 }} 197 } 198 199 // WithReusePort sets SO_REUSEPORT on listener, it is only used with Option `WithServiceAddr`. 200 // It won't take effect when listener is specified by WithListener. 201 func WithReusePort(reuse bool) Option { 202 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 203 di.Push(fmt.Sprintf("WithReusePort(%+v)", reuse)) 204 205 o.RemoteOpt.ReusePort = reuse 206 }} 207 } 208 209 // WithSupportedTransportsFunc sets a function which converts supported transports from server option. 210 func WithSupportedTransportsFunc(f func(option remote.ServerOption) []string) Option { 211 return Option{ 212 F: func(o *internal_server.Options, di *utils.Slice) { 213 di.Push("WithSupportedTransportsFunc()") 214 o.SupportedTransportsFunc = f 215 }, 216 } 217 } 218 219 // WithProfiler set a profiler to server. 220 func WithProfiler(pc profiler.Profiler) Option { 221 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 222 di.Push(fmt.Sprintf("WithProfiler(%T{%+v})", pc, pc)) 223 o.RemoteOpt.Profiler = pc 224 }} 225 } 226 227 // WithProfilerTransInfoTagging set transinfo tagging function to profiler 228 // TransInfoTagging extracting tags after TransInfo decoded but before message decoded. 229 // At this stage, we can only get msg.TransInfo() and the real message payload is not decoded yet. 230 // If upstream is not use TTHeader protocol, we can get nothing here. 231 // So if you don't very care about the accuracy of statistics, we recommend to use WithProfilerMessageTagging to extract your custom tags. 232 func WithProfilerTransInfoTagging(tagging remote.TransInfoTagging) Option { 233 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 234 di.Push(fmt.Sprintf("WithProfilerTransInfoTagging(%+v)", utils.GetFuncName(tagging))) 235 interTagging := o.RemoteOpt.ProfilerTransInfoTagging 236 if interTagging == nil { 237 o.RemoteOpt.ProfilerTransInfoTagging = tagging 238 return 239 } 240 o.RemoteOpt.ProfilerTransInfoTagging = func(ctx context.Context, msg remote.Message) (context.Context, []string) { 241 c, t := tagging(ctx, msg) 242 c2, t2 := interTagging(c, msg) 243 return c2, append(t, t2...) 244 } 245 }} 246 } 247 248 // WithProfilerMessageTagging set message tagging function to profiler 249 // MessageTagging extracting tags after whole decode process finished. 250 // At this stage, we can get the rpcInfo from ctx, and full complete message. 251 func WithProfilerMessageTagging(tagging remote.MessageTagging) Option { 252 return Option{F: func(o *internal_server.Options, di *utils.Slice) { 253 di.Push(fmt.Sprintf("WithProfilerMessageTagging(%+v)", utils.GetFuncName(tagging))) 254 interTagging := o.RemoteOpt.ProfilerMessageTagging 255 if interTagging == nil { 256 o.RemoteOpt.ProfilerMessageTagging = tagging 257 return 258 } 259 o.RemoteOpt.ProfilerMessageTagging = func(ctx context.Context, msg remote.Message) (context.Context, []string) { 260 c, t := tagging(ctx, msg) 261 c2, t2 := interTagging(c, msg) 262 return c2, append(t, t2...) 263 } 264 }} 265 }