Skip to content

Commit cded0c3

Browse files
authored
Upgrade to Formidable 3, Node 14, and audit fix (#1192)
1 parent ceb2599 commit cded0c3

File tree

8 files changed

+1242
-1146
lines changed

8 files changed

+1242
-1146
lines changed

package-lock.json

Lines changed: 1148 additions & 1069 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
"version": "0.45.0",
44
"description": "A minimal node SOAP client",
55
"engines": {
6-
"node": ">=12.0.0"
6+
"node": ">=14.0.0"
77
},
88
"author": "Vinay Pulim <[email protected]>",
99
"dependencies": {
1010
"axios-ntlm": "^1.2.0",
1111
"debug": "^4.3.2",
12-
"formidable": "^2.0.1",
12+
"formidable": "^3.2.4",
1313
"get-stream": "^6.0.1",
1414
"lodash": "^4.17.21",
1515
"sax": ">=0.6",
@@ -19,7 +19,7 @@
1919
"xml-crypto": "^2.1.3"
2020
},
2121
"peerDependencies": {
22-
"axios": ">=0.21.1"
22+
"axios": "^0.27.2"
2323
},
2424
"repository": {
2525
"type": "git",
@@ -78,7 +78,7 @@
7878
"source-map-support": "^0.5.10",
7979
"timekeeper": "^2.1.2",
8080
"tslint": "^5.18.0",
81-
"typedoc": "^0.20.37",
82-
"typescript": "^3.9.10"
81+
"typedoc": "^0.23.10",
82+
"typescript": "^4.7.4"
8383
}
8484
}

src/http.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as url from 'url';
1111
import { v4 as uuidv4 } from 'uuid';
1212
import MIMEType = require('whatwg-mimetype');
1313
import { gzipSync } from 'zlib';
14-
import { IExOptions, IHeaders, IHttpClient, IMTOMAttachments, IOptions } from './types';
14+
import { IExOptions, IHeaders, IHttpClient, IOptions } from './types';
1515
import { parseMTOMResp } from './utils';
1616

