No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

multipart.js 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.parseObjectUploadMultipartRequest = void 0;
  4. const LINE_SEPARATOR = `\r\n`;
  5. function splitBufferByDelimiter(buffer, delimiter, maxResults = -1) {
  6. let offset = 0;
  7. let nextDelimiterIndex = buffer.indexOf(delimiter, offset);
  8. const bufferParts = [];
  9. while (nextDelimiterIndex !== -1) {
  10. if (maxResults === 0) {
  11. return bufferParts;
  12. }
  13. else if (maxResults === 1) {
  14. bufferParts.push(Buffer.from(buffer.slice(offset)));
  15. return bufferParts;
  16. }
  17. bufferParts.push(Buffer.from(buffer.slice(offset, nextDelimiterIndex)));
  18. offset = nextDelimiterIndex + delimiter.length;
  19. nextDelimiterIndex = buffer.indexOf(delimiter, offset);
  20. maxResults -= 1;
  21. }
  22. bufferParts.push(Buffer.from(buffer.slice(offset)));
  23. return bufferParts;
  24. }
  25. function parseMultipartRequestBody(boundaryId, body) {
  26. const cleanBoundaryId = boundaryId.replace(/^["'](.+(?=["']$))["']$/, "$1");
  27. const boundaryString = `--${cleanBoundaryId}`;
  28. const bodyParts = splitBufferByDelimiter(body, boundaryString).map((buf) => {
  29. return Buffer.from(buf.slice(2));
  30. });
  31. const parsedParts = [];
  32. for (const bodyPart of bodyParts.slice(1, bodyParts.length - 1)) {
  33. parsedParts.push(parseMultipartRequestBodyPart(bodyPart));
  34. }
  35. return parsedParts;
  36. }
  37. function parseMultipartRequestBodyPart(bodyPart) {
  38. const sections = splitBufferByDelimiter(bodyPart, LINE_SEPARATOR, 3);
  39. const contentTypeRaw = sections[0].toString().toLowerCase();
  40. if (!contentTypeRaw.startsWith("content-type: ")) {
  41. throw new Error(`Failed to parse multipart request body part. Missing content type.`);
  42. }
  43. const dataRaw = Buffer.from(sections[2]).slice(0, sections[2].byteLength - LINE_SEPARATOR.length);
  44. return { contentTypeRaw, dataRaw };
  45. }
  46. function parseObjectUploadMultipartRequest(contentTypeHeader, body) {
  47. if (!contentTypeHeader.startsWith("multipart/related")) {
  48. throw new Error(`Bad content type. ${contentTypeHeader}`);
  49. }
  50. const boundaryId = contentTypeHeader.split("boundary=")[1];
  51. if (!boundaryId) {
  52. throw new Error(`Bad content type. ${contentTypeHeader}`);
  53. }
  54. const parsedBody = parseMultipartRequestBody(boundaryId, body);
  55. if (parsedBody.length !== 2) {
  56. throw new Error(`Unexpected number of parts in request body`);
  57. }
  58. return {
  59. metadataRaw: parsedBody[0].dataRaw.toString(),
  60. dataRaw: Buffer.from(parsedBody[1].dataRaw),
  61. };
  62. }
  63. exports.parseObjectUploadMultipartRequest = parseObjectUploadMultipartRequest;