如何将已认证GitHub会话传入语言服务器并跟踪管理?
实现语言服务器获取GitHub认证会话并内存跟踪
一、客户端传递认证信息到服务器
有两种实用方式将认证会话传给语言服务器:
1. 启动服务器时通过初始化参数传递
客户端在配置服务器启动选项时,把已获取的GitHub认证token放入initializationOptions,服务器在初始化阶段接收:
// 客户端VS Code扩展代码 import * as vscode from 'vscode'; import * as path from 'path'; export async function activate(context: vscode.ExtensionContext) { // 调用VS Code认证API获取GitHub会话 const githubSession = await vscode.authentication.getSession('github', ['repo'], { createIfNone: false }); const serverModule = context.asAbsolutePath(path.join('out', 'server', 'server.js')); const serverOptions: vscode.LanguageServerOptions = { run: { module: serverModule }, debug: { module: serverModule, options: { execArgv: ['--nolazy', '--inspect=6009'] } } }; const clientOptions: vscode.LanguageClientOptions = { documentSelector: [{ scheme: 'file', language: 'your-language' }], // 携带认证信息到初始化参数 initializationOptions: { githubAuth: { token: githubSession?.accessToken } } }; const client = new vscode.LanguageClient('yourLanguageServer', 'Your Language Server', serverOptions, clientOptions); client.start(); context.subscriptions.push(client); }
2. 运行时通过自定义请求传递
如果认证是在服务器启动后完成的,客户端可发送自定义LSP请求传递token:
// 客户端代码 client.sendRequest('$/setGitHubAuth', { token: githubSession.accessToken, rootUri: vscode.workspace.workspaceFolders?.[0].uri.toString() });
二、服务器端接收并内存存储会话
服务器在内存中维护会话,支持多workspace场景:
// 语言服务器代码 import { createConnection, InitializeParams, InitializeResult } from 'vscode-languageserver/node'; const connection = createConnection(); // 用Map关联workspace根URI与认证token,避免多workspace会话混淆 const githubSessions = new Map<string, string>(); // 处理初始化请求,获取启动时的认证信息 connection.onInitialize((params: InitializeParams): InitializeResult => { const githubAuth = params.initializationOptions?.githubAuth; if (githubAuth?.token && params.rootUri) { githubSessions.set(params.rootUri, githubAuth.token); } return { capabilities: { completionProvider: { resolveProvider: true }, diagnosticProvider: { interFileDependencies: false, workspaceDiagnostics: false }, documentSymbolProvider: true } }; }); // 处理自定义设置认证的请求 connection.onRequest('$/setGitHubAuth', (params: { token: string, rootUri?: string }) => { const targetUri = params.rootUri || connection.workspace.rootUri; if (targetUri) { githubSessions.set(targetUri, params.token); return { success: true }; } return { success: false, reason: 'No workspace root URI provided' }; }); // 辅助函数:根据文档URI获取对应workspace的认证token function getGitHubToken(documentUri: string): string | undefined { // 简化逻辑:直接使用当前workspace根URI匹配,实际可根据文档路径做更精准关联 const rootUri = connection.workspace.rootUri; return rootUri ? githubSessions.get(rootUri) : undefined; }
三、在服务器功能中使用认证会话
在诊断、代码补全、文档符号等逻辑中,直接调用getGitHubToken获取会话,请求GitHub API:
// 示例:代码补全中使用GitHub会话 connection.onCompletion(async (params) => { const token = getGitHubToken(params.textDocument.uri); if (!token) { // 无认证时返回空补全或提示用户完成认证 return { items: [] }; } // 携带token请求GitHub API获取数据 const apiResponse = await fetch('https://api.github.com/repos/your-org/your-repo/contents', { headers: { Authorization: `token ${token}` } }); const repoContents = await apiResponse.json(); // 转换为LSP补全项 const completionItems = repoContents.map((item: any) => ({ label: item.name, kind: item.type === 'dir' ? 4 : 1 // 对应文件夹/文件的补全类型 })); return { items: completionItems }; });
注意事项
- 内存存储特性:会话仅保存在服务器内存中,服务器重启后会丢失,需客户端重新传递(符合你的需求)。
- 多workspace隔离:通过
Map关联workspace根URI与token,避免不同项目的会话互相干扰。 - 安全性:LSP通信为本地进程间通信,token传递无需额外加密,不要将token持久化到磁盘。
内容的提问来源于stack exchange,提问作者GabeV
相关产品推荐
相关产品推荐

