Since yesterday, I’ve been getting the following error returned from CloudFront when attempting to subscribe to events via EventSub:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>400 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Bad request.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: -TSEMQNPYUCSKqXaVPLcIpz2qjVbEZeYcq0CjQJyb9saJPLQQh1RGA==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>
I’m running this in NodeJS using NGROK to handle the SSL stuff so I can keep the bot local. After every stream I unsubscribe from all events so I don’t waste resources and subscribe again for new streams. Here’s the area of code throwing the error with a comment on the appropriate line:
app.post('/createWebhook', (request, response) => {
let createWebhookParameters = {
host: "api.twitch.tv",
path: "helix/eventsub/subscriptions",
method: 'POST',
headers: {
"Content-Type": "application/json",
"Client-ID": configuration.API_KEY,
"Authorization": "Bearer " + access_token
}
};
let createWebhookBody = {
...eventTypesConfig[request.query.eventType],
"transport": {
"method": "webhook",
"callback": ngrokURL + "/twitchwebhooks/callback",
"secret": configuration.TWITCH_SIGNING_SECRET
}
};
let responseData = "";
let webhookRequest = https.request(createWebhookParameters, (result) => {
result.setEncoding('utf8');
result.on('data', function (data) {
responseData = responseData + data;
console.log(responseData);
}).on('end', function (_result) {
try {
let responseBody = JSON.parse(responseData); // <--- This is expecting JSON but receiving the HTML error
response.send(responseBody);
}
catch (error) {
console.log(error);
}
})
});
webhookRequest.on('error', (error) => {
console.log(error);
});
webhookRequest.write(JSON.stringify(createWebhookBody));
webhookRequest.end();
});
I’ve been using this code for a few years now with no issues. I’ve looked to see if EventSub has been updated and see nothing unusual. I’ve updated my local self-signed certificates in case they expired. No core functionality has changed. Am I missing something new? What should I try next?
Some new information. Last night after stream, I noticed a new error in relation to this that might help with troubleshooting:
Error: 50630000:error:0A000119:SSL routines:ssl3_get_record:decryption failed or bad record mac:c:\ws\deps\openssl\openssl\ssl\record\ssl3_record.c:623:
This is making me wonder if something is off with my self-signed certificate, but it worked fine before and I’ve already tried generating a new one. I’ll keep researching while waiting for a potential response here. Hope y’all are having an excellent day!
Considering it works in CURL, why does it break in my code when it worked just fine before? I’ve made no changes to the connection functionality. Thank you for your help!
This sounds like your program is using a different build of curl and/or it’s selections of certs and/or not using the onboard system curl to make requests.
After pursuing ginovva320’s question and discovering how to make a connection with CURL, I decided to try shifting my connection logic to Axios instead of pure JavaScript to see what would happen and it correctly subscribes to events using Axios. The relevant code that’s currently working for me is below in case anyone faces the same problem:
While I’m glad it’s connecting again, I’d still love to know why my original code no longer works after being unchanged and functional for about two years. If anyone has ideas on that, I’d be eager to hear them both for my own learning as well as anyone else’s.
Thanks again! If this continues to work for my next stream or two, I’ll mark this post as the solution.
This sounds like your program is using a different build of curl and/or it’s selections of certs and/or not using the onboard system curl to make requests.
Interesting. I didn’t know you could have different builds of CURL running simultaneously. How can I see what my program is using vs the system?
Why axios when fetch is built in (to both browsers and nodeJS)?
Since you used pure https.request it probably doesn’t know where to look for the certification bundle, and it’s not in the default place or even the onboard/built in to your OS stuff. Or you didn’t update node and the certs that remote are using cannot be verfified by your system, or remote uses new certificate types that your node doesn’t understand.
Really, force of habit from building projects prior to fetch being implemented natively into Node. That, and I kind of forgot it was, in fact, natively implemented later. I should probably move everything to fetch sooner or later to save having an extra npm package
Great point! What gets me is why it worked just fine one day and not the next. Perhaps the CA store default was switched in a Node update or something? Regardless, you reminded me to add my self-signed certificates to Windows, as I’m pretty sure I forgot that when setting up my current rig. Thank you, sir, and for the additional information! You’re a legend!
As far as what happened, we are always making changes and updates in the background. My guess is that an update to the TLS security policy of our CDN was incompatible with your local node setup. I’m sure Barry’s on the right track with it being cert bundle related.