1717
const debug = debugBuilder('node-soap');
@@ -53,8 +53,6 @@ export class HttpClient implements IHttpClient {
5353
public buildRequest(rurl: string, data: any, exheaders?: IHeaders, exoptions: IExOptions = {}): any {
5454
const curl = url.parse(rurl);
5555
const method = data ? 'POST' : 'GET';
56-
const secure = curl.protocol === 'https:';
57-
const path = [curl.pathname || '/', curl.search || '', curl.hash || ''].join('');
5856

5957
const host = curl.hostname;
6058
const port = parseInt(curl.port, 10);
@@ -206,7 +204,13 @@ export class HttpClient implements IHttpClient {
206204
}
207205
const _this = this;
208206
req.then((res) => {
209-
let body;
207+
208+
const handleBody = (body?: string) => {
209+
res.data = this.handleResponse(req, res, body || res.data);
210+
callback(null, res, res.data);
211+
return res;
212+
};
213+
210214
if (_this.options.parseReponseAttachments) {
211215
const isMultipartResp = res.headers['content-type'] && res.headers['content-type'].toLowerCase().indexOf('multipart/related') > -1;
212216
if (isMultipartResp) {
@@ -218,23 +222,24 @@ export class HttpClient implements IHttpClient {
218222
if (!boundary) {
219223
return callback(new Error('Missing boundary from content-type'));
220224
}
221-
const multipartResponse = parseMTOMResp(res.data, boundary);
222-
223-
// first part is the soap response
224-
const firstPart = multipartResponse.parts.shift();
225-
if (!firstPart || !firstPart.body) {
226-
return callback(new Error('Cannot parse multipart response'));
227-
}
228-
body = firstPart.body.toString('utf8');
229-
(res as any).mtomResponseAttachments = multipartResponse;
225+
return parseMTOMResp(res.data, boundary, (err, multipartResponse) => {
226+
if (err) {
227+
return callback(err);
228+
}
229+
// first part is the soap response
230+
const firstPart = multipartResponse.parts.shift();
231+
if (!firstPart || !firstPart.body) {
232+
return callback(new Error('Cannot parse multipart response'));
233+
}
234+
(res as any).mtomResponseAttachments = multipartResponse;
235+
return handleBody(firstPart.body.toString('utf8'));
236+
});
230237
} else {
231-
body = res.data.toString('utf8');
238+
return handleBody(res.data.toString('utf8'));
232239
}
240+
} else {
241+
return handleBody();
233242
}
234-
235-
res.data = this.handleResponse(req, res, body || res.data);
236-
callback(null, res, res.data);
237-
return res;
238243
}, (err) => {
239244
return callback(err);
240245
});

src/utils.ts

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11

22
import * as crypto from 'crypto';
3-
import { MultipartParser } from 'formidable';
43
import { IMTOMAttachments } from './types';
54

65
export function passwordDigest(nonce: string, created: string, password: string): string {
@@ -67,46 +66,50 @@ export function xmlEscape(obj) {
6766
return obj;
6867
}
6968

70-
export function parseMTOMResp(payload: Buffer, boundary: string): IMTOMAttachments {
71-
const resp: IMTOMAttachments = {
72-
parts: [],
73-
};
74-
let headerName = '';
75-
let headerValue = '';
76-
let data: Buffer;
77-
let partIndex = 0;
78-
const parser = new MultipartParser();
79-
80-
parser.initWithBoundary(boundary);
81-
parser.on('data', ({ name, buffer, start, end }) => {
82-
switch (name) {
83-
case 'partBegin':
84-
resp.parts[partIndex] = {
85-
body: null,
86-
headers: {},
87-
};
88-
data = Buffer.from('');
89-
break;
90-
case 'headerField':
91-
headerName = buffer.slice(start, end).toString();
92-
break;
93-
case 'headerValue':
94-
headerValue = buffer.slice(start, end).toString();
95-
break;
96-
case 'headerEnd':
97-
resp.parts[partIndex].headers[headerName.toLowerCase()] = headerValue;
98-
break;
99-
case 'partData':
100-
data = Buffer.concat([data, buffer.slice(start, end)]);
101-
break;
102-
case 'partEnd':
103-
resp.parts[partIndex].body = data;
104-
partIndex++;
105-
break;
106-
}
107-
});
108-
109-
parser.write(payload);
110-
111-
return resp;
69+
export function parseMTOMResp(payload: Buffer, boundary: string, callback: (err?: Error, resp?: IMTOMAttachments) => void) {
70+
return import('formidable')
71+
.then(({ MultipartParser }) => {
72+
const resp: IMTOMAttachments = {
73+
parts: [],
74+
};
75+
let headerName = '';
76+
let headerValue = '';
77+
let data: Buffer;
78+
let partIndex = 0;
79+
const parser = new MultipartParser();
80+
81+
parser.initWithBoundary(boundary);
82+
parser.on('data', ({ name, buffer, start, end }) => {
83+
switch (name) {
84+
case 'partBegin':
85+
resp.parts[partIndex] = {
86+
body: null,
87+
headers: {},
88+
};
89+
data = Buffer.from('');
90+
break;
91+
case 'headerField':
92+
headerName = buffer.slice(start, end).toString();
93+
break;
94+
case 'headerValue':
95+
headerValue = buffer.slice(start, end).toString();
96+
break;
97+
case 'headerEnd':
98+
resp.parts[partIndex].headers[headerName.toLowerCase()] = headerValue;
99+
break;
100+
case 'partData':
101+
data = Buffer.concat([data, buffer.slice(start, end)]);
102+
break;
103+
case 'partEnd':
104+
resp.parts[partIndex].body = data;
105+
partIndex++;
106+
break;
107+
}
108+
});
109+
110+
parser.write(payload);
111+
112+
return callback(null, resp);
113+
})
114+
.catch(callback);
112115
}

test/_socketStream.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ module.exports = function createSocketStream(file, length) {
2424
socketStream.destroy = function() {
2525
};
2626

27+
// axios calls this
28+
socketStream.setKeepAlive = function() {
29+
};
30+
2731
socketStream.req = httpReqStream;
2832
socketStream.res = httpResStream;
2933

test/client-customHttp-test.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,18 @@ it('should allow customization of httpClient and the wsdl file download should p
4949
socketStream.destroy = function() {
5050
};
5151

52+
// axios calls this
53+
socketStream.setKeepAlive = function() {
54+
};
55+
5256
//Custom httpClient
53-
function MyHttpClient (options, socket){
54-
httpClient.call(this,options);
55-
this.agent = new CustomAgent(options, socket);
57+
class MyHttpClient extends httpClient {
58+
constructor(options, socket) {
59+
super(options)
60+
this.agent = new CustomAgent(options, socket);
61+
}
5662
}
5763

58-
util.inherits(MyHttpClient, httpClient);
59-
6064
MyHttpClient.prototype.request = function(rurl, data, callback, exheaders, exoptions) {
6165
var self = this;
6266
var options = self.buildRequest(rurl, data, exheaders, exoptions);

test/client-customHttp-xsdinclude-test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ it('should allow customization of httpClient, the wsdl file, and associated data
3434
};
3535

3636
//Custom httpClient
37-
function MyHttpClient (options, wsdlSocket, xsdSocket){
38-
httpClient.call(this,options);
39-
this.agent = new CustomAgent(options, wsdlSocket, xsdSocket);
37+
class MyHttpClient extends httpClient {
38+
constructor(options, wsdlSocket, xsdSocket) {
39+
super(options);
40+
this.agent = new CustomAgent(options, wsdlSocket, xsdSocket);
41+
}
4042
}
4143

42-
util.inherits(MyHttpClient, httpClient);
43-
4444
MyHttpClient.prototype.request = function(rurl, data, callback, exheaders, exoptions) {
4545
var self = this;
4646
var options = self.buildRequest(rurl, data, exheaders, exoptions);

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
22
"compileOnSave": true,
33
"compilerOptions": {
4-
"target": "es3",
4+
"target": "es2020",
55
"module": "commonjs",
6+
"moduleResolution": "nodenext",
67
"outDir": "lib",
78
"sourceMap": true,
89
"declaration": true,

0 commit comments

Comments
 (0)