Skip to content

Commit 2449abe

Browse files
committed
refactor(grpc-reflection): simplified request handling and file dependency logic
1 parent 89a5cbb commit 2449abe

File tree

1 file changed

+45
-37
lines changed

1 file changed

+45
-37
lines changed

packages/grpc-reflection/src/implementations/reflection-v1.ts

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class ReflectionError extends Error {
2626
}
2727
}
2828

29-
/** Analyzes a gRPC server and exposes methods to reflect on it
29+
/** Analyzes a gRPC package definition and exposes methods to reflect on it
3030
*
3131
* NOTE: the files returned by this service may not match the handwritten ones 1:1.
3232
* This is because proto-loader reorients files based on their package definition,
@@ -37,7 +37,7 @@ export class ReflectionError extends Error {
3737
*/
3838
export class ReflectionV1Implementation {
3939

40-
/** The full list of proto files (including imported deps) that the gRPC server includes */
40+
/** The full list of proto files (including imported deps) that the gRPC package includes */
4141
private readonly fileDescriptorSet = new FileDescriptorSet();
4242

4343
/** An index of proto files by file name (eg. 'sample.proto') */
@@ -172,32 +172,34 @@ export class ReflectionV1Implementation {
172172
handleServerReflectionRequest(message: ServerReflectionRequest): ServerReflectionResponse {
173173
const response: ServerReflectionResponse = {
174174
validHost: message.host,
175-
originalRequest: message,
176-
fileDescriptorResponse: undefined,
177-
allExtensionNumbersResponse: undefined,
178-
listServicesResponse: undefined,
179-
errorResponse: undefined,
175+
originalRequest: message
180176
};
181177

182178
try {
183-
if (message.listServices !== undefined) {
184-
response.listServicesResponse = this.listServices(message.listServices);
185-
} else if (message.fileContainingSymbol !== undefined) {
186-
response.fileDescriptorResponse = this.fileContainingSymbol(message.fileContainingSymbol);
187-
} else if (message.fileByFilename !== undefined) {
188-
response.fileDescriptorResponse = this.fileByFilename(message.fileByFilename);
189-
} else if (message.fileContainingExtension !== undefined) {
190-
response.fileDescriptorResponse = this.fileContainingExtension(
191-
message.fileContainingExtension?.containingType || '',
192-
message.fileContainingExtension?.extensionNumber || -1
193-
);
194-
} else if (message.allExtensionNumbersOfType) {
195-
response.allExtensionNumbersResponse = this.allExtensionNumbersOfType(message.allExtensionNumbersOfType);
196-
} else {
197-
throw new ReflectionError(
198-
grpc.status.UNIMPLEMENTED,
199-
`Unimplemented method for request: ${message}`,
200-
);
179+
switch(message.messageRequest) {
180+
case 'listServices':
181+
response.listServicesResponse = this.listServices(message.listServices || '');
182+
break;
183+
case 'fileContainingSymbol':
184+
response.fileDescriptorResponse = this.fileContainingSymbol(message.fileContainingSymbol || '');
185+
break;
186+
case 'fileByFilename':
187+
response.fileDescriptorResponse = this.fileByFilename(message.fileByFilename || '');
188+
break;
189+
case 'fileContainingExtension':
190+
response.fileDescriptorResponse = this.fileContainingExtension(
191+
message.fileContainingExtension?.containingType || '',
192+
message.fileContainingExtension?.extensionNumber || -1
193+
);
194+
break;
195+
case 'allExtensionNumbersOfType':
196+
response.allExtensionNumbersResponse = this.allExtensionNumbersOfType(message.allExtensionNumbersOfType || '');
197+
break;
198+
default:
199+
throw new ReflectionError(
200+
grpc.status.UNIMPLEMENTED,
201+
`Unimplemented method for request: ${message.messageRequest}`,
202+
);
201203
}
202204
} catch (e) {
203205
if (e instanceof ReflectionError) {
@@ -315,20 +317,26 @@ export class ReflectionV1Implementation {
315317
};
316318
}
317319

318-
private getFileDependencies(
319-
file: FileDescriptorProto,
320-
visited: Set<FileDescriptorProto> = new Set(),
321-
): FileDescriptorProto[] {
322-
const newVisited = visited.add(file);
320+
private getFileDependencies(file: FileDescriptorProto): FileDescriptorProto[] {
321+
const visited: Set<FileDescriptorProto> = new Set();
322+
const toVisit: FileDescriptorProto[] = file.getDependencyList().map((dep) => this.fileNameIndex[dep]);
323323

324-
const directDeps = file.getDependencyList().map((dep) => this.fileNameIndex[dep]);
325-
const transitiveDeps = directDeps
326-
.filter((dep) => !newVisited.has(dep))
327-
.map((dep) => this.getFileDependencies(dep, newVisited))
328-
.flat();
324+
while (toVisit.length > 0) {
325+
const current = toVisit.pop();
329326

330-
const allDeps = [...directDeps, ...transitiveDeps];
327+
if (!current || visited.has(current)) {
328+
continue;
329+
}
331330

332-
return [...new Set(allDeps)];
331+
visited.add(current);
332+
toVisit.push(
333+
...current.getDependencyList()
334+
.map((dep) => this.fileNameIndex[dep])
335+
.filter((dep) => !visited.has(dep))
336+
);
337+
}
338+
339+
return Array.from(visited);
333340
}
341+
334342
}

0 commit comments

Comments
 (0)