source: imaps-frontend/node_modules/axios/lib/helpers/formDataToStream.js@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 2.8 KB
Line 
1import {TextEncoder} from 'util';
2import {Readable} from 'stream';
3import utils from "../utils.js";
4import readBlob from "./readBlob.js";
5
6const BOUNDARY_ALPHABET = utils.ALPHABET.ALPHA_DIGIT + '-_';
7
8const textEncoder = new TextEncoder();
9
10const CRLF = '\r\n';
11const CRLF_BYTES = textEncoder.encode(CRLF);
12const CRLF_BYTES_COUNT = 2;
13
14class FormDataPart {
15 constructor(name, value) {
16 const {escapeName} = this.constructor;
17 const isStringValue = utils.isString(value);
18
19 let headers = `Content-Disposition: form-data; name="${escapeName(name)}"${
20 !isStringValue && value.name ? `; filename="${escapeName(value.name)}"` : ''
21 }${CRLF}`;
22
23 if (isStringValue) {
24 value = textEncoder.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF));
25 } else {
26 headers += `Content-Type: ${value.type || "application/octet-stream"}${CRLF}`
27 }
28
29 this.headers = textEncoder.encode(headers + CRLF);
30
31 this.contentLength = isStringValue ? value.byteLength : value.size;
32
33 this.size = this.headers.byteLength + this.contentLength + CRLF_BYTES_COUNT;
34
35 this.name = name;
36 this.value = value;
37 }
38
39 async *encode(){
40 yield this.headers;
41
42 const {value} = this;
43
44 if(utils.isTypedArray(value)) {
45 yield value;
46 } else {
47 yield* readBlob(value);
48 }
49
50 yield CRLF_BYTES;
51 }
52
53 static escapeName(name) {
54 return String(name).replace(/[\r\n"]/g, (match) => ({
55 '\r' : '%0D',
56 '\n' : '%0A',
57 '"' : '%22',
58 }[match]));
59 }
60}
61
62const formDataToStream = (form, headersHandler, options) => {
63 const {
64 tag = 'form-data-boundary',
65 size = 25,
66 boundary = tag + '-' + utils.generateString(size, BOUNDARY_ALPHABET)
67 } = options || {};
68
69 if(!utils.isFormData(form)) {
70 throw TypeError('FormData instance required');
71 }
72
73 if (boundary.length < 1 || boundary.length > 70) {
74 throw Error('boundary must be 10-70 characters long')
75 }
76
77 const boundaryBytes = textEncoder.encode('--' + boundary + CRLF);
78 const footerBytes = textEncoder.encode('--' + boundary + '--' + CRLF + CRLF);
79 let contentLength = footerBytes.byteLength;
80
81 const parts = Array.from(form.entries()).map(([name, value]) => {
82 const part = new FormDataPart(name, value);
83 contentLength += part.size;
84 return part;
85 });
86
87 contentLength += boundaryBytes.byteLength * parts.length;
88
89 contentLength = utils.toFiniteNumber(contentLength);
90
91 const computedHeaders = {
92 'Content-Type': `multipart/form-data; boundary=${boundary}`
93 }
94
95 if (Number.isFinite(contentLength)) {
96 computedHeaders['Content-Length'] = contentLength;
97 }
98
99 headersHandler && headersHandler(computedHeaders);
100
101 return Readable.from((async function *() {
102 for(const part of parts) {
103 yield boundaryBytes;
104 yield* part.encode();
105 }
106
107 yield footerBytes;
108 })());
109};
110
111export default formDataToStream;
Note: See TracBrowser for help on using the repository browser.