diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js index 39514b254764cdd36362deda078ef1ba8f782ae6..8e0884acea6affb0fced16e9d91f213c6954a3ce 100644 --- a/src/node/src/metadata.js +++ b/src/node/src/metadata.js @@ -49,10 +49,14 @@ function Metadata() { } function normalizeKey(key) { - return _.deburr(key).toLowerCase(); + return key.toLowerCase(); } function validate(key, value) { + if (!(/^[a-z\d-]+$/.test(key))) { + throw new Error('Metadata keys must be nonempty strings containing only ' + + 'alphanumeric characters and hyphens'); + } if (_.endsWith(key, '-bin')) { if (!(value instanceof Buffer)) { throw new Error('keys that end with \'-bin\' must have Buffer values'); @@ -62,6 +66,10 @@ function validate(key, value) { throw new Error( 'keys that don\'t end with \'-bin\' must have String values'); } + if (!(/^[\x20-\x7E]*$/.test(value))) { + throw new Error('Metadata string values can only contain printable ' + + 'ASCII characters and space'); + } } } diff --git a/src/node/test/metadata_test.js b/src/node/test/metadata_test.js index f1859b674d8fc266189c004a639de33c7ade95e1..227fa9c99492ec568810d9f95d0c4c042cbc4775 100644 --- a/src/node/test/metadata_test.js +++ b/src/node/test/metadata_test.js @@ -59,6 +59,19 @@ describe('Metadata', function() { metadata.set('key-bin', new Buffer('value')); }); }); + it('Rejects invalid keys', function() { + assert.throws(function() { + metadata.set('key$', 'value'); + }); + assert.throws(function() { + metadata.set('', 'value'); + }); + }); + it('Rejects values with non-ASCII characters', function() { + assert.throws(function() { + metadata.set('key', 'résumé'); + }); + }); it('Saves values that can be retrieved', function() { metadata.set('key', 'value'); assert.deepEqual(metadata.get('key'), ['value']); @@ -92,6 +105,14 @@ describe('Metadata', function() { metadata.add('key-bin', new Buffer('value')); }); }); + it('Rejects invalid keys', function() { + assert.throws(function() { + metadata.add('key$', 'value'); + }); + assert.throws(function() { + metadata.add('', 'value'); + }); + }); it('Saves values that can be retrieved', function() { metadata.add('key', 'value'); assert.deepEqual(metadata.get('key'), ['value']); diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index c7e63e9814181e5dc51d9f90f76fc544a0930cab..7c2a8d72583dba3372317d719caff010e6737215 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -359,7 +359,7 @@ describe('Other conditions', function() { test_service = test_proto.lookup('TestService'); server = new grpc.Server(); var trailer_metadata = new grpc.Metadata(); - trailer_metadata.add('trailer_present', 'yes'); + trailer_metadata.add('trailer-present', 'yes'); server.addProtoService(test_service, { unary: function(call, cb) { var req = call.request; @@ -514,7 +514,7 @@ describe('Other conditions', function() { assert.ifError(err); }); call.on('status', function(status) { - assert.deepEqual(status.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -523,7 +523,7 @@ describe('Other conditions', function() { assert(err); }); call.on('status', function(status) { - assert.deepEqual(status.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -535,7 +535,7 @@ describe('Other conditions', function() { call.write({error: false}); call.end(); call.on('status', function(status) { - assert.deepEqual(status.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -547,7 +547,7 @@ describe('Other conditions', function() { call.write({error: true}); call.end(); call.on('status', function(status) { - assert.deepEqual(status.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -556,7 +556,7 @@ describe('Other conditions', function() { call.on('data', function(){}); call.on('status', function(status) { assert.strictEqual(status.code, grpc.status.OK); - assert.deepEqual(status.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -564,7 +564,7 @@ describe('Other conditions', function() { var call = client.serverStream({error: true}); call.on('data', function(){}); call.on('error', function(error) { - assert.deepEqual(error.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(error.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -576,7 +576,7 @@ describe('Other conditions', function() { call.on('data', function(){}); call.on('status', function(status) { assert.strictEqual(status.code, grpc.status.OK); - assert.deepEqual(status.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -587,7 +587,7 @@ describe('Other conditions', function() { call.end(); call.on('data', function(){}); call.on('error', function(error) { - assert.deepEqual(error.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(error.metadata.get('trailer-present'), ['yes']); done(); }); });