@apeleghq/multipart-parser
Version:
TypeScript streaming parser for MIME multipart messages
7 lines (6 loc) • 5.61 kB
JavaScript
;var L=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var q=Object.prototype.hasOwnProperty;var z=(t,a)=>{for(var r in a)L(t,r,{get:a[r],enumerable:!0})},H=(t,a,r,s)=>{if(a&&typeof a=="object"||typeof a=="function")for(let i of C(a))!q.call(t,i)&&i!==r&&L(t,i,{get:()=>a[i],enumerable:!(s=k(a,i))||s.enumerable});return t};var Z=t=>H(L({},"__esModule",{value:!0}),t);var X={};z(X,{boundaryMatchRegex:()=>T,boundaryRegex:()=>w,default:()=>O,encodeMultipartMessage:()=>j,parseMessage:()=>R,parseMultipartMessage:()=>O});module.exports=Z(X);var w=/^[0-9a-zA-Z'()+_,\-./:=? ]{0,69}[0-9a-zA-Z'()+_,\-./:=?]$/,T=/;\s*boundary=(?:"([0-9a-zA-Z'()+_,\-./:=? ]{0,69}[0-9a-zA-Z'()+_,\-./:=?])"|([0-9a-zA-Z'+_\-.]{0,69}[0-9a-zA-Z'+_\-.]))/;var W=t=>new ReadableStream({pull(r){if(ArrayBuffer.isView(t))r.enqueue(t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength));else if(t instanceof ArrayBuffer)r.enqueue(t);else throw new TypeError("Expected ArrayBuffer or an ArrayBuffer view.");r.close()}}),b=W;var P=/;\s*boundary=(?:"([^"]+)"|([^;",]+))/,U="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-.",v=()=>{let t=new Uint8Array(24);return globalThis.crypto.getRandomValues(t),Array.from(t).map(a=>U[a%U.length]).join("")},m={preventClose:!0};async function*$(t,a,r){let s=new TextEncoder,i=s.encode(`\r
--${t}`);if(Array.isArray(a)&&a.length<1){await r.abort(Error("At least one part is required"));return}let o=0;for await(let e of a){o++;let n,d;if(!e.body&&e.parts)if(d=e.headers.get("content-type"),!d)n=v(),d=`multipart/mixed; boundary="${n}"`;else if(!d.startsWith("multipart/")||!P.test(d)){await r.abort(Error("Invalid multipart content type: "+d));return}else{let l=d.match(T);(!l||!(n=l[1]||l[2]))&&(n=v(),d=d.replace(P,`; boundary="${n}"`))}await b(i).pipeTo(r,m),yield;{let l=[""];if(d){let f=!1;e.headers.forEach((u,y)=>{y!=="content-type"?l.push(`${y}: ${u}`):(f=!0,l.push(`${y}: ${d}`))}),f||l.push(`content-type: ${d}`)}else e.headers.forEach((f,u)=>{l.push(`${u}: ${f}`)});e.parts||!e.body?l.push(""):l.push("","");let A=s.encode(l.join(`\r
`));l.length=0,await b(A).pipeTo(r,m),yield}if(e.body){if(e.body instanceof ArrayBuffer||ArrayBuffer.isView(e.body))await b(e.body).pipeTo(r,m);else if(e.body instanceof Blob)await e.body.stream().pipeTo(r,m);else if(e.body instanceof ReadableStream)await e.body.pipeTo(r,m);else{await r.abort(Error("Invalid body type"));return}yield}else if(e.parts){if(!n){await r.abort(Error("Runtime exception: undefined part boundary"));return}yield*$(n,e.parts,r),yield}}if(!o){await r.abort(Error("At least one part is required"));return}let p=s.encode(`\r
--${t}--`);await b(p).pipeTo(r,m)}var V=(t,a)=>{let r=new TransformStream,s=$(t,a,r.writable),i=!1,o=r.readable.getReader();return new ReadableStream({start(e){(async()=>{for(;;)try{let n=await o.read();if(n.done){let d=new Uint8Array([13,10]);e.enqueue(d.buffer.slice(d.byteOffset,d.byteOffset+d.byteLength)),e.close();return}e.enqueue(n.value)}catch(n){e.error(n);return}})().catch(()=>{})},async pull(){if(i)return;(await s.next()).done&&(i=!0,await r.writable.close())}})},j=V;var Y=(t,a)=>{e:for(let r=0;r<=t.length-a.length;r++){for(let s=0;s<a.length;s++)if(t[r+s]!==a[s])continue e;return r}return-1},h=Y;var D=new TextDecoder,F=new TextEncoder,B=F.encode(`\r
`),J=[9,32],K=(t,a)=>{let r=0,s=[];for(;(r=h(t,B))!==-1&&r!==0;){let o=t.indexOf(58);if(o===-1)throw new Error("Invalid header");let p=D.decode(t.subarray(0,o));for(;J.includes(t[r+2]);){let n=h(t.subarray(r+2),B);if(n<1)break;r+=2+n}let e=D.decode(t.subarray(o+1,r)).replace(/\r\n/g,"");s.push([p,e]),t=t.subarray(r+B.length)}return{headers:a?a(s):(()=>{let o=new Headers(s);return o.has("content-transfer-encoding")||o.set("content-transfer-encoding","7bit"),o.has("content-type")||o.set("content-type","text/plain; charset=us-ascii"),o})(),body:r===-1?null:t.subarray(r+B.length)}},R=K;var Q=(t,...a)=>{let r=a.reduce((o,p)=>o+p.byteLength,t.length),s=new(Object(a[0])).constructor(r);s.set(t);let i=t.length;return a.forEach(o=>{s.set(o,i),i+=o.byteLength}),s},G=Q;async function*N(t,a,r){var A;if(!w.test(a))throw new Error("Invalid boundary delimiter");let s=new TextEncoder,i=[9,32],o=new Uint8Array([13,10]),p=s.encode(`\r
--${a}`),e=new Uint8Array,n=0,d=!1,l=t.getReader();try{for(;n!==3;){let{done:f,value:u}=await l.read();if(f){if(e.length===0||d)throw new Error("Invalid message");d=!0}else e=G(e,ArrayBuffer.isView(u)?new Uint8Array(u.buffer,u.byteOffset,u.byteLength):new Uint8Array(u));for(;e.length>0;){let y=NaN;if(n===0&&(y=h(e,p.slice(2))-2,y===-3)||(y!==-2&&(y=h(e,p)),y===-1))break;let c=y+p.length,g=f?0:h(e.subarray(c,c+32),o);if(g===-1&&e.length-c<32)break;if(g===-1||!Array.from(e.subarray(c+Math.min(2,g),c+g)).every(I=>i.includes(I)))throw new Error(`Invalid boundary at index ${y}`);if(f||g>=2){if([1,2].includes(n)&&e[c+0]===e[c+1]&&e[c+0]===45)n=3;else if(!i.includes(e[c+0])||!i.includes(e[c+1]))throw new Error(`Invalid boundary at index ${y} (${a}): ${(A=e[c+1])==null?void 0:A.toString(16)}`)}switch(n){case 0:n=1;break;case 1:n=2;case 2:case 3:if(e.subarray(y,c).length>0){let I=e.subarray(0,y),x=R(I,r),E=x.headers.get("content-type"),M;if(x.body&&(E!=null&&E.startsWith("multipart/"))){let S=E.match(T);if(S){let _=S[1]||S[2];M=N(b(x.body),_)}else M=null}yield{headers:x.headers,body:x.body,...M!==void 0&&{parts:M}}}break}if(n===3){e=e.subarray(e.length);break}e=e.subarray(g+c+2)}}}finally{l.releaseLock()}}var O=N;0&&(module.exports={boundaryMatchRegex,boundaryRegex,encodeMultipartMessage,parseMessage,parseMultipartMessage});