graphql-yoga
Version:
<div align="center"><img src="https://raw.githubusercontent.com/graphql-hive/graphql-yoga/refs/heads/main/website/public/cover.png" width="720" /></div>
78 lines (77 loc) • 2.76 kB
JavaScript
import { createGraphQLError } from '@graphql-tools/utils';
import { handleMaybePromise } from '@whatwg-node/promise-helpers';
import { isContentTypeMatch } from './utils.js';
export function isPOSTMultipartRequest(request) {
return request.method === 'POST' && isContentTypeMatch(request, 'multipart/form-data');
}
export function parsePOSTMultipartRequest(request) {
return handleMaybePromise(() => request.formData(), (requestBody) => {
const operationsStr = requestBody.get('operations');
if (!operationsStr) {
throw createGraphQLError('Missing multipart form field "operations"');
}
if (typeof operationsStr !== 'string') {
throw createGraphQLError('Multipart form field "operations" must be a string');
}
let operations;
try {
operations = JSON.parse(operationsStr);
}
catch {
throw createGraphQLError('Multipart form field "operations" must be a valid JSON string');
}
const mapStr = requestBody.get('map');
if (mapStr != null) {
if (typeof mapStr !== 'string') {
throw createGraphQLError('Multipart form field "map" must be a string');
}
let map;
try {
map = JSON.parse(mapStr);
}
catch {
throw createGraphQLError('Multipart form field "map" must be a valid JSON string');
}
for (const fileIndex in map) {
const file = requestBody.get(fileIndex);
const keys = map[fileIndex];
for (const key of keys) {
setObjectKeyPath(operations, key, file);
}
}
}
return operations;
}, e => {
if (e instanceof Error && e.message.startsWith('File size limit exceeded: ')) {
throw createGraphQLError(e.message, {
extensions: {
http: {
status: 413,
},
},
});
}
throw e;
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function setObjectKeyPath(object, keyPath, value) {
const keys = keyPath.split('.');
let current = object;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
return;
}
const isLastKey = i === keys.length - 1;
if (isLastKey) {
current[key] = value;
}
else {
if (!(key in current)) {
current[key] = {};
}
current = current[key];
}
}
}