gohttp
Version:
http & https client for HTTP/1.1 and HTTP/2
212 lines (158 loc) • 5.23 kB
JavaScript
;
//const crypto = require('crypto');
const fs = require('node:fs');
const fsp = fs.promises;
var bodymaker = function (options = {}) {
if (!(this instanceof bodymaker)) return new bodymaker(options);
//最大同时上传文件数量限制
this.maxUploadLimit = 10;
//上传文件最大数据量
this.maxUploadSize = 2000000000;
//单个文件最大上传大小
this.maxFileSize = 1000000000;
this.mimeTable = {
'css' : 'text/css',
'der' : 'application/x-x509-ca-cert',
'gif' : 'image/gif',
'gz' : 'application/x-gzip',
'h' : 'text/plain',
'htm' : 'text/html',
'html' : 'text/html',
'c' : 'text/plain',
'txt' : 'text/plain',
'js' : 'application/x-javascript',
'jpg' : 'image/jpeg',
'jpeg' : 'image/jpeg',
'png' : 'image/png',
'gif' : 'image/gif',
'webp' : 'image/webp',
'mp3' : 'audio/mpeg',
'mp4' : 'video/mp4',
'webm' : 'video/webm',
'exe' : 'application/octet-stream',
'wav' : 'audio/x-wav',
'svg' : 'image/svg+xml',
'tar' : 'application/x-tar',
'ttf' : 'font/ttf',
'wtf' : 'font/wtf',
'woff' : 'font/woff',
'woff2' : 'font/woff2',
'ttc' : 'font/ttc',
'xls' : 'application/vnd.ms-excel',
'gz' : 'application/x-gzip',
'zip' : 'application/zip',
'pdf' : 'application/pdf',
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'doc': 'application/vnd.ms-word',
'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'odp': 'application/vnd.oasis.opendocument.presentation',
'odt': 'application/vnd.oasis.opendocument.text',
'ods': 'application/vnd.oasis.opendocument.spreadsheet',
'odg': 'application/vnd.oasis.opendocument.graphics'
}
this.default_mime = 'application/octet-stream'
this.extName = function (filename = '') {
if (filename.length < 2) return '';
let name_split = filename.split('.').filter(p => p.length > 0);
if (name_split.length < 2) return '';
return name_split[name_split.length - 1];
}
this.mimeType = function (filename) {
var extname = this.extName(filename);
extname = extname.toLowerCase();
if (extname !== '' && this.mimeTable[extname] !== undefined) {
return this.mimeTable[extname];
}
return this.default_mime;
}
}
bodymaker.prototype.fmtName = function (name) {
return name.replace(/"/g, '%22');
}
bodymaker.prototype.fmtFilename = function (name) {
if (name.indexOf('/') >= 0) {
let namesplit = name.split('/').filter(p => p.length > 0);
if (namesplit.length > 0) {
name = namesplit[namesplit.length - 1];
}
}
return name.replace(/"/g, '%22');
}
bodymaker.prototype.makeUploadData = async function (r) {
let bdy = this.boundary();
let formData = '';
if (r.form !== undefined) {
if (typeof r.form === 'object') {
for (let k in r.form) {
formData += `\r\n--${bdy}\r\nContent-Disposition: form-data; `
+ `name=${'"'}${this.fmtName(k)}${'"'}\r\n\r\n${r.form[k]}`;
}
}
}
let bodyfi = {};
let header_data = '';
let payload = '';
let content_length = Buffer.byteLength(formData);
let end_data = `\r\n--${bdy}--\r\n`;
content_length += Buffer.byteLength(end_data);
if (r.files && typeof r.files === 'object') {
let t = '';
for (let k in r.files) {
if (typeof r.files[k] === 'string') {
t = [ r.files[k] ];
} else {
t = r.files[k];
}
let fst = null;
for (let i=0; i < t.length; i++) {
header_data = `Content-Disposition: form-data; `
+ `name="${this.fmtName(k)}"; `
+ `filename="${this.fmtFilename(t[i])}"`
+ `\r\nContent-Type: ${this.mimeType(t[i])}`;
payload = `\r\n--${bdy}\r\n${header_data}\r\n\r\n`;
content_length += Buffer.byteLength(payload);
try {
fst = fs.statSync(t[i]);
content_length += fst.size;
} catch (err) {
console.error(err);
continue ;
}
bodyfi[ t[i] ] = {
payload : payload,
length: fst.size
};
}
}
}
let seek = 0;
let bodyData = Buffer.alloc(content_length);
seek = Buffer.from(formData).copy(bodyData);
//let fd = -1;
let fh = null;
let fret;
for (let f in bodyfi) {
seek += Buffer.from(bodyfi[f].payload).copy(bodyData, seek);
try {
fh = await fsp.open(f);
fret = await fh.read(bodyData, seek, bodyfi[f].length, 0)
seek += fret.bytesRead;
} catch (err) {
throw err;
} finally {
fh && fh.close && fh.close();
}
}
Buffer.from(end_data).copy(bodyData, seek);
return {
'content-type' : `multipart/form-data; boundary=${bdy}`,
'body' : bodyData,
'content-length' : content_length
};
};
bodymaker.prototype.boundary = function() {
let bdy = `${Date.now()}${parseInt(Math.random() * 10000)+10001}`;
return `----------------${bdy}`;
};
module.exports = bodymaker;