Merge branch 'main' into ihrpr/resume-long-running-requests

This commit is contained in:
ihrpr 2025-04-15 22:10:58 +01:00
commit f9f2ba4717
No known key found for this signature in database
2 changed files with 76 additions and 23 deletions

View file

@ -23,6 +23,7 @@ import {
ServerCapabilities,
} from "../types.js";
import { Transport, TransportSendOptions } from "./transport.js";
import { AuthInfo } from "../server/auth/types.js";
/**
* Callback for progress notifications.
@ -104,6 +105,11 @@ export type RequestHandlerExtra<SendRequestT extends Request,
*/
signal: AbortSignal;
/**
* Information about a validated access token, provided to request handlers.
*/
authInfo?: AuthInfo;
/**
* The session ID from the transport, if available.
*/
@ -269,11 +275,11 @@ export abstract class Protocol<
this._onerror(error);
};
this._transport.onmessage = (message) => {
this._transport.onmessage = (message, extra) => {
if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
this._onresponse(message);
} else if (isJSONRPCRequest(message)) {
this._onrequest(message);
this._onrequest(message, extra);
} else if (isJSONRPCNotification(message)) {
this._onnotification(message);
} else {
@ -321,7 +327,7 @@ export abstract class Protocol<
);
}
private _onrequest(request: JSONRPCRequest): void {
private _onrequest(request: JSONRPCRequest, extra?: { authInfo?: AuthInfo }): void {
const handler =
this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
@ -346,20 +352,20 @@ export abstract class Protocol<
const abortController = new AbortController();
this._requestHandlerAbortControllers.set(request.id, abortController);
// Create extra object with both abort signal and sessionId from transport
const extra: RequestHandlerExtra<SendRequestT, SendNotificationT> = {
const fullExtra: RequestHandlerExtra<SendRequestT, SendNotificationT> = {
signal: abortController.signal,
sessionId: this._transport?.sessionId,
sendNotification:
(notification) =>
this.notification(notification, { relatedRequestId: request.id }),
sendRequest: (r, resultSchema, options?) =>
this.request(r, resultSchema, { ...options, relatedRequestId: request.id })
this.request(r, resultSchema, { ...options, relatedRequestId: request.id }),
authInfo: extra?.authInfo,
};
// Starting with Promise.resolve() puts any synchronous errors into the monad as well.
Promise.resolve()
.then(() => handler(request, extra))
.then(() => handler(request, fullExtra))
.then(
(result) => {
if (abortController.signal.aborted) {

View file

@ -1,3 +1,4 @@
import { AuthInfo } from "../server/auth/types.js";
import { JSONRPCMessage, RequestId } from "../types.js";
/**
@ -64,8 +65,11 @@ export interface Transport {
/**
* Callback for when a message (request or response) is received over the connection.
*
* Includes the authInfo if the transport is authenticated.
*
*/
onmessage?: (message: JSONRPCMessage) => void;
onmessage?: (message: JSONRPCMessage, extra?: { authInfo?: AuthInfo }) => void;
/**
* The session ID generated for this connection.