Skip to content

Commit 8c3b89d

Browse files
committed
feat: allow streams as request data
1 parent 3abb555 commit 8c3b89d

File tree

9 files changed

+112
-32
lines changed

9 files changed

+112
-32
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ mocha-eclipse.js
1717
*.sublime-project
1818
*.sublime-workspace
1919
*.code-workspace
20+
.vscode/*
21+

lib/NrcConnectManager.js

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import followRedirect from 'follow-redirects';
33
import zlib from 'zlib';
44
import debug from './NrcDebugger.js';
5+
import stream from 'stream';
56

67

78
const {http, https} = followRedirect;
@@ -121,16 +122,7 @@ export class NrcConnectManager {
121122
self.#configureRequest(request, requestConfig, clientRequest);
122123
clientRequest.setHttpRequest(request);
123124

124-
// write POST/PUT data to request body;
125-
// find valid serializer to be used to serialize request data,
126-
// first one found
127-
// is the one to be used.if none found for match condition,
128-
// default serializer is used
129-
if (options.data) {
130-
request.write(options.data);
131-
}
132-
133-
request.end();
125+
self.#writeRequest(options.data, request);
134126

135127
// handle request errors and handle them by request or general
136128
// error handler
@@ -204,15 +196,9 @@ export class NrcConnectManager {
204196
clientRequest.setHttpRequest(request);
205197

206198
debug('options data', options.data);
207-
// write POST/PUT data to request body;
208-
// find valid serializer to be used to serialize request data,
209-
// first one found
210-
// is the one to be used.if none found for match condition,
211-
// default serializer is used
212-
if (options.data) {
213-
request.write(options.data);
214-
}
215-
request.end(); // end request when data is written
199+
200+
201+
this.#writeRequest(options.data, request);
216202

217203
// handle request errors and handle them by request or general
218204
// error handler
@@ -230,6 +216,38 @@ export class NrcConnectManager {
230216
});
231217
}
232218

219+
220+
/**
221+
* Description placeholder
222+
* @date 10/19/2023 - 7:06:36 PM
223+
*
224+
* @param {*} data
225+
* @param {*} request
226+
*/
227+
#writeRequest(data, request) {
228+
if (data) {
229+
if (data instanceof stream) {
230+
// close request when stream ends
231+
data.pipe(request);
232+
data.on('end', ()=>{
233+
request.end();
234+
data.close();
235+
});
236+
} else {
237+
// write POST/PUT data to request body;
238+
// find valid serializer to be used to serialize request data,
239+
// first one found
240+
// is the one to be used.if none found for match condition,
241+
// default serializer is used
242+
request.write(data);
243+
request.end();
244+
}
245+
} else {
246+
// no data, end request
247+
request.end();
248+
}
249+
}
250+
233251
/**
234252
* prepare request using global or method config
235253
* @author aacerox

lib/NrcIoManager.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import urlParser from 'url';
44
import NrcClientRequest from './NrcClientRequest.js';
55
import events from 'events';
66
import debug from './NrcDebugger.js';
7+
import stream from 'stream';
78

89
// declare ioManager constants
910
const CONSTANTS = {
@@ -523,7 +524,11 @@ export default class NrcIoManager extends events.EventEmitter {
523524

524525
// always set Content-length header if not set previously
525526
// set Content length for some servers to work (nginx, apache)
526-
if (
527+
528+
if (args.data instanceof stream) {
529+
// if data is stream redirect to options to be used
530+
options.data = args.data;
531+
} else if (
527532
args.data !== undefined &&
528533
!options.headers.hasOwnProperty(CONSTANTS.HEADER_CONTENT_LENGTH)
529534
) {

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
},
3737
"scripts": {
3838
"build": "rm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && bash ./fixup",
39-
"test": "mocha --exit",
39+
"test": "npm run build && mocha --exit",
4040
"changeset": "changeset",
4141
"publish:packages": "changeset publish",
4242
"version:packages": "changeset version"

test/resources/stream-file.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
2+
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
3+
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
4+
Nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor.
5+
In reprehenderit in voluptate velit esse cillum dolore eu fugiat.
6+
Nulla pariatur. Excepteur sint occaecat cupidatat non proident.
7+
Sunt in culpa qui officia deserunt mollit anim id est laborum.
8+
9+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
10+
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
11+
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
12+
Nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor.
13+
In reprehenderit in voluptate velit esse cillum dolore eu fugiat.
14+
Nulla pariatur. Excepteur sint occaecat cupidatat non proident.
15+
Sunt in culpa qui officia deserunt mollit anim id est laborum.
16+
17+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
18+
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
19+
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
20+
Nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor.
21+
In reprehenderit in voluptate velit esse cillum dolore eu fugiat.
22+
Nulla pariatur. Excepteur sint occaecat cupidatat non proident.
23+
Sunt in culpa qui officia deserunt mollit anim id est laborum.

test/server/mock-server.mjs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,19 @@ const RouteManager = {
161161
res.write(JSON.stringify(message));
162162
res.end();
163163
},
164+
'/stream': function(req, res) {
165+
let requestBody = '';
166+
167+
req.on('data', (chunk) => requestBody +=chunk);
168+
169+
req.on('end', function(data) {
170+
res.writeHead(200, {
171+
'Content-Type': 'text/plain',
172+
});
173+
res.write(requestBody);
174+
res.end();
175+
});
176+
},
164177

165178
},
166179
'sleep': function(ms) {

test/specs/TestPOSTMethod.mjs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/* eslint-disable max-len */
22
import server from '../server/mock-server.mjs';
33
import Client from '../../dist/mjs/NodeRestClient.js';
4+
import {createReadStream, readFileSync} from 'fs';
5+
46

57
describe('POST Method', function() {
68
// eslint-disable-next-line no-invalid-this
@@ -228,6 +230,28 @@ describe('POST Method', function() {
228230
});
229231
});
230232

233+
describe('#STREAM', function() {
234+
it('POST request with file read stream', function(done) {
235+
const client = new Client();
236+
237+
// create read stream from file
238+
const testFilePath = './test/resources/stream-file.txt';
239+
const sourceData = readFileSync(testFilePath);
240+
const sourceStream = createReadStream(testFilePath);
241+
242+
243+
client.post(
244+
server.baseURL + '/stream',
245+
{data: sourceStream},
246+
function(data, response) {
247+
response.statusCode.should.be.equal(200);
248+
data.toString().should.equal(sourceData.toString());
249+
done();
250+
},
251+
);
252+
});
253+
});
254+
231255
after(function() {
232256
server.close();
233257
console.log('server stopped');

test/specs/TestRIOFacade.mjs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,6 @@ describe('IO Facade', function() {
191191
serializedCallback(JSON.stringify(data));
192192
},
193193
};
194-
const defaultTestSerializer = {'name': 'default-test-serializer',
195-
'isDefault': true,
196-
'serialize': function(data, nrcEventEmitter, serializedCallback) {
197-
if (typeof data === 'object') {
198-
data.defaultParsed = true;
199-
}
200-
serializedCallback(data);
201-
},
202-
};
203194

204195

205196
it('add invalid serializer to client', function(done) {
@@ -260,6 +251,7 @@ describe('IO Facade', function() {
260251
data.postData.includes('serialized').should.be.true();
261252
});
262253

254+
request.should.not.be.null();
263255
done();
264256
});
265257

@@ -300,6 +292,9 @@ describe('IO Facade', function() {
300292

301293
after(function() {
302294
server.close();
303-
console.log('server stopped');
295+
// server will respond with ECONNRESET if we do not wait her
296+
setTimeout(() => {
297+
console.log('server stopped');
298+
}, 500 );
304299
});
305300
});

0 commit comments

Comments
 (0)