mirror of https://github.com/grpc/grpc-node.git
refactor(grpc-reflection): simplified request handling and file dependency logic
This commit is contained in:
parent
89a5cbbdf4
commit
2449abe398
|
@ -26,7 +26,7 @@ export class ReflectionError extends Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Analyzes a gRPC server and exposes methods to reflect on it
|
/** Analyzes a gRPC package definition and exposes methods to reflect on it
|
||||||
*
|
*
|
||||||
* NOTE: the files returned by this service may not match the handwritten ones 1:1.
|
* NOTE: the files returned by this service may not match the handwritten ones 1:1.
|
||||||
* This is because proto-loader reorients files based on their package definition,
|
* This is because proto-loader reorients files based on their package definition,
|
||||||
|
@ -37,7 +37,7 @@ export class ReflectionError extends Error {
|
||||||
*/
|
*/
|
||||||
export class ReflectionV1Implementation {
|
export class ReflectionV1Implementation {
|
||||||
|
|
||||||
/** The full list of proto files (including imported deps) that the gRPC server includes */
|
/** The full list of proto files (including imported deps) that the gRPC package includes */
|
||||||
private readonly fileDescriptorSet = new FileDescriptorSet();
|
private readonly fileDescriptorSet = new FileDescriptorSet();
|
||||||
|
|
||||||
/** An index of proto files by file name (eg. 'sample.proto') */
|
/** An index of proto files by file name (eg. 'sample.proto') */
|
||||||
|
@ -172,32 +172,34 @@ export class ReflectionV1Implementation {
|
||||||
handleServerReflectionRequest(message: ServerReflectionRequest): ServerReflectionResponse {
|
handleServerReflectionRequest(message: ServerReflectionRequest): ServerReflectionResponse {
|
||||||
const response: ServerReflectionResponse = {
|
const response: ServerReflectionResponse = {
|
||||||
validHost: message.host,
|
validHost: message.host,
|
||||||
originalRequest: message,
|
originalRequest: message
|
||||||
fileDescriptorResponse: undefined,
|
|
||||||
allExtensionNumbersResponse: undefined,
|
|
||||||
listServicesResponse: undefined,
|
|
||||||
errorResponse: undefined,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (message.listServices !== undefined) {
|
switch(message.messageRequest) {
|
||||||
response.listServicesResponse = this.listServices(message.listServices);
|
case 'listServices':
|
||||||
} else if (message.fileContainingSymbol !== undefined) {
|
response.listServicesResponse = this.listServices(message.listServices || '');
|
||||||
response.fileDescriptorResponse = this.fileContainingSymbol(message.fileContainingSymbol);
|
break;
|
||||||
} else if (message.fileByFilename !== undefined) {
|
case 'fileContainingSymbol':
|
||||||
response.fileDescriptorResponse = this.fileByFilename(message.fileByFilename);
|
response.fileDescriptorResponse = this.fileContainingSymbol(message.fileContainingSymbol || '');
|
||||||
} else if (message.fileContainingExtension !== undefined) {
|
break;
|
||||||
response.fileDescriptorResponse = this.fileContainingExtension(
|
case 'fileByFilename':
|
||||||
message.fileContainingExtension?.containingType || '',
|
response.fileDescriptorResponse = this.fileByFilename(message.fileByFilename || '');
|
||||||
message.fileContainingExtension?.extensionNumber || -1
|
break;
|
||||||
);
|
case 'fileContainingExtension':
|
||||||
} else if (message.allExtensionNumbersOfType) {
|
response.fileDescriptorResponse = this.fileContainingExtension(
|
||||||
response.allExtensionNumbersResponse = this.allExtensionNumbersOfType(message.allExtensionNumbersOfType);
|
message.fileContainingExtension?.containingType || '',
|
||||||
} else {
|
message.fileContainingExtension?.extensionNumber || -1
|
||||||
throw new ReflectionError(
|
);
|
||||||
grpc.status.UNIMPLEMENTED,
|
break;
|
||||||
`Unimplemented method for request: ${message}`,
|
case 'allExtensionNumbersOfType':
|
||||||
);
|
response.allExtensionNumbersResponse = this.allExtensionNumbersOfType(message.allExtensionNumbersOfType || '');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ReflectionError(
|
||||||
|
grpc.status.UNIMPLEMENTED,
|
||||||
|
`Unimplemented method for request: ${message.messageRequest}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof ReflectionError) {
|
if (e instanceof ReflectionError) {
|
||||||
|
@ -315,20 +317,26 @@ export class ReflectionV1Implementation {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFileDependencies(
|
private getFileDependencies(file: FileDescriptorProto): FileDescriptorProto[] {
|
||||||
file: FileDescriptorProto,
|
const visited: Set<FileDescriptorProto> = new Set();
|
||||||
visited: Set<FileDescriptorProto> = new Set(),
|
const toVisit: FileDescriptorProto[] = file.getDependencyList().map((dep) => this.fileNameIndex[dep]);
|
||||||
): FileDescriptorProto[] {
|
|
||||||
const newVisited = visited.add(file);
|
|
||||||
|
|
||||||
const directDeps = file.getDependencyList().map((dep) => this.fileNameIndex[dep]);
|
while (toVisit.length > 0) {
|
||||||
const transitiveDeps = directDeps
|
const current = toVisit.pop();
|
||||||
.filter((dep) => !newVisited.has(dep))
|
|
||||||
.map((dep) => this.getFileDependencies(dep, newVisited))
|
|
||||||
.flat();
|
|
||||||
|
|
||||||
const allDeps = [...directDeps, ...transitiveDeps];
|
if (!current || visited.has(current)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
return [...new Set(allDeps)];
|
visited.add(current);
|
||||||
|
toVisit.push(
|
||||||
|
...current.getDependencyList()
|
||||||
|
.map((dep) => this.fileNameIndex[dep])
|
||||||
|
.filter((dep) => !visited.has(dep))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array.from(visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue