discord-api-docs
discord-api-docs copied to clipboard
Responding to an interaction received via webhook fails if the response is bigger than 150kb
Description
Responding to an interaction received via webhook directly with a multipart/form-data file upload causes "This interaction failed" when uploading a 160kb file, but works when uploading a 150kb file.
I have tested with multiple file types including images, text and binary, with and without content-length, changed keepalive timeout headers, boundary encoding...
I am unsure at which exact size the issue starts, but somewhere between 150kb and 160kb the responses start failing. I believe this is not caused by the 3 second rule, as that would show "This interaction did not respond" instead plus the 160kb test fails 100% of the time while the 150kb test works 99% of the time, which cant be explained by network/upload lag.
ignoring the webhook and calling the /callback endpoint instead works as expected. responding to the webhook with a type 5 (defer response) and then editing or following up also works as expected.
Steps to Reproduce
on interaction webhook received, i respond with the following content:
HTTP/1.1 200 OK
Content-Type: multipart/form-data; boundary=e944dac9857d54f659308490be19fe59
Date: Wed, 27 Jul 2022 12:29:35 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Transfer-Encoding: chunked
--e944dac9857d54f659308490be19fe59
Content-Disposition: form-data; name="files[0]"; filename="test.bin"
Content-Type: application/octet-stream
[bytes here]
--e944dac9857d54f659308490be19fe59
Content-Disposition: form-data; name="payload_json"
Content-Type: application/json
{"type":4,"data":{"embeds":[{"title":"hello","description":"world","color":11908533}]}}
--e944dac9857d54f659308490be19fe59--
if [bytes here] contains 150k bytes the response works as expected, however when i do the exact same response with 160k bytes, it instantly causes "this interaction failed".
if i do not respond to the webhook interaction and instead call the /callback endpoint then it works as expected with both 150kb and 160kb. example /callback call:
POST /api/v10/interactions/[interaction.id]/[interaction.token]/callback HTTP/1.1
Content-Type: multipart/form-data; boundary=151a12fd1c1d2d6f4aa844dc40e4a0be
Host: discord.com
Connection: keep-alive
Transfer-Encoding: chunked
--151a12fd1c1d2d6f4aa844dc40e4a0be
Content-Disposition: form-data; name="files[0]"; filename="test.bin"
Content-Type: application/octet-stream
[bytes here]
--151a12fd1c1d2d6f4aa844dc40e4a0be
Content-Disposition: form-data; name="payload_json"
Content-Type: application/json
{"type":4,"data":{"embeds":[{"title":"hello","description":"world","color":11908533}]}}
--151a12fd1c1d2d6f4aa844dc40e4a0be--
Expected Behavior
Allow larger files like the /callback endpoint (provided the server is capable of uploading them fast enough) or document that responses to webhook interactions have additional size limitations besides the 3 second rule
Current Behavior
responding to a webhook interaction with a 160kb file instantly causes "This interaction failed"
Screenshots/Videos
No response
Client and System Information
node 16.13 on repl.it (for the ssl) using core node modules http.Server for webhook interactions and https.request for the /callback test
sample server code excluding signature validation and ping handling:
onRequest(req, res) {
req.on("end", () => {
const boundary = randomBytes(16).toString("hex");
const files = [{
name: "test.bin",
type: "application/octet-stream",
data: Buffer.from("a".repeat(160000)) // 160000 fails, 150000 works
}]
const payload = {
type: 4,
data: {
embeds: [{
title: "hello",
description: "world",
color: 11908533
}]
}
}
res.writeHead(200, { "Content-Type": `multipart/form-data; boundary=${boundary}` });
for (let i = 0; i < files.length; i++) {
const file = files[i];
const type = typeof file.type === "string" ? `\r\nContent-Type: ${file.type}` : "";
res.write(`\r\n--${boundary}\r\nContent-Disposition: form-data; name="files[${i}]"; filename="${file.name}"${type}\r\n\r\n`);
res.write(file.data);
}
res.write(`\r\n--${boundary}\r\nContent-Disposition: form-data; name="payload_json"\r\nContent-Type: application/json\r\n\r\n${ JSON.stringify(payload)}`);
res.end(`\r\n--${boundary}--`);
});
}
Sorry, we don't plan to update support for this anytime soon.