From 5c413947a42a5962c729302d7ab83d2cc97bb716 Mon Sep 17 00:00:00 2001 From: Phil Kunz Date: Thu, 19 Jul 2018 16:16:02 +0200 Subject: [PATCH] add formData capability --- package-lock.json | 52 +++++++++++++++++++++++++++++-- package.json | 4 ++- ts/smartrequest.formdata.ts | 62 +++++++++++++++++++++++++++++++++++++ ts/smartrequest.plugins.ts | 7 +++-- ts/smartrequest.request.ts | 33 +++++++++++++------- 5 files changed, 142 insertions(+), 16 deletions(-) create mode 100644 ts/smartrequest.formdata.ts diff --git a/package-lock.json b/package-lock.json index 41f8863..35d57e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -102,6 +102,14 @@ "@types/chai": "*" } }, + "@types/form-data": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", + "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", + "requires": { + "@types/node": "*" + } + }, "@types/fs-extra": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", @@ -114,8 +122,7 @@ "@types/node": { "version": "10.5.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.2.tgz", - "integrity": "sha512-m9zXmifkZsMHZBOyxZWilMwmTlpC8x5Ty360JKTiXvlXZfBWYpsg9ZZvP/Ye+iZUh+Q+MxDLjItVTWIsfwz+8Q==", - "dev": true + "integrity": "sha512-m9zXmifkZsMHZBOyxZWilMwmTlpC8x5Ty360JKTiXvlXZfBWYpsg9ZZvP/Ye+iZUh+Q+MxDLjItVTWIsfwz+8Q==" }, "@types/vinyl": { "version": "2.0.2", @@ -153,6 +160,11 @@ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -255,6 +267,14 @@ "readable-stream": "^2.3.5" } }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -286,6 +306,11 @@ "object-keys": "^1.0.8" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -354,6 +379,16 @@ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + } + }, "fs-extra": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", @@ -520,6 +555,19 @@ "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", "dev": true }, + "mime-db": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" + }, + "mime-types": { + "version": "2.1.19", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", + "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "requires": { + "mime-db": "~1.35.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", diff --git a/package.json b/package.json index bce46d0..0f62e2c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,9 @@ }, "homepage": "https://gitlab.com/pushrocks/smartrequest#README", "dependencies": { - "@pushrocks/smartpromise": "^2.0.5" + "@pushrocks/smartpromise": "^2.0.5", + "@types/form-data": "^2.2.1", + "form-data": "^2.3.2" }, "devDependencies": { "@gitzone/tsrun": "^1.1.9", diff --git a/ts/smartrequest.formdata.ts b/ts/smartrequest.formdata.ts new file mode 100644 index 0000000..3cd6f19 --- /dev/null +++ b/ts/smartrequest.formdata.ts @@ -0,0 +1,62 @@ +import * as plugins from "./smartrequest.plugins"; +import * as interfaces from "./smartrequest.interfaces"; +import { request } from "./smartrequest.request"; + +/** + * the interfae for FormFieldData + */ +export interface IFormField { + name: string; + type: "string" | "filePath" | "Buffer"; + payload: string; +} + +/** + * retrieve the FormData headers in reliable way + * @param formDataArg + */ +const getFormDataHeaders = (formDataArg: plugins.formData) => { + const done = plugins.smartpromise.defer(); + formDataArg.getLength((err, length) => { + if (err) { + done.reject(err); + } + const headers = Object.assign( + { "Content-Length": length }, + formDataArg.getHeaders() + ); + done.resolve(headers); + }); + return done.promise; +}; + +const appendFormField = async ( + formDataArg: plugins.formData, + formDataField: IFormField +) => { + if (formDataField.type === "filePath") { + formDataArg.append("type", "image"); + let fileData = plugins.fs.createReadStream( + plugins.path.join(__dirname, formDataField.payload) + ); + formDataArg.append("media", fileData, "upload.pdf"); + } +}; + +export const postFormData = async ( + urlArg: string, + optionsArg: interfaces.ISmartRequestOptions = {}, + payloadArg: IFormField[] +) => { + const form = new plugins.formData(); + for (const formField of payloadArg) { + await appendFormField(form, formField); + } + const pipeLog: any = async (...args) => { + console.log(args); + }; + const requestOptions = Object.assign({}, optionsArg, { requestBody: form }); + + // lets fire the actual request for sending the formdata + request(urlArg, requestOptions); +}; diff --git a/ts/smartrequest.plugins.ts b/ts/smartrequest.plugins.ts index 8b916ba..dc7fb57 100644 --- a/ts/smartrequest.plugins.ts +++ b/ts/smartrequest.plugins.ts @@ -1,7 +1,10 @@ -import * as url from 'url'; +import * as formData from 'form-data'; +import * as fs from 'fs'; import * as http from 'http'; import * as https from 'https'; +import * as path from 'path'; +import * as url from 'url'; import * as smartpromise from '@pushrocks/smartpromise'; -export { url, http, https, smartpromise }; +export {formData, http, https, fs, path, url, smartpromise }; diff --git a/ts/smartrequest.request.ts b/ts/smartrequest.request.ts index 0354a51..441229d 100644 --- a/ts/smartrequest.request.ts +++ b/ts/smartrequest.request.ts @@ -86,7 +86,28 @@ export let request = async ( // lets perform the actual request - let request = requestModule.request(optionsArg, async response => { + let request = requestModule.request(optionsArg); + + // lets write the requestBody + if (optionsArg.requestBody) { + if ( + typeof optionsArg.requestBody !== "string" + && !(optionsArg.requestBody instanceof plugins.formData) + ) { + optionsArg.requestBody = JSON.stringify(optionsArg.requestBody); + request.write(optionsArg.requestBody); + } else if (optionsArg.requestBody instanceof plugins.formData) { + optionsArg.requestBody.pipe(request); + } + } + + // lets handle an error + request.on("error", e => { + console.error(e); + }); + + // lets handle the response + request.on("response", async response => { if (streamArg) { done.resolve(response); } else { @@ -95,16 +116,6 @@ export let request = async ( } }); - // lets write the requestBody - if (optionsArg.requestBody) { - if (typeof optionsArg.requestBody !== "string") { - optionsArg.requestBody = JSON.stringify(optionsArg.requestBody); - } - request.write(optionsArg.requestBody); - } - request.on("error", e => { - console.error(e); - }); request.end(); const result = await done.promise;