| 21 | ) |
| 22 | |
| 23 | func GetProtoMessageDescriptor(ctx context.Context, logger *zap.Logger, pc models.ProtoConfig) (protoreflect.MessageDescriptor, []protoreflect.FileDescriptor, error) { |
| 24 | if pc.ProtoFile == "" && pc.ProtoDir == "" { |
| 25 | return nil, nil, fmt.Errorf("protoFile or protoDir must be provided") |
| 26 | } |
| 27 | |
| 28 | if pc.RequestURI == "" { |
| 29 | return nil, nil, fmt.Errorf("requestURI must be provided, eg:/service.DataService/GetComplexData") |
| 30 | } |
| 31 | |
| 32 | protoPath := pc.ProtoFile |
| 33 | protoDir := pc.ProtoDir |
| 34 | protoInclude := pc.ProtoInclude |
| 35 | grpcPath := pc.RequestURI |
| 36 | |
| 37 | // Auto-derive protoDir from gRPC path when protoInclude is available. |
| 38 | // This enables multi-service scenarios where different requests need different proto directories. |
| 39 | if len(protoInclude) > 0 && grpcPath != "" { |
| 40 | derived, err := deriveProtoDirFromPath(grpcPath, protoInclude) |
| 41 | if err == nil { |
| 42 | protoDir = derived // Use derived directory, taking precedence over config |
| 43 | } else { |
| 44 | logger.Debug("could not auto-derive protoDir from protoInclude; proceeding with provided protoDir", zap.Error(err)) |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | // Validate that we have at least one source of proto files |
| 49 | if protoPath == "" && protoDir == "" { |
| 50 | return nil, nil, fmt.Errorf("protoFile or protoDir must be provided (auto-derive from protoInclude also failed)") |
| 51 | } |
| 52 | |
| 53 | // Normalize protoInclude roots to absolute. |
| 54 | var absRoots []string |
| 55 | for _, p := range protoInclude { |
| 56 | absPath, err := mustAbs(p) |
| 57 | if err != nil { |
| 58 | return nil, nil, err |
| 59 | } |
| 60 | absRoots = append(absRoots, absPath) |
| 61 | } |
| 62 | |
| 63 | // If -proto is given, ensure its directory is an include root. |
| 64 | var absProto string |
| 65 | if protoPath != "" { |
| 66 | var err error |
| 67 | absProto, err = mustAbs(protoPath) |
| 68 | if err != nil { |
| 69 | return nil, nil, err |
| 70 | } |
| 71 | protoDirOfFile := filepath.Dir(absProto) |
| 72 | if !containsDir(absRoots, protoDirOfFile) { |
| 73 | absRoots = append(absRoots, protoDirOfFile) |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | // If -proto_dir is given, ensure it is an include root. |
| 78 | var absProtoDir string |
| 79 | if protoDir != "" { |
| 80 | var err error |