359
metricsHandler metrics.Handler,
360
namespaceRegistry namespace.Registry,
362
>
// Create the set of methods via reflection. We currently accept the overhead
363
>
// of reflection compared to having to custom generate gateway code.
364
>
methods := map[string]*serviceMethod{}
365
>
for qualifiedServerName, server := range servers {
366
>
serverVal := reflect.ValueOf(server)
367
>
for reflectMethod := range serverVal.Type().Methods() {
368
>
// We intentionally look this up by name to not assume method indexes line
369
>
// up from type to value
370
>
methodVal := serverVal.MethodByName(reflectMethod.Name)
371
>
// We assume the methods we want only accept a context + request and only
372
>
// return a response + error. We also assume the method name matches the
373
>
// RPC name.
374
>
methodType := methodVal.Type()
375
>
validRPCMethod := methodType.Kind() == reflect.Func &&
376
>
methodType.NumIn() == 2 &&
377
>
methodType.NumOut() == 2 &&
378
>
methodType.In(0) == contextType &&
379
>
methodType.In(1).Implements(protoMessageType) &&
380
>
methodType.Out(0).Implements(protoMessageType) &&
381
>
methodType.Out(1) == errorType
382
>
if !validRPCMethod {
383
>
continue
384
}
385
>
fullMethod := "/" + qualifiedServerName + "/" + reflectMethod.Name
http_api_server.go
386
>
methods[fullMethod] = &serviceMethod{
387
>
info: grpc.UnaryServerInfo{Server: server, FullMethod: fullMethod},
388
>
handler: func(ctx context.Context, req any) (any, error) {
389
ret := methodVal.Call([]reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(req)})
390
err, _ := ret[1].Interface().(error)