server/utils/request.ts

97 lines
2.7 KiB
TypeScript
Raw Normal View History

2023-09-15 03:22:27 +02:00
/**
* Takes a request, and turns FormData or query parameters
* into a JSON object as would be returned by req.json()
* This is a translation layer that allows clients to use
* either FormData, query parameters, or JSON in the request
* @param request The request to parse
*/
/* export async function parseRequest<T>(request: Request): Promise<Partial<T>> {
2023-09-15 03:22:27 +02:00
const query = new URL(request.url).searchParams;
2023-11-26 22:54:20 +01:00
let output: Partial<T> = {};
2023-09-15 03:22:27 +02:00
2023-09-23 04:46:52 +02:00
// Parse SearchParams arrays into JSON arrays
const arrayKeys = [...query.keys()].filter(key => key.endsWith("[]"));
2023-11-26 23:46:15 +01:00
const nonArrayKeys = [...query.keys()].filter(key => !key.endsWith("[]"));
2023-09-23 04:46:52 +02:00
for (const key of arrayKeys) {
const value = query.getAll(key);
query.delete(key);
query.append(key, JSON.stringify(value));
}
2023-11-26 23:46:15 +01:00
// Append non array keys to output
for (const key of nonArrayKeys) {
// @ts-expect-error Complains about type
output[key] = query.get(key);
}
2023-11-26 22:54:20 +01:00
const queryEntries = [...query.entries()];
if (queryEntries.length > 0) {
const data: Record<string, string | string[]> = {};
const arrayKeys = [...query.keys()].filter(key => key.endsWith("[]"));
for (const key of arrayKeys) {
const value = query.getAll(key);
query.delete(key);
// @ts-expect-error JSON arrays are valid
data[key] = JSON.parse(value);
}
output = {
...output,
...(data as T),
};
2023-11-12 09:28:06 +01:00
}
2023-09-15 03:22:27 +02:00
// if request contains a JSON body
if (request.headers.get("Content-Type")?.includes("application/json")) {
2023-11-26 22:54:20 +01:00
try {
output = {
...output,
...((await request.json()) as T),
};
} catch {
// Invalid JSON
}
2023-09-15 03:22:27 +02:00
}
// If request contains FormData
if (request.headers.get("Content-Type")?.includes("multipart/form-data")) {
// @ts-expect-error It hates entries() for some reason
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
2023-11-26 22:54:20 +01:00
const formData = [...(await request.formData()).entries()];
2023-09-22 03:09:14 +02:00
2023-11-26 22:54:20 +01:00
if (formData.length > 0) {
2023-09-15 03:22:27 +02:00
const data: Record<string, string | File> = {};
2023-11-26 22:54:20 +01:00
for (const [key, value] of formData) {
2023-09-15 03:22:27 +02:00
// If object, parse as JSON
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-base-to-string, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
2023-09-15 03:22:27 +02:00
data[key] = JSON.parse(value.toString());
} catch {
// If a file, set as a file
if (value instanceof File) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
2023-09-15 03:22:27 +02:00
data[key] = value;
} else {
// Otherwise, set as a string
// eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
data[key] = value.toString();
2023-09-15 03:22:27 +02:00
}
}
}
2023-11-26 22:54:20 +01:00
output = {
...output,
...(data as T),
};
2023-09-15 03:22:27 +02:00
}
}
2023-11-26 22:54:20 +01:00
return output;
2023-09-15 03:22:27 +02:00
}
*/