From 6fbfcace18e512f7239a26fbb8380c5c2a78ee2d Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 18 Dec 2015 15:26:50 -0800 Subject: [PATCH 1/8] Fix a couple of minor issues in the Node library --- ext/call_credentials.cc | 2 ++ ext/timeval.cc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/call_credentials.cc b/ext/call_credentials.cc index 8cbfb1eb..91acb862 100644 --- a/ext/call_credentials.cc +++ b/ext/call_credentials.cc @@ -32,6 +32,8 @@ */ #include +#include +#include #include "grpc/grpc.h" #include "grpc/grpc_security.h" diff --git a/ext/timeval.cc b/ext/timeval.cc index bf68513c..64015e84 100644 --- a/ext/timeval.cc +++ b/ext/timeval.cc @@ -46,7 +46,7 @@ gpr_timespec MillisecondsToTimespec(double millis) { } else if (millis == -std::numeric_limits::infinity()) { return gpr_inf_past(GPR_CLOCK_REALTIME); } else { - return gpr_time_from_micros(static_cast(millis * 1000), + return gpr_time_from_micros(static_cast(millis * 1000), GPR_CLOCK_REALTIME); } } From c6a904261a07dee277a8b4024f43654fe5c31a62 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 4 Jan 2016 15:25:09 -0800 Subject: [PATCH 2/8] Fixed a too-long line in a file --- interop/async_delay_queue.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interop/async_delay_queue.js b/interop/async_delay_queue.js index 2bd3ca4d..5df1e009 100644 --- a/interop/async_delay_queue.js +++ b/interop/async_delay_queue.js @@ -36,8 +36,8 @@ var _ = require('lodash'); /** - * This class represents a queue of callbacks that must happen sequentially, each - * with a specific delay after the previous event. + * This class represents a queue of callbacks that must happen sequentially, + * each with a specific delay after the previous event. */ function AsyncDelayQueue() { this.queue = []; From 10b3ca011873a822b4470e16965c037e4811b970 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 7 Jan 2016 10:03:18 -0800 Subject: [PATCH 3/8] Make Node library use core metadata validation instead of duplicating it --- ext/call.cc | 8 ++------ ext/node_grpc.cc | 50 +++++++++++++++++++++++++++++++++++++++++++++++- src/metadata.js | 20 ++++++++++--------- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/ext/call.cc b/ext/call.cc index c0e2b0f0..84a3e227 100644 --- a/ext/call.cc +++ b/ext/call.cc @@ -95,10 +95,6 @@ Local nanErrorWithCode(const char *msg, grpc_call_error code) { return scope.Escape(err); } -bool EndsWith(const char *str, const char *substr) { - return strcmp(str+strlen(str)-strlen(substr), substr) == 0; -} - bool CreateMetadataArray(Local metadata, grpc_metadata_array *array, shared_ptr resources) { HandleScope scope; @@ -126,7 +122,7 @@ bool CreateMetadataArray(Local metadata, grpc_metadata_array *array, grpc_metadata *current = &array->metadata[array->count]; current->key = **utf8_key; // Only allow binary headers for "-bin" keys - if (EndsWith(current->key, "-bin")) { + if (grpc_is_binary_header(current->key, strlen(current->key))) { if (::node::Buffer::HasInstance(value)) { current->value = ::node::Buffer::Data(value); current->value_length = ::node::Buffer::Length(value); @@ -180,7 +176,7 @@ Local ParseMetadata(const grpc_metadata_array *metadata_array) { } else { array = Local::Cast(maybe_array.ToLocalChecked()); } - if (EndsWith(elem->key, "-bin")) { + if (grpc_is_binary_header(elem->key, strlen(elem->key))) { Nan::Set(array, index_map[elem->key], MakeFastBuffer( Nan::CopyBuffer(elem->value, diff --git a/ext/node_grpc.cc b/ext/node_grpc.cc index 5b5f3c1c..a2b8e0d2 100644 --- a/ext/node_grpc.cc +++ b/ext/node_grpc.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,7 @@ #include "completion_queue_async_worker.h" #include "server_credentials.h" +using v8::FunctionTemplate; using v8::Local; using v8::Value; using v8::Object; @@ -230,6 +231,40 @@ void InitWriteFlags(Local exports) { Nan::Set(write_flags, Nan::New("NO_COMPRESS").ToLocalChecked(), NO_COMPRESS); } +NAN_METHOD(MetadataKeyIsLegal) { + if (!info[0]->IsString()) { + return Nan::ThrowTypeError( + "headerKeyIsLegal's argument must be a string"); + } + Local key = Nan::To(info[0]).ToLocalChecked(); + char *key_str = *Nan::Utf8String(key); + info.GetReturnValue().Set(static_cast( + grpc_header_key_is_legal(key_str, static_cast(key->Length())))); +} + +NAN_METHOD(MetadataNonbinValueIsLegal) { + if (!info[0]->IsString()) { + return Nan::ThrowTypeError( + "metadataNonbinValueIsLegal's argument must be a string"); + } + Local value = Nan::To(info[0]).ToLocalChecked(); + char *value_str = *Nan::Utf8String(value); + info.GetReturnValue().Set(static_cast( + grpc_header_nonbin_value_is_legal( + value_str, static_cast(value->Length())))); +} + +NAN_METHOD(MetadataKeyIsBinary) { + if (!info[0]->IsString()) { + return Nan::ThrowTypeError( + "metadataKeyIsLegal's argument must be a string"); + } + Local key = Nan::To(info[0]).ToLocalChecked(); + char *key_str = *Nan::Utf8String(key); + info.GetReturnValue().Set(static_cast( + grpc_is_binary_header(key_str, static_cast(key->Length())))); +} + void init(Local exports) { Nan::HandleScope scope; grpc_init(); @@ -247,6 +282,19 @@ void init(Local exports) { grpc::node::Server::Init(exports); grpc::node::CompletionQueueAsyncWorker::Init(exports); grpc::node::ServerCredentials::Init(exports); + + // Attach a few utility functions directly to the module + Nan::Set(exports, Nan::New("metadataKeyIsLegal").ToLocalChecked(), + Nan::GetFunction( + Nan::New(MetadataKeyIsLegal)).ToLocalChecked()); + Nan::Set(exports, Nan::New("metadataNonbinValueIsLegal").ToLocalChecked(), + Nan::GetFunction( + Nan::New(MetadataNonbinValueIsLegal) + ).ToLocalChecked()); + Nan::Set(exports, Nan::New("metadataKeyIsBinary").ToLocalChecked(), + Nan::GetFunction( + Nan::New(MetadataKeyIsBinary) + ).ToLocalChecked()); } NODE_MODULE(grpc_node, init) diff --git a/src/metadata.js b/src/metadata.js index 0a2f1489..fef79f95 100644 --- a/src/metadata.js +++ b/src/metadata.js @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,6 +49,8 @@ var _ = require('lodash'); +var grpc = require('bindings')('grpc_node'); + /** * Class for storing metadata. Keys are normalized to lowercase ASCII. * @constructor @@ -58,15 +60,16 @@ function Metadata() { } function normalizeKey(key) { - if (!(/^[A-Za-z\d_-]+$/.test(key))) { - throw new Error('Metadata keys must be nonempty strings containing only ' + - 'alphanumeric characters and hyphens'); + key = key.toLowerCase(); + if (grpc.metadataKeyIsLegal(key)) { + return key; + } else { + throw new Error('Metadata key contains illegal characters'); } - return key.toLowerCase(); } function validate(key, value) { - if (_.endsWith(key, '-bin')) { + if (grpc.metadataKeyIsBinary(key)) { if (!(value instanceof Buffer)) { throw new Error('keys that end with \'-bin\' must have Buffer values'); } @@ -75,9 +78,8 @@ 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'); + if (!grpc.metadataNonbinValueIsLegal(value)) { + throw new Error('Metadata string value contains illegal characters'); } } } From e6690d6ee51dc31ae3e2a5a09c1abb6adc830d4e Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 13 Jan 2016 10:05:00 -0800 Subject: [PATCH 4/8] Don't modify proto method names in service paths in Node library --- src/common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.js b/src/common.js index e4fe5a8e..19336ab8 100644 --- a/src/common.js +++ b/src/common.js @@ -125,7 +125,7 @@ exports.getProtobufServiceAttrs = function getProtobufServiceAttrs(service) { var prefix = '/' + fullyQualifiedName(service) + '/'; return _.object(_.map(service.children, function(method) { return [_.camelCase(method.name), { - path: prefix + _.capitalize(method.name), + path: prefix + method.name, requestStream: method.requestStream, responseStream: method.responseStream, requestSerialize: serializeCls(method.resolvedRequestType.build()), From 3f599065b91ef04bac797c67f939a72156d0e2ed Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 13 Jan 2016 17:45:30 -0800 Subject: [PATCH 5/8] Update copyrights --- ext/call.cc | 4 ++-- interop/async_delay_queue.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/call.cc b/ext/call.cc index 9f023b58..e1fc111e 100644 --- a/ext/call.cc +++ b/ext/call.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -773,4 +773,4 @@ NAN_METHOD(Call::SetCredentials) { } } // namespace node -} // namespace grpc +} // namespace grpc \ No newline at end of file diff --git a/interop/async_delay_queue.js b/interop/async_delay_queue.js index 5df1e009..b3c30abc 100644 --- a/interop/async_delay_queue.js +++ b/interop/async_delay_queue.js @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -76,4 +76,4 @@ AsyncDelayQueue.prototype.add = function(callback, delay) { } }; -module.exports = AsyncDelayQueue; +module.exports = AsyncDelayQueue; \ No newline at end of file From 4008482e6594f5937231beb74dcc45afaa18b694 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 14 Jan 2016 11:09:08 -0800 Subject: [PATCH 6/8] Updated copyright in node/common.js --- src/common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.js b/src/common.js index 19336ab8..2e6c01c4 100644 --- a/src/common.js +++ b/src/common.js @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without From af73647f8137ec7b96eb456b5cd6e8a3282b7926 Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Thu, 14 Jan 2016 15:27:08 -0800 Subject: [PATCH 7/8] Added back trailing newlines --- ext/call.cc | 2 +- interop/async_delay_queue.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/call.cc b/ext/call.cc index e1fc111e..da312886 100644 --- a/ext/call.cc +++ b/ext/call.cc @@ -773,4 +773,4 @@ NAN_METHOD(Call::SetCredentials) { } } // namespace node -} // namespace grpc \ No newline at end of file +} // namespace grpc diff --git a/interop/async_delay_queue.js b/interop/async_delay_queue.js index b3c30abc..df572096 100644 --- a/interop/async_delay_queue.js +++ b/interop/async_delay_queue.js @@ -76,4 +76,4 @@ AsyncDelayQueue.prototype.add = function(callback, delay) { } }; -module.exports = AsyncDelayQueue; \ No newline at end of file +module.exports = AsyncDelayQueue; From 5176f384a2d457453e0d722f133640987b4d792a Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 14 Jan 2016 18:29:17 -0800 Subject: [PATCH 8/8] Update Node API documentation generation configuration for move to repo root --- jsdoc_conf.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jsdoc_conf.json b/jsdoc_conf.json index 876a8e19..c3a0174f 100644 --- a/jsdoc_conf.json +++ b/jsdoc_conf.json @@ -3,13 +3,13 @@ "allowUnknownTags": true }, "source": { - "include": [ "index.js", "src" ], - "includePattern": ".+\\.js(doc)?$", + "include": [ "src/node/index.js", "src/node/src" ], + "includePattern": "src/node/.+\\.js(doc)?$", "excludePattern": "(^|\\/|\\\\)_" }, "opts": { "package": "package.json", - "readme": "README.md" + "readme": "src/node/README.md" }, "plugins": [], "templates": {