Skip to content

Instantly share code, notes, and snippets.

@DinoChiesa
Created February 9, 2026 22:10
Show Gist options
  • Select an option

  • Save DinoChiesa/d187c90774671e246a1edd251c2e67bb to your computer and use it in GitHub Desktop.

Select an option

Save DinoChiesa/d187c90774671e246a1edd251c2e67bb to your computer and use it in GitHub Desktop.
parse multipart/form-data in JavaScript, for Apigee X
function parseMultipartPart(part) {
var lines = part.split(/\r\n|\n/);
var name = null;
var value = [];
var state = 0;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
switch (state) {
case 0 /* awaiting content-disposition */:
{
var lowerCaseLine = line.toLowerCase();
if (lowerCaseLine.startsWith("content-disposition:")) {
var nameMatch = /name=\"([^\"]+)\"/.exec(line);
if (nameMatch && nameMatch.length > 1) {
name = nameMatch[1];
state = 1;
}
}
}
break;
case 1 /* awaiting end of headers */:
if (line.trim() === "") {
// Empty line, part content starts after this
state = 2;
}
break;
case 2 /* Reading part content */:
value.push(line);
break;
default:
throw new Error("parse error");
}
}
var resultValue = value.join("\n");
if (resultValue.endsWith("\n")) {
resultValue = resultValue.slice(0, -1);
}
return {
name: name,
value: resultValue,
};
}
function parseMultiPart(eachPart) {
var ctype = context.getVariable("request.header.content-type");
// Example
// Content-Type: multipart/form-data; boundary=---------------------------1837170403803086655542689190
var parts = ctype.split(";").map((p) => p.trim());
// print("examining part0: (" + parts[0] + ")");
if (parts[0] != "multipart/form-data") {
throw new Error("Not a multipart/form-data message");
}
var boundaryPart = parts.find((v) => v.startsWith("boundary="));
var boundary =
boundaryPart && boundaryPart.split("=").map((p) => p.trim())[1];
var payload = context.getVariable("request.content");
parts = payload.split("--" + boundary).map((p) => p.trim());
if (parts && parts.length) {
var L = parts.length;
if (parts[L - 1] == "--") {
// end of all parts marker
var count = 0;
parts.forEach((part, ix) => {
if (part && part != "--") {
var parsed = parseMultipartPart(part);
eachPart(parsed, ix);
count++;
}
});
context.setVariable("formpart.count", String(count));
} else {
throw new Error("Could not find the final part delimiter");
}
} else {
context.setVariable("formpart.count", "0");
}
}
parseMultiPart((parsed, ix) => {
context.setVariable("formpart." + ix + ".name", parsed.name);
context.setVariable("formpart." + ix + ".value", parsed.value);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment