fix: refine stacktrace attribution of errors thrown from middleware (#21470)
* Refine middleware types to include the method signature and to express the nullability of the middleware. * Make sure that the stacktrace does not involve middleware unless the error originated from the middleware itself. Co-authored-by: steveluscher <github@steveluscher.com>
This commit is contained in:
parent
88ef24cecb
commit
d36ff8d978
|
@ -760,19 +760,24 @@ function createRpcClient(
|
||||||
agentManager = new AgentManager(useHttps);
|
agentManager = new AgentManager(useHttps);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fetchWithMiddleware: (url: string, options: any) => Promise<Response>;
|
let fetchWithMiddleware:
|
||||||
|
| ((url: string, options: any) => Promise<Response>)
|
||||||
|
| undefined;
|
||||||
|
|
||||||
if (fetchMiddleware) {
|
if (fetchMiddleware) {
|
||||||
fetchWithMiddleware = (url: string, options: any) => {
|
fetchWithMiddleware = async (url: string, options: any) => {
|
||||||
return new Promise<Response>((resolve, reject) => {
|
const modifiedFetchArgs = await new Promise<[string, any]>(
|
||||||
fetchMiddleware(url, options, async (url: string, options: any) => {
|
(resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
resolve(await fetch(url, options));
|
fetchMiddleware(url, options, (modifiedUrl, modifiedOptions) =>
|
||||||
|
resolve([modifiedUrl, modifiedOptions]),
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
});
|
);
|
||||||
|
return await fetch(...modifiedFetchArgs);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1972,7 +1977,7 @@ export type HttpHeaders = {[header: string]: string};
|
||||||
export type FetchMiddleware = (
|
export type FetchMiddleware = (
|
||||||
url: string,
|
url: string,
|
||||||
options: any,
|
options: any,
|
||||||
fetch: Function,
|
fetch: (modifiedUrl: string, modifiedOptions: any) => void,
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -133,6 +133,35 @@ describe('Connection', () => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it('should attribute middleware fatals to the middleware', async () => {
|
||||||
|
let connection = new Connection(url, {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
fetchMiddleware: (_url, _options, _fetch) => {
|
||||||
|
throw new Error('This middleware experienced a fatal error');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const error = await expect(connection.getVersion()).to.be.rejectedWith(
|
||||||
|
'This middleware experienced a fatal error',
|
||||||
|
);
|
||||||
|
expect(error)
|
||||||
|
.to.be.an.instanceOf(Error)
|
||||||
|
.and.to.have.property('stack')
|
||||||
|
.that.include('fetchMiddleware');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not attribute fetch errors to the middleware', async () => {
|
||||||
|
let connection = new Connection(url, {
|
||||||
|
fetchMiddleware: (url, _options, fetch) => {
|
||||||
|
fetch(url, 'An `Object` was expected here; this is a `TypeError`.');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const error = await expect(connection.getVersion()).to.be.rejected;
|
||||||
|
expect(error)
|
||||||
|
.to.be.an.instanceOf(Error)
|
||||||
|
.and.to.have.property('stack')
|
||||||
|
.that.does.not.include('fetchMiddleware');
|
||||||
|
});
|
||||||
|
|
||||||
it('get account info - not found', async () => {
|
it('get account info - not found', async () => {
|
||||||
const account = Keypair.generate();
|
const account = Keypair.generate();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue