refactor(proxy): rely on auth header instead (#9422)

* refactor(proxy): rely on auth header instead

* chore: typo

* chore: language

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* chore: more language

Co-authored-by: Aura Román <kyradiscord@gmail.com>

* chore: more language nitpicks

Co-authored-by: ckohen <chaikohen@gmail.com>

* fix: unnecessary async

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Aura Román <kyradiscord@gmail.com>
Co-authored-by: ckohen <chaikohen@gmail.com>
This commit is contained in:
DD
2023-04-21 23:36:15 +03:00
committed by GitHub
parent 3e01f91bbb
commit a49ed0a2d5
4 changed files with 44 additions and 32 deletions

View File

@@ -1,18 +1,6 @@
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 { RequestMethod, REST, RouteLike } from '@discordjs/rest';
import { populateSuccessfulResponse, populateErrorResponse } from '../util/responseHelpers.js';
import type { RequestHandler } from '../util/util';
/**
@@ -36,29 +24,33 @@ export function proxyRequests(rest: REST): RequestHandler {
// eslint-disable-next-line unicorn/no-unsafe-regex, prefer-named-capture-group
const fullRoute = parsedUrl.pathname.replace(/^\/api(\/v\d+)?/, '') as RouteLike;
const headers: Record<string, string> = {
'Content-Type': req.headers['content-type']!,
};
if (req.headers.authorization) {
headers.authorization = req.headers.authorization;
}
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,
// We forward the auth header anyway
auth: false,
passThroughBody: true,
query: parsedUrl.searchParams,
headers: {
'Content-Type': req.headers['content-type']!,
},
headers,
});
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
const knownError = populateErrorResponse(res, error);
if (!knownError) {
// 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;
}

View File

@@ -1,6 +1,6 @@
import type { ServerResponse } from 'node:http';
import { pipeline } from 'node:stream/promises';
import type { DiscordAPIError, HTTPError, RateLimitError } from '@discordjs/rest';
import { DiscordAPIError, HTTPError, RateLimitError } from '@discordjs/rest';
import type { Dispatcher } from 'undici';
/**
@@ -59,3 +59,24 @@ export function populateAbortErrorResponse(res: ServerResponse): void {
res.statusCode = 504;
res.statusMessage = 'Upstream timed out';
}
/**
* Tries to populate a server response from an error object
*
* @param res - The server response to populate
* @param error - The error to check and use
* @returns - True if the error is known and the response object was populated, otherwise false
*/
export function populateErrorResponse(res: ServerResponse, error: unknown): boolean {
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 {
return false;
}
return true;
}