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

userAgentAppendix appended multiple times to REST user-agent header each time WebhookClient is instantiated #9421

Closed
cycloptux opened this issue Apr 19, 2023 · 4 comments · Fixed by #9425

Comments

@cycloptux
Copy link
Contributor

cycloptux commented Apr 19, 2023

Which package is this bug report for?

discord.js

Issue description

The PR #9267 introduced an unexpected behavior when instantiating a new WebhookClient, which extends BaseClient, specifying the userAgentAppendix.

Specifically, this part of the BaseClient initiation:

if (options.rest?.userAgentAppendix) {
// Merging the default options when a custom user agent appendix is supplied
// Replaces the discord.js string. Enforce it.
options.rest.userAgentAppendix = `${Options.userAgentAppendix} ${options.rest.userAgentAppendix}`;
}

edits the original options.rest.userAgentAppendix prepending Options.userAgentAppendix. This is fine when instantiating a single Client, but poses problems when instantiating multiple WebhookClients after the initial initiation since the userAgentAppendix value gets longer and longer each time a new WebhookClient() is called, to the point where Discord starts returning 400 errors when sending webhooks through any newly instantiated WebhookClient.

This could be solved by deep cloning options before running:

/**
* The options the client was instantiated with
* @type {ClientOptions}
*/
this.options = mergeDefault(Options.createDefault(), options);

and then moving the above assignment after the deep clone, applied to this.options, but deep cloning though JSON.parse/JSON.stringify and structuredClone breaks complex properties of the rest object, e.g. a custom agent.

Code sample

const clientOptions = { rest: { userAgentAppendix: "loremIpsum/1.0.0" } };
while (true) {
    const webhookClient = new WebhookClient({ url: "https://discord.com/api/..." }, clientOptions);
    console.log(webhookClient.options.rest.userAgentAppendix);
    // userAgentAppendix - and consequently the "user-agent" header - will progressively get bigger: discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 discord.js/14.9.0 Node.js/v18.16.0 [...] discord.js/14.9.0 Node.js/v18.16.0 loremIpsum/1.0.0
}

Package version

14.9.0

Node.js version

18.16.0

Operating system

No response

Priority this issue should have

Medium (should be fixed soon)

Which partials do you have configured?

Not applicable (subpackage bug)

Which gateway intents are you subscribing to?

Not applicable (subpackage bug)

I have tested this issue on a development release

No response

@Jiralite
Copy link
Member

Hi, thank you for the report.

I copied your code sample and I am monitoring the requests via Undici:

import diagnosticsChannel from "node:diagnostics_channel";
import { WebhookClient } from "discord.js";

diagnosticsChannel.channel("undici:request:create").subscribe(({ request }) => {
	console.log(request.headers); // Log the headers.
});

while (true) {
	const webhookClient = new WebhookClient(
		{ url: "https://discord.com/api/..." },
		{ rest: { userAgentAppendix: "loremIpsum/1.0.0" } },
	);

	await webhookClient.send("Hello there");
}

The diagnostics channel is reporting the same user agent for each request (on 14.9.0 and ecd1b5d):

Content-Type: application/json
User-Agent: DiscordBot (https://discord.js.org, 1.7.0) discord.js/14.9.0 Node.js/v19.6.0 loremIpsum/1.0.0

Content-Type: application/json
User-Agent: DiscordBot (https://discord.js.org, 1.7.0) discord.js/14.9.0 Node.js/v19.6.0 loremIpsum/1.0.0

Content-Type: application/json
User-Agent: DiscordBot (https://discord.js.org, 1.7.0) discord.js/14.9.0 Node.js/v19.6.0 loremIpsum/1.0.0

Content-Type: application/json
User-Agent: DiscordBot (https://discord.js.org, 1.7.0) discord.js/14.9.0 Node.js/v19.6.0 loremIpsum/1.0.0

Content-Type: application/json
User-Agent: DiscordBot (https://discord.js.org, 1.7.0) discord.js/14.9.0 Node.js/v19.6.0 loremIpsum/1.0.0

Content-Type: application/json
User-Agent: DiscordBot (https://discord.js.org, 1.7.0) discord.js/14.9.0 Node.js/v19.6.0 loremIpsum/1.0.0

Content-Type: application/json
User-Agent: DiscordBot (https://discord.js.org, 1.7.0) discord.js/14.9.0 Node.js/v19.6.0 loremIpsum/1.0.0

I seem to not be able to reproduce this. Is there any other missing information, or perhaps the code sample was malformed?

@cycloptux
Copy link
Contributor Author

You are right, the example code was malformed. The point of the bug is that the options object is edited on each iteration, passing a plain object created a clean situation each time.
Try again with the example in the first post and you should see it. You don't even have to send the message, you can just check the userAgentAppendix option.

@Jiralite
Copy link
Member

I see the mutation crystal clear now. Thank you!

Try again with the example in the first post and you should see it. You don't even have to send the message, you can just check the userAgentAppendix option.

I think you might need to move clientOptions outside of the while() loop!

@cycloptux
Copy link
Contributor Author

Done and thanks!

@kodiakhq kodiakhq bot closed this as completed in #9425 Apr 28, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 28, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants