source: node_modules/axios/lib/helpers/formDataToStream.js@ ff72ad2

Last change on this file since ff72ad2 was ff72ad2, checked in by ste08 <sjovanoska@…>, 2 months ago

Adding review works\!

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