| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 | 
							- import util from 'util';
 
- import {Readable} from 'stream';
 
- import utils from "../utils.js";
 
- import readBlob from "./readBlob.js";
 
- import platform from "../platform/index.js";
 
- const BOUNDARY_ALPHABET = platform.ALPHABET.ALPHA_DIGIT + '-_';
 
- const textEncoder = typeof TextEncoder === 'function' ? new TextEncoder() : new util.TextEncoder();
 
- const CRLF = '\r\n';
 
- const CRLF_BYTES = textEncoder.encode(CRLF);
 
- const CRLF_BYTES_COUNT = 2;
 
- class FormDataPart {
 
-   constructor(name, value) {
 
-     const {escapeName} = this.constructor;
 
-     const isStringValue = utils.isString(value);
 
-     let headers = `Content-Disposition: form-data; name="${escapeName(name)}"${
 
-       !isStringValue && value.name ? `; filename="${escapeName(value.name)}"` : ''
 
-     }${CRLF}`;
 
-     if (isStringValue) {
 
-       value = textEncoder.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF));
 
-     } else {
 
-       headers += `Content-Type: ${value.type || "application/octet-stream"}${CRLF}`
 
-     }
 
-     this.headers = textEncoder.encode(headers + CRLF);
 
-     this.contentLength = isStringValue ? value.byteLength : value.size;
 
-     this.size = this.headers.byteLength + this.contentLength + CRLF_BYTES_COUNT;
 
-     this.name = name;
 
-     this.value = value;
 
-   }
 
-   async *encode(){
 
-     yield this.headers;
 
-     const {value} = this;
 
-     if(utils.isTypedArray(value)) {
 
-       yield value;
 
-     } else {
 
-       yield* readBlob(value);
 
-     }
 
-     yield CRLF_BYTES;
 
-   }
 
-   static escapeName(name) {
 
-       return String(name).replace(/[\r\n"]/g, (match) => ({
 
-         '\r' : '%0D',
 
-         '\n' : '%0A',
 
-         '"' : '%22',
 
-       }[match]));
 
-   }
 
- }
 
- const formDataToStream = (form, headersHandler, options) => {
 
-   const {
 
-     tag = 'form-data-boundary',
 
-     size = 25,
 
-     boundary = tag + '-' + platform.generateString(size, BOUNDARY_ALPHABET)
 
-   } = options || {};
 
-   if(!utils.isFormData(form)) {
 
-     throw TypeError('FormData instance required');
 
-   }
 
-   if (boundary.length < 1 || boundary.length > 70) {
 
-     throw Error('boundary must be 10-70 characters long')
 
-   }
 
-   const boundaryBytes = textEncoder.encode('--' + boundary + CRLF);
 
-   const footerBytes = textEncoder.encode('--' + boundary + '--' + CRLF + CRLF);
 
-   let contentLength = footerBytes.byteLength;
 
-   const parts = Array.from(form.entries()).map(([name, value]) => {
 
-     const part = new FormDataPart(name, value);
 
-     contentLength += part.size;
 
-     return part;
 
-   });
 
-   contentLength += boundaryBytes.byteLength * parts.length;
 
-   contentLength = utils.toFiniteNumber(contentLength);
 
-   const computedHeaders = {
 
-     'Content-Type': `multipart/form-data; boundary=${boundary}`
 
-   }
 
-   if (Number.isFinite(contentLength)) {
 
-     computedHeaders['Content-Length'] = contentLength;
 
-   }
 
-   headersHandler && headersHandler(computedHeaders);
 
-   return Readable.from((async function *() {
 
-     for(const part of parts) {
 
-       yield boundaryBytes;
 
-       yield* part.encode();
 
-     }
 
-     yield footerBytes;
 
-   })());
 
- };
 
- export default formDataToStream;
 
 
  |