Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discord API REST response body access #10240

Open
DEVTomatoCake opened this issue May 2, 2024 · 1 comment
Open

Discord API REST response body access #10240

DEVTomatoCake opened this issue May 2, 2024 · 1 comment

Comments

@DEVTomatoCake
Copy link

DEVTomatoCake commented May 2, 2024

Which application or package is this feature request for?

rest

Feature

For debugging and logging purposes I want to be able to access the body the Discord REST API responded with after a request.

While I'm able to see the request body, e.g. using undicis diagnostic channel, or the response event of the REST client, I - as far as I know - cannot get the response body using it.

Ideal solution or implementation

Ideally, a REST event (e.g. responseBody) would be emitted once the parseResponse has finished parsing the response.

export async function parseResponse(res: ResponseLike): Promise<unknown> {
if (res.headers.get('Content-Type')?.startsWith('application/json')) {
return res.json();
}
return res.arrayBuffer();
}

The event should include the body itself and basic information about the response, like the headers, similar to the response event. This is useful to only log the application/json content type, and ignoring binary ones.

Alternative solutions or implementations

A REST client argument which can be used to replace the parseResponse function, allowing users to implement logging directly in the parsing function.

Other context

The response REST event already includes the cloned response as second parameter, however, calling <Response>.json() results in discord.js being unable to process the response:

/node_modules/discord.js/node_modules/@discordjs/rest/node_modules/undici/lib/api/readable.js:199
    throw new TypeError('unusable')
          ^
TypeError: unusable
    at consume (/node_modules/discord.js/node_modules/@discordjs/rest/node_modules/undici/lib/api/readable.js:199:11)
    at BodyReadable.json (/node_modules/discord.js/node_modules/@discordjs/rest/node_modules/undici/lib/api/readable.js:115:12)
    at Object.json (/node_modules/discord.js/node_modules/@discordjs/rest/dist/index.js:78:23)
    at parseResponse (/node_modules/discord.js/node_modules/@discordjs/rest/dist/index.js:269:16)
    at _REST.request (/node_modules/discord.js/node_modules/@discordjs/rest/dist/index.js:1267:12)

Originally asked in Logging API response body on the discord.js Discord.

@ckohen
Copy link
Member

ckohen commented May 2, 2024

The clone of the response object passed to the event is not guaranteed to have a useable body. If you're using the fetch strategy it will because it is calling res.clone() as you observed. However, undici.request does not return a Response object. djs will create a ResponseLike object which is why you can call .json at all. when using the undiciRequest strategy, the response passed is a shallow clone of this object.

Unfortunately, there's not a way to consume the body from the response event (when used with undiciRequest) without making it unuseable for the other consumer. We could pipe the stream to two passthroughs if you're listening to the event, but there's no guarantee that the one passed to the response event will get consumed then.

Passing only json responses seems not great for some use cases (though we'd probably name the event jsonBodyResponse or something), but honestly my main concern would be passing a shallow clone to that event, since that could end up with users mutating data unintentionally before it even gets to the main library parsing code. We could do a deep clone, though that would probably make the event unuseable for production debugging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants