Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

server: send response to client with res.end() #1043

Merged
merged 1 commit into from Feb 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Readme.md
Expand Up @@ -219,6 +219,7 @@ Server options include the below:
- `ca`: An array of strings or Buffers of trusted certificates in PEM format. If this is omitted several well known "root" CAs will be used, like VeriSign. These are used to authorize connections.
- `crl` : Either a string or list of strings of PEM encoded CRLs (Certificate Revocation List)
- `ciphers`: A string describing the ciphers to use or exclude, separated by :. The default cipher suite is:
- `enableChunkedEncoding`: A boolean for controlling chunked transfer encoding in response. Some client (such as Windows 10's MDM enrollment SOAP client) is sensitive to transfer-encoding mode and can't accept chunked response. This option let user disable chunked transfer encoding for such a client. Default to `true` for backward compatibility.

``` javascript
var xml = require('fs').readFileSync('myservice.wsdl', 'utf8');
Expand Down
37 changes: 26 additions & 11 deletions lib/server.js
Expand Up @@ -40,6 +40,8 @@ var Server = function (server, path, services, wsdl, options) {
this.suppressStack = options && options.suppressStack;
this.returnFault = options && options.returnFault;
this.onewayOptions = options && options.oneWay || {};
this.enableChunkedEncoding =
options.enableChunkedEncoding === undefined ? true : !!options.enableChunkedEncoding;

if (path[path.length - 1] !== '/')
path += '/';
Expand Down Expand Up @@ -144,30 +146,22 @@ Server.prototype._processRequestXml = function (req, res, xml) {
self.log("received", xml);
}
self._process(xml, req, function (result, statusCode) {
if (statusCode) {
res.statusCode = statusCode;
}
res.write(result);
res.end();
self._sendHttpResponse(res, statusCode, result);
if (typeof self.log === 'function') {
self.log("replied", result);
}
});
} catch (err) {
if (err.Fault !== undefined) {
return self._sendError(err.Fault, function (result, statusCode) {
res.statusCode = statusCode || 500;
res.write(result);
res.end();
self._sendHttpResponse(res, statusCode || 500, result);
if (typeof self.log === 'function') {
self.log("error", err);
}
}, new Date().toISOString());
} else {
error = err.stack ? (self.suppressStack === true ? err.message : err.stack) : err;
res.statusCode = 500;
res.write(error);
res.end();
self._sendHttpResponse(res, /* statusCode */ 500, error);
if (typeof self.log === 'function') {
self.log("error", error);
}
Expand Down Expand Up @@ -517,4 +511,25 @@ Server.prototype._sendError = function (soapFault, callback, includeTimestamp) {
return callback(self._envelope(fault, '', includeTimestamp), statusCode);
};

Server.prototype._sendHttpResponse = function (res, statusCode, result) {
if (statusCode) {
res.statusCode = statusCode;
}

/*
* Calling res.write(result) follow by res.end() will cause Node.js to use
* chunked encoding, while calling res.end(result) directly will cause
* Node.js to calculate and send Content-Length header. See
* nodejs/node#26005.
*/

if (this.enableChunkedEncoding) {
res.write(result);
res.end();
}
else {
res.end(result);
}
}

exports.Server = Server;
1 change: 1 addition & 0 deletions lib/soap.d.ts
Expand Up @@ -97,6 +97,7 @@ export interface IServerOptions extends IWsdlBaseOptions {
uri?: string;
suppressStack?: boolean;
oneWay?: IOneWayOptions;
enableChunkedEncoding?: boolean;
[key: string]: any;
}

Expand Down
95 changes: 95 additions & 0 deletions test/server-options-test.js
Expand Up @@ -460,4 +460,99 @@ describe('SOAP Server with Options', function() {
});
});
});
it('should use chunked transfer encoding by default', function (done) {
test.server.listen(15099, null, null, function() {
test.soapServer = soap.listen(test.server, {
path: '/stockquote',
services: test.service,
xml: test.wsdl,
}, test.service, test.wsdl);
test.baseUrl = 'http://' + test.server.address().address + ":" + test.server.address().port;

//windows return 0.0.0.0 as address and that is not
//valid to use in a request
if (test.server.address().address === '0.0.0.0' || test.server.address().address === '::') {
test.baseUrl = 'http://127.0.0.1:' + test.server.address().port;
}

soap.createClient(test.baseUrl + '/stockquote?wsdl', function(err, client) {
assert.ifError(err);

client.on('response', function(body, response, eid) {
var headers = response.headers;
assert.strictEqual(headers['transfer-encoding'], 'chunked');
assert.equal(headers['content-length'], undefined);
})

client.SetTradePrice({ tickerSymbol: 'GOOG' }, function(err, result, body) {
assert.ifError(err);
done();
});
});
});
});
it('should use chunked transfer encoding when enabled in options', function (done) {
test.server.listen(15099, null, null, function() {
test.soapServer = soap.listen(test.server, {
path: '/stockquote',
services: test.service,
xml: test.wsdl,
enableChunkedEncoding: true,
}, test.service, test.wsdl);
test.baseUrl = 'http://' + test.server.address().address + ":" + test.server.address().port;

//windows return 0.0.0.0 as address and that is not
//valid to use in a request
if (test.server.address().address === '0.0.0.0' || test.server.address().address === '::') {
test.baseUrl = 'http://127.0.0.1:' + test.server.address().port;
}

soap.createClient(test.baseUrl + '/stockquote?wsdl', function(err, client) {
assert.ifError(err);

client.on('response', function(body, response, eid) {
var headers = response.headers;
assert.strictEqual(headers['transfer-encoding'], 'chunked');
assert.equal(headers['content-length'], undefined);
})

client.SetTradePrice({ tickerSymbol: 'GOOG' }, function(err, result, body) {
assert.ifError(err);
done();
});
});
});
});
it('should not use chunked transfer encoding when disabled in options', function (done) {
test.server.listen(15099, null, null, function() {
test.soapServer = soap.listen(test.server, {
path: '/stockquote',
services: test.service,
xml: test.wsdl,
enableChunkedEncoding: false,
}, test.service, test.wsdl);
test.baseUrl = 'http://' + test.server.address().address + ":" + test.server.address().port;

//windows return 0.0.0.0 as address and that is not
//valid to use in a request
if (test.server.address().address === '0.0.0.0' || test.server.address().address === '::') {
test.baseUrl = 'http://127.0.0.1:' + test.server.address().port;
}

soap.createClient(test.baseUrl + '/stockquote?wsdl', function(err, client) {
assert.ifError(err);

client.on('response', function(body, response, eid) {
var headers = response.headers;
assert.notEqual(headers['content-length'], undefined);
assert.equal(headers['transfer-encoding'], undefined);
})

client.SetTradePrice({ tickerSymbol: 'GOOG' }, function(err, result, body) {
assert.ifError(err);
done();
});
});
});
});
});