Files
discord.js/packages/proxy/src/handlers/proxyRequests.ts
Lioness100 1ba1f238f0 docs: fix typos (#9127)
* docs: fix typos

* indicies -> indices

* rename file

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-02-17 20:07:38 +00:00

70 lines
2.3 KiB
TypeScript

import { URL } from 'node:url';
import {
DiscordAPIError,
HTTPError,
RateLimitError,
type RequestMethod,
type REST,
type RouteLike,
} from '@discordjs/rest';
import {
populateAbortErrorResponse,
populateGeneralErrorResponse,
populateSuccessfulResponse,
populateRatelimitErrorResponse,
} from '../util/responseHelpers.js';
import type { RequestHandler } from '../util/util';
/**
* Creates an HTTP handler used to forward requests to Discord
*
* @param rest - REST instance to use for the requests
*/
export function proxyRequests(rest: REST): RequestHandler {
return async (req, res) => {
const { method, url } = req;
if (!method || !url) {
throw new TypeError(
'Invalid request. Missing method and/or url, implying that this is not a Server IncomingMessage',
);
}
// The 2nd parameter is here so the URL constructor doesn't complain about an "invalid url" when the origin is missing
// we don't actually care about the origin and the value passed is irrelevant
const parsedUrl = new URL(url, 'http://noop');
// eslint-disable-next-line unicorn/no-unsafe-regex, prefer-named-capture-group
const fullRoute = parsedUrl.pathname.replace(/^\/api(\/v\d+)?/, '') as RouteLike;
try {
const discordResponse = await rest.raw({
body: req,
fullRoute,
// This type cast is technically incorrect, but we want Discord to throw Method Not Allowed for us
method: method as RequestMethod,
passThroughBody: true,
query: parsedUrl.searchParams,
headers: {
'Content-Type': req.headers['content-type']!,
},
});
await populateSuccessfulResponse(res, discordResponse);
} catch (error) {
if (error instanceof DiscordAPIError || error instanceof HTTPError) {
populateGeneralErrorResponse(res, error);
} else if (error instanceof RateLimitError) {
populateRatelimitErrorResponse(res, error);
} else if (error instanceof Error && error.name === 'AbortError') {
populateAbortErrorResponse(res);
} else {
// Unclear if there's better course of action here for unknown errors. Any web framework allows to pass in an error handler for something like this
// at which point the user could dictate what to do with the error - otherwise we could just 500
throw error;
}
} finally {
res.end();
}
};
}