mirror of https://github.com/grpc/grpc-node.git
Split Credentials into two types
This commit is contained in:
parent
49c1c52bb5
commit
6fcabd1a36
|
@ -72,9 +72,10 @@
|
||||||
"sources": [
|
"sources": [
|
||||||
"ext/byte_buffer.cc",
|
"ext/byte_buffer.cc",
|
||||||
"ext/call.cc",
|
"ext/call.cc",
|
||||||
|
"ext/call_credentials.cc",
|
||||||
"ext/channel.cc",
|
"ext/channel.cc",
|
||||||
|
"ext/channel_credentials.cc",
|
||||||
"ext/completion_queue_async_worker.cc",
|
"ext/completion_queue_async_worker.cc",
|
||||||
"ext/credentials.cc",
|
|
||||||
"ext/node_grpc.cc",
|
"ext/node_grpc.cc",
|
||||||
"ext/server.cc",
|
"ext/server.cc",
|
||||||
"ext/server_credentials.cc",
|
"ext/server_credentials.cc",
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
#include "call.h"
|
#include "call.h"
|
||||||
#include "channel.h"
|
#include "channel.h"
|
||||||
#include "completion_queue_async_worker.h"
|
#include "completion_queue_async_worker.h"
|
||||||
#include "credentials.h"
|
#include "call_credentials.h"
|
||||||
#include "timeval.h"
|
#include "timeval.h"
|
||||||
|
|
||||||
using std::unique_ptr;
|
using std::unique_ptr;
|
||||||
|
@ -733,12 +733,12 @@ NAN_METHOD(Call::SetCredentials) {
|
||||||
return Nan::ThrowTypeError(
|
return Nan::ThrowTypeError(
|
||||||
"setCredentials can only be called on Call objects");
|
"setCredentials can only be called on Call objects");
|
||||||
}
|
}
|
||||||
if (!Credentials::HasInstance(info[0])) {
|
if (!CallCredentials::HasInstance(info[0])) {
|
||||||
return Nan::ThrowTypeError(
|
return Nan::ThrowTypeError(
|
||||||
"setCredentials' first argument must be a credential");
|
"setCredentials' first argument must be a CallCredentials");
|
||||||
}
|
}
|
||||||
Call *call = ObjectWrap::Unwrap<Call>(info.This());
|
Call *call = ObjectWrap::Unwrap<Call>(info.This());
|
||||||
Credentials *creds_object = ObjectWrap::Unwrap<Credentials>(
|
CallCredentials *creds_object = ObjectWrap::Unwrap<CallCredentials>(
|
||||||
Nan::To<Object>(info[0]).ToLocalChecked());
|
Nan::To<Object>(info[0]).ToLocalChecked());
|
||||||
grpc_credentials *creds = creds_object->GetWrappedCredentials();
|
grpc_credentials *creds = creds_object->GetWrappedCredentials();
|
||||||
grpc_call_error error = GRPC_CALL_ERROR;
|
grpc_call_error error = GRPC_CALL_ERROR;
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "grpc/grpc.h"
|
#include "grpc/grpc.h"
|
||||||
#include "grpc/grpc_security.h"
|
#include "grpc/grpc_security.h"
|
||||||
#include "grpc/support/log.h"
|
#include "grpc/support/log.h"
|
||||||
#include "credentials.h"
|
#include "call_credentials.h"
|
||||||
#include "call.h"
|
#include "call.h"
|
||||||
|
|
||||||
namespace grpc {
|
namespace grpc {
|
||||||
|
@ -61,47 +61,42 @@ using v8::Object;
|
||||||
using v8::ObjectTemplate;
|
using v8::ObjectTemplate;
|
||||||
using v8::Value;
|
using v8::Value;
|
||||||
|
|
||||||
Nan::Callback *Credentials::constructor;
|
Nan::Callback *CallCredentials::constructor;
|
||||||
Persistent<FunctionTemplate> Credentials::fun_tpl;
|
Persistent<FunctionTemplate> CallCredentials::fun_tpl;
|
||||||
|
|
||||||
Credentials::Credentials(grpc_credentials *credentials)
|
CallCredentials::CallCredentials(grpc_credentials *credentials)
|
||||||
: wrapped_credentials(credentials) {}
|
: wrapped_credentials(credentials) {}
|
||||||
|
|
||||||
Credentials::~Credentials() {
|
CallCredentials::~CallCredentials() {
|
||||||
grpc_credentials_release(wrapped_credentials);
|
grpc_credentials_release(wrapped_credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Credentials::Init(Local<Object> exports) {
|
void CallCredentials::Init(Local<Object> exports) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
|
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
|
||||||
tpl->SetClassName(Nan::New("Credentials").ToLocalChecked());
|
tpl->SetClassName(Nan::New("CallCredentials").ToLocalChecked());
|
||||||
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
|
Nan::SetPrototypeMethod(tpl, "compose", Compose);
|
||||||
fun_tpl.Reset(tpl);
|
fun_tpl.Reset(tpl);
|
||||||
Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked();
|
Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked();
|
||||||
Nan::Set(ctr, Nan::New("createSsl").ToLocalChecked(),
|
|
||||||
Nan::GetFunction(
|
|
||||||
Nan::New<FunctionTemplate>(CreateSsl)).ToLocalChecked());
|
|
||||||
Nan::Set(ctr, Nan::New("createComposite").ToLocalChecked(),
|
|
||||||
Nan::GetFunction(
|
|
||||||
Nan::New<FunctionTemplate>(CreateComposite)).ToLocalChecked());
|
|
||||||
Nan::Set(ctr, Nan::New("createInsecure").ToLocalChecked(),
|
|
||||||
Nan::GetFunction(
|
|
||||||
Nan::New<FunctionTemplate>(CreateInsecure)).ToLocalChecked());
|
|
||||||
Nan::Set(ctr, Nan::New("createFromPlugin").ToLocalChecked(),
|
Nan::Set(ctr, Nan::New("createFromPlugin").ToLocalChecked(),
|
||||||
Nan::GetFunction(
|
Nan::GetFunction(
|
||||||
Nan::New<FunctionTemplate>(CreateFromPlugin)).ToLocalChecked());
|
Nan::New<FunctionTemplate>(CreateFromPlugin)).ToLocalChecked());
|
||||||
Nan::Set(exports, Nan::New("Credentials").ToLocalChecked(), ctr);
|
Nan::Set(exports, Nan::New("CallCredentials").ToLocalChecked(), ctr);
|
||||||
constructor = new Nan::Callback(ctr);
|
constructor = new Nan::Callback(ctr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Credentials::HasInstance(Local<Value> val) {
|
bool CallCredentials::HasInstance(Local<Value> val) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
return Nan::New(fun_tpl)->HasInstance(val);
|
return Nan::New(fun_tpl)->HasInstance(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Local<Value> Credentials::WrapStruct(grpc_credentials *credentials) {
|
Local<Value> CallCredentials::WrapStruct(grpc_credentials *credentials) {
|
||||||
EscapableHandleScope scope;
|
EscapableHandleScope scope;
|
||||||
const int argc = 1;
|
const int argc = 1;
|
||||||
|
if (credentials == NULL) {
|
||||||
|
return scope.Escape(Nan::Null());
|
||||||
|
}
|
||||||
Local<Value> argv[argc] = {
|
Local<Value> argv[argc] = {
|
||||||
Nan::New<External>(reinterpret_cast<void *>(credentials))};
|
Nan::New<External>(reinterpret_cast<void *>(credentials))};
|
||||||
MaybeLocal<Object> maybe_instance = Nan::NewInstance(
|
MaybeLocal<Object> maybe_instance = Nan::NewInstance(
|
||||||
|
@ -113,20 +108,20 @@ Local<Value> Credentials::WrapStruct(grpc_credentials *credentials) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
grpc_credentials *Credentials::GetWrappedCredentials() {
|
grpc_credentials *CallCredentials::GetWrappedCredentials() {
|
||||||
return wrapped_credentials;
|
return wrapped_credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(Credentials::New) {
|
NAN_METHOD(CallCredentials::New) {
|
||||||
if (info.IsConstructCall()) {
|
if (info.IsConstructCall()) {
|
||||||
if (!info[0]->IsExternal()) {
|
if (!info[0]->IsExternal()) {
|
||||||
return Nan::ThrowTypeError(
|
return Nan::ThrowTypeError(
|
||||||
"Credentials can only be created with the provided functions");
|
"CallCredentials can only be created with the provided functions");
|
||||||
}
|
}
|
||||||
Local<External> ext = info[0].As<External>();
|
Local<External> ext = info[0].As<External>();
|
||||||
grpc_credentials *creds_value =
|
grpc_credentials *creds_value =
|
||||||
reinterpret_cast<grpc_credentials *>(ext->Value());
|
reinterpret_cast<grpc_credentials *>(ext->Value());
|
||||||
Credentials *credentials = new Credentials(creds_value);
|
CallCredentials *credentials = new CallCredentials(creds_value);
|
||||||
credentials->Wrap(info.This());
|
credentials->Wrap(info.This());
|
||||||
info.GetReturnValue().Set(info.This());
|
info.GetReturnValue().Set(info.This());
|
||||||
return;
|
return;
|
||||||
|
@ -144,71 +139,26 @@ NAN_METHOD(Credentials::New) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(Credentials::CreateSsl) {
|
NAN_METHOD(CallCredentials::Compose) {
|
||||||
char *root_certs = NULL;
|
if (!CallCredentials::HasInstance(info.This())) {
|
||||||
grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL};
|
|
||||||
if (::node::Buffer::HasInstance(info[0])) {
|
|
||||||
root_certs = ::node::Buffer::Data(info[0]);
|
|
||||||
} else if (!(info[0]->IsNull() || info[0]->IsUndefined())) {
|
|
||||||
return Nan::ThrowTypeError("createSsl's first argument must be a Buffer");
|
|
||||||
}
|
|
||||||
if (::node::Buffer::HasInstance(info[1])) {
|
|
||||||
key_cert_pair.private_key = ::node::Buffer::Data(info[1]);
|
|
||||||
} else if (!(info[1]->IsNull() || info[1]->IsUndefined())) {
|
|
||||||
return Nan::ThrowTypeError(
|
return Nan::ThrowTypeError(
|
||||||
"createSSl's second argument must be a Buffer if provided");
|
"compose can only be called on CallCredentials objects");
|
||||||
}
|
}
|
||||||
if (::node::Buffer::HasInstance(info[2])) {
|
if (!CallCredentials::HasInstance(info[0])) {
|
||||||
key_cert_pair.cert_chain = ::node::Buffer::Data(info[2]);
|
|
||||||
} else if (!(info[2]->IsNull() || info[2]->IsUndefined())) {
|
|
||||||
return Nan::ThrowTypeError(
|
return Nan::ThrowTypeError(
|
||||||
"createSSl's third argument must be a Buffer if provided");
|
"compose's first argument must be a CallCredentials object");
|
||||||
}
|
}
|
||||||
grpc_credentials *creds = grpc_ssl_credentials_create(
|
CallCredentials *self = ObjectWrap::Unwrap<CallCredentials>(info.This());
|
||||||
root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair,
|
CallCredentials *other = ObjectWrap::Unwrap<CallCredentials>(
|
||||||
NULL);
|
|
||||||
if (creds == NULL) {
|
|
||||||
info.GetReturnValue().SetNull();
|
|
||||||
} else {
|
|
||||||
info.GetReturnValue().Set(WrapStruct(creds));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NAN_METHOD(Credentials::CreateComposite) {
|
|
||||||
if (!HasInstance(info[0])) {
|
|
||||||
return Nan::ThrowTypeError(
|
|
||||||
"createComposite's first argument must be a Credentials object");
|
|
||||||
}
|
|
||||||
if (!HasInstance(info[1])) {
|
|
||||||
return Nan::ThrowTypeError(
|
|
||||||
"createComposite's second argument must be a Credentials object");
|
|
||||||
}
|
|
||||||
Credentials *creds0 = ObjectWrap::Unwrap<Credentials>(
|
|
||||||
Nan::To<Object>(info[0]).ToLocalChecked());
|
Nan::To<Object>(info[0]).ToLocalChecked());
|
||||||
Credentials *creds1 = ObjectWrap::Unwrap<Credentials>(
|
|
||||||
Nan::To<Object>(info[1]).ToLocalChecked());
|
|
||||||
if (creds0->wrapped_credentials == NULL) {
|
|
||||||
info.GetReturnValue().Set(info[1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (creds1->wrapped_credentials == NULL) {
|
|
||||||
info.GetReturnValue().Set(info[0]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
grpc_credentials *creds = grpc_composite_credentials_create(
|
grpc_credentials *creds = grpc_composite_credentials_create(
|
||||||
creds0->wrapped_credentials, creds1->wrapped_credentials, NULL);
|
self->wrapped_credentials, other->wrapped_credentials, NULL);
|
||||||
if (creds == NULL) {
|
|
||||||
info.GetReturnValue().SetNull();
|
|
||||||
} else {
|
|
||||||
info.GetReturnValue().Set(WrapStruct(creds));
|
info.GetReturnValue().Set(WrapStruct(creds));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(Credentials::CreateInsecure) {
|
|
||||||
info.GetReturnValue().Set(WrapStruct(NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
NAN_METHOD(Credentials::CreateFromPlugin) {
|
|
||||||
|
NAN_METHOD(CallCredentials::CreateFromPlugin) {
|
||||||
if (!info[0]->IsFunction()) {
|
if (!info[0]->IsFunction()) {
|
||||||
return Nan::ThrowTypeError(
|
return Nan::ThrowTypeError(
|
||||||
"createFromPlugin's argument must be a function");
|
"createFromPlugin's argument must be a function");
|
||||||
|
@ -221,11 +171,7 @@ NAN_METHOD(Credentials::CreateFromPlugin) {
|
||||||
plugin.state = reinterpret_cast<void*>(state);
|
plugin.state = reinterpret_cast<void*>(state);
|
||||||
grpc_credentials *creds = grpc_metadata_credentials_create_from_plugin(plugin,
|
grpc_credentials *creds = grpc_metadata_credentials_create_from_plugin(plugin,
|
||||||
NULL);
|
NULL);
|
||||||
if (creds == NULL) {
|
|
||||||
info.GetReturnValue().SetNull();
|
|
||||||
} else {
|
|
||||||
info.GetReturnValue().Set(WrapStruct(creds));
|
info.GetReturnValue().Set(WrapStruct(creds));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(PluginCallback) {
|
NAN_METHOD(PluginCallback) {
|
||||||
|
@ -245,9 +191,6 @@ NAN_METHOD(PluginCallback) {
|
||||||
shared_ptr<Resources> resources(new Resources);
|
shared_ptr<Resources> resources(new Resources);
|
||||||
grpc_status_code code = static_cast<grpc_status_code>(
|
grpc_status_code code = static_cast<grpc_status_code>(
|
||||||
Nan::To<uint32_t>(info[0]).FromJust());
|
Nan::To<uint32_t>(info[0]).FromJust());
|
||||||
//Utf8String details_str(info[1]);
|
|
||||||
//char *details = static_cast<char*>(calloc(details_str.length(), sizeof(char)));
|
|
||||||
//memcpy(details, *details_str, details_str.length());
|
|
||||||
char *details = *Utf8String(info[1]);
|
char *details = *Utf8String(info[1]);
|
||||||
grpc_metadata_array array;
|
grpc_metadata_array array;
|
||||||
if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(),
|
if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(),
|
|
@ -31,19 +31,17 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NET_GRPC_NODE_CREDENTIALS_H_
|
#ifndef GRPC_NODE_CALL_CREDENTIALS_H_
|
||||||
#define NET_GRPC_NODE_CREDENTIALS_H_
|
#define GRPC_NODE_CALL_CREDENTIALS_H_
|
||||||
|
|
||||||
#include <node.h>
|
#include <node.h>
|
||||||
#include <nan.h>
|
#include <nan.h>
|
||||||
#include "grpc/grpc.h"
|
|
||||||
#include "grpc/grpc_security.h"
|
#include "grpc/grpc_security.h"
|
||||||
|
|
||||||
namespace grpc {
|
namespace grpc {
|
||||||
namespace node {
|
namespace node {
|
||||||
|
|
||||||
/* Wrapper class for grpc_credentials structs */
|
class CallCredentials : public Nan::ObjectWrap {
|
||||||
class Credentials : public Nan::ObjectWrap {
|
|
||||||
public:
|
public:
|
||||||
static void Init(v8::Local<v8::Object> exports);
|
static void Init(v8::Local<v8::Object> exports);
|
||||||
static bool HasInstance(v8::Local<v8::Value> val);
|
static bool HasInstance(v8::Local<v8::Value> val);
|
||||||
|
@ -54,18 +52,18 @@ class Credentials : public Nan::ObjectWrap {
|
||||||
grpc_credentials *GetWrappedCredentials();
|
grpc_credentials *GetWrappedCredentials();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Credentials(grpc_credentials *credentials);
|
explicit CallCredentials(grpc_credentials *credentials);
|
||||||
~Credentials();
|
~CallCredentials();
|
||||||
|
|
||||||
// Prevent copying
|
// Prevent copying
|
||||||
Credentials(const Credentials &);
|
CallCredentials(const CallCredentials &);
|
||||||
Credentials &operator=(const Credentials &);
|
CallCredentials &operator=(const CallCredentials &);
|
||||||
|
|
||||||
static NAN_METHOD(New);
|
static NAN_METHOD(New);
|
||||||
static NAN_METHOD(CreateSsl);
|
static NAN_METHOD(CreateSsl);
|
||||||
static NAN_METHOD(CreateComposite);
|
|
||||||
static NAN_METHOD(CreateInsecure);
|
|
||||||
static NAN_METHOD(CreateFromPlugin);
|
static NAN_METHOD(CreateFromPlugin);
|
||||||
|
|
||||||
|
static NAN_METHOD(Compose);
|
||||||
static Nan::Callback *constructor;
|
static Nan::Callback *constructor;
|
||||||
// Used for typechecking instances of this javascript class
|
// Used for typechecking instances of this javascript class
|
||||||
static Nan::Persistent<v8::FunctionTemplate> fun_tpl;
|
static Nan::Persistent<v8::FunctionTemplate> fun_tpl;
|
||||||
|
@ -97,6 +95,6 @@ NAN_METHOD(PluginCallback);
|
||||||
NAUV_WORK_CB(SendPluginCallback);
|
NAUV_WORK_CB(SendPluginCallback);
|
||||||
|
|
||||||
} // namespace node
|
} // namespace node
|
||||||
} // namespace grpc
|
} // namepsace grpc
|
||||||
|
|
||||||
#endif // NET_GRPC_NODE_CREDENTIALS_H_
|
#endif // GRPC_NODE_CALL_CREDENTIALS_H_
|
|
@ -42,7 +42,7 @@
|
||||||
#include "call.h"
|
#include "call.h"
|
||||||
#include "channel.h"
|
#include "channel.h"
|
||||||
#include "completion_queue_async_worker.h"
|
#include "completion_queue_async_worker.h"
|
||||||
#include "credentials.h"
|
#include "channel_credentials.h"
|
||||||
#include "timeval.h"
|
#include "timeval.h"
|
||||||
|
|
||||||
namespace grpc {
|
namespace grpc {
|
||||||
|
@ -112,11 +112,11 @@ NAN_METHOD(Channel::New) {
|
||||||
// Owned by the Channel object
|
// Owned by the Channel object
|
||||||
Utf8String host(info[0]);
|
Utf8String host(info[0]);
|
||||||
grpc_credentials *creds;
|
grpc_credentials *creds;
|
||||||
if (!Credentials::HasInstance(info[1])) {
|
if (!ChannelCredentials::HasInstance(info[1])) {
|
||||||
return Nan::ThrowTypeError(
|
return Nan::ThrowTypeError(
|
||||||
"Channel's second argument must be a credential");
|
"Channel's second argument must be a ChannelCredentials");
|
||||||
}
|
}
|
||||||
Credentials *creds_object = ObjectWrap::Unwrap<Credentials>(
|
ChannelCredentials *creds_object = ObjectWrap::Unwrap<ChannelCredentials>(
|
||||||
Nan::To<Object>(info[1]).ToLocalChecked());
|
Nan::To<Object>(info[1]).ToLocalChecked());
|
||||||
creds = creds_object->GetWrappedCredentials();
|
creds = creds_object->GetWrappedCredentials();
|
||||||
grpc_channel_args *channel_args_ptr;
|
grpc_channel_args *channel_args_ptr;
|
||||||
|
|
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright 2015, Google Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <node.h>
|
||||||
|
|
||||||
|
#include "grpc/grpc.h"
|
||||||
|
#include "grpc/grpc_security.h"
|
||||||
|
#include "grpc/support/log.h"
|
||||||
|
#include "channel_credentials.h"
|
||||||
|
#include "call_credentials.h"
|
||||||
|
#include "call.h"
|
||||||
|
|
||||||
|
namespace grpc {
|
||||||
|
namespace node {
|
||||||
|
|
||||||
|
using Nan::Callback;
|
||||||
|
using Nan::EscapableHandleScope;
|
||||||
|
using Nan::HandleScope;
|
||||||
|
using Nan::Maybe;
|
||||||
|
using Nan::MaybeLocal;
|
||||||
|
using Nan::ObjectWrap;
|
||||||
|
using Nan::Persistent;
|
||||||
|
using Nan::Utf8String;
|
||||||
|
|
||||||
|
using v8::Exception;
|
||||||
|
using v8::External;
|
||||||
|
using v8::Function;
|
||||||
|
using v8::FunctionTemplate;
|
||||||
|
using v8::Integer;
|
||||||
|
using v8::Local;
|
||||||
|
using v8::Object;
|
||||||
|
using v8::ObjectTemplate;
|
||||||
|
using v8::Value;
|
||||||
|
|
||||||
|
Nan::Callback *ChannelCredentials::constructor;
|
||||||
|
Persistent<FunctionTemplate> ChannelCredentials::fun_tpl;
|
||||||
|
|
||||||
|
ChannelCredentials::ChannelCredentials(grpc_credentials *credentials)
|
||||||
|
: wrapped_credentials(credentials) {}
|
||||||
|
|
||||||
|
ChannelCredentials::~ChannelCredentials() {
|
||||||
|
grpc_credentials_release(wrapped_credentials);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChannelCredentials::Init(Local<Object> exports) {
|
||||||
|
HandleScope scope;
|
||||||
|
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
|
||||||
|
tpl->SetClassName(Nan::New("ChannelCredentials").ToLocalChecked());
|
||||||
|
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
|
Nan::SetPrototypeMethod(tpl, "compose", Compose);
|
||||||
|
fun_tpl.Reset(tpl);
|
||||||
|
Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked();
|
||||||
|
Nan::Set(ctr, Nan::New("createSsl").ToLocalChecked(),
|
||||||
|
Nan::GetFunction(
|
||||||
|
Nan::New<FunctionTemplate>(CreateSsl)).ToLocalChecked());
|
||||||
|
Nan::Set(ctr, Nan::New("createInsecure").ToLocalChecked(),
|
||||||
|
Nan::GetFunction(
|
||||||
|
Nan::New<FunctionTemplate>(CreateInsecure)).ToLocalChecked());
|
||||||
|
Nan::Set(exports, Nan::New("ChannelCredentials").ToLocalChecked(), ctr);
|
||||||
|
constructor = new Nan::Callback(ctr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChannelCredentials::HasInstance(Local<Value> val) {
|
||||||
|
HandleScope scope;
|
||||||
|
return Nan::New(fun_tpl)->HasInstance(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Local<Value> ChannelCredentials::WrapStruct(grpc_credentials *credentials) {
|
||||||
|
EscapableHandleScope scope;
|
||||||
|
const int argc = 1;
|
||||||
|
Local<Value> argv[argc] = {
|
||||||
|
Nan::New<External>(reinterpret_cast<void *>(credentials))};
|
||||||
|
MaybeLocal<Object> maybe_instance = Nan::NewInstance(
|
||||||
|
constructor->GetFunction(), argc, argv);
|
||||||
|
if (maybe_instance.IsEmpty()) {
|
||||||
|
return scope.Escape(Nan::Null());
|
||||||
|
} else {
|
||||||
|
return scope.Escape(maybe_instance.ToLocalChecked());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grpc_credentials *ChannelCredentials::GetWrappedCredentials() {
|
||||||
|
return wrapped_credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
NAN_METHOD(ChannelCredentials::New) {
|
||||||
|
if (info.IsConstructCall()) {
|
||||||
|
if (!info[0]->IsExternal()) {
|
||||||
|
return Nan::ThrowTypeError(
|
||||||
|
"ChannelCredentials can only be created with the provided functions");
|
||||||
|
}
|
||||||
|
Local<External> ext = info[0].As<External>();
|
||||||
|
grpc_credentials *creds_value =
|
||||||
|
reinterpret_cast<grpc_credentials *>(ext->Value());
|
||||||
|
ChannelCredentials *credentials = new ChannelCredentials(creds_value);
|
||||||
|
credentials->Wrap(info.This());
|
||||||
|
info.GetReturnValue().Set(info.This());
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const int argc = 1;
|
||||||
|
Local<Value> argv[argc] = {info[0]};
|
||||||
|
MaybeLocal<Object> maybe_instance = constructor->GetFunction()->NewInstance(
|
||||||
|
argc, argv);
|
||||||
|
if (maybe_instance.IsEmpty()) {
|
||||||
|
// There's probably a pending exception
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
info.GetReturnValue().Set(maybe_instance.ToLocalChecked());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NAN_METHOD(ChannelCredentials::CreateSsl) {
|
||||||
|
char *root_certs = NULL;
|
||||||
|
grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL};
|
||||||
|
if (::node::Buffer::HasInstance(info[0])) {
|
||||||
|
root_certs = ::node::Buffer::Data(info[0]);
|
||||||
|
} else if (!(info[0]->IsNull() || info[0]->IsUndefined())) {
|
||||||
|
return Nan::ThrowTypeError("createSsl's first argument must be a Buffer");
|
||||||
|
}
|
||||||
|
if (::node::Buffer::HasInstance(info[1])) {
|
||||||
|
key_cert_pair.private_key = ::node::Buffer::Data(info[1]);
|
||||||
|
} else if (!(info[1]->IsNull() || info[1]->IsUndefined())) {
|
||||||
|
return Nan::ThrowTypeError(
|
||||||
|
"createSSl's second argument must be a Buffer if provided");
|
||||||
|
}
|
||||||
|
if (::node::Buffer::HasInstance(info[2])) {
|
||||||
|
key_cert_pair.cert_chain = ::node::Buffer::Data(info[2]);
|
||||||
|
} else if (!(info[2]->IsNull() || info[2]->IsUndefined())) {
|
||||||
|
return Nan::ThrowTypeError(
|
||||||
|
"createSSl's third argument must be a Buffer if provided");
|
||||||
|
}
|
||||||
|
grpc_credentials *creds = grpc_ssl_credentials_create(
|
||||||
|
root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair,
|
||||||
|
NULL);
|
||||||
|
if (creds == NULL) {
|
||||||
|
info.GetReturnValue().SetNull();
|
||||||
|
} else {
|
||||||
|
info.GetReturnValue().Set(WrapStruct(creds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NAN_METHOD(ChannelCredentials::Compose) {
|
||||||
|
if (!ChannelCredentials::HasInstance(info.This())) {
|
||||||
|
return Nan::ThrowTypeError(
|
||||||
|
"compose can only be called on ChannelCredentials objects");
|
||||||
|
}
|
||||||
|
if (!CallCredentials::HasInstance(info[0])) {
|
||||||
|
return Nan::ThrowTypeError(
|
||||||
|
"compose's first argument must be a CallCredentials object");
|
||||||
|
}
|
||||||
|
ChannelCredentials *self = ObjectWrap::Unwrap<ChannelCredentials>(
|
||||||
|
info.This());
|
||||||
|
CallCredentials *other = ObjectWrap::Unwrap<CallCredentials>(
|
||||||
|
Nan::To<Object>(info[0]).ToLocalChecked());
|
||||||
|
grpc_credentials *creds = grpc_composite_credentials_create(
|
||||||
|
self->wrapped_credentials, other->GetWrappedCredentials(), NULL);
|
||||||
|
if (creds == NULL) {
|
||||||
|
info.GetReturnValue().SetNull();
|
||||||
|
} else {
|
||||||
|
info.GetReturnValue().Set(WrapStruct(creds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NAN_METHOD(ChannelCredentials::CreateInsecure) {
|
||||||
|
info.GetReturnValue().Set(WrapStruct(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace node
|
||||||
|
} // namespace grpc
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright 2015, Google Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following disclaimer
|
||||||
|
* in the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Google Inc. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NET_GRPC_NODE_CHANNEL_CREDENTIALS_H_
|
||||||
|
#define NET_GRPC_NODE_CHANNEL_CREDENTIALS_H_
|
||||||
|
|
||||||
|
#include <node.h>
|
||||||
|
#include <nan.h>
|
||||||
|
#include "grpc/grpc.h"
|
||||||
|
#include "grpc/grpc_security.h"
|
||||||
|
|
||||||
|
namespace grpc {
|
||||||
|
namespace node {
|
||||||
|
|
||||||
|
/* Wrapper class for grpc_credentials structs */
|
||||||
|
class ChannelCredentials : public Nan::ObjectWrap {
|
||||||
|
public:
|
||||||
|
static void Init(v8::Local<v8::Object> exports);
|
||||||
|
static bool HasInstance(v8::Local<v8::Value> val);
|
||||||
|
/* Wrap a grpc_credentials struct in a javascript object */
|
||||||
|
static v8::Local<v8::Value> WrapStruct(grpc_credentials *credentials);
|
||||||
|
|
||||||
|
/* Returns the grpc_credentials struct that this object wraps */
|
||||||
|
grpc_credentials *GetWrappedCredentials();
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit ChannelCredentials(grpc_credentials *credentials);
|
||||||
|
~ChannelCredentials();
|
||||||
|
|
||||||
|
// Prevent copying
|
||||||
|
ChannelCredentials(const ChannelCredentials &);
|
||||||
|
ChannelCredentials &operator=(const ChannelCredentials &);
|
||||||
|
|
||||||
|
static NAN_METHOD(New);
|
||||||
|
static NAN_METHOD(CreateSsl);
|
||||||
|
static NAN_METHOD(CreateInsecure);
|
||||||
|
|
||||||
|
static NAN_METHOD(Compose);
|
||||||
|
static Nan::Callback *constructor;
|
||||||
|
// Used for typechecking instances of this javascript class
|
||||||
|
static Nan::Persistent<v8::FunctionTemplate> fun_tpl;
|
||||||
|
|
||||||
|
grpc_credentials *wrapped_credentials;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace node
|
||||||
|
} // namespace grpc
|
||||||
|
|
||||||
|
#endif // NET_GRPC_NODE_CHANNEL_CREDENTIALS_H_
|
|
@ -37,10 +37,11 @@
|
||||||
#include "grpc/grpc.h"
|
#include "grpc/grpc.h"
|
||||||
|
|
||||||
#include "call.h"
|
#include "call.h"
|
||||||
|
#include "call_credentials.h"
|
||||||
#include "channel.h"
|
#include "channel.h"
|
||||||
|
#include "channel_credentials.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "completion_queue_async_worker.h"
|
#include "completion_queue_async_worker.h"
|
||||||
#include "credentials.h"
|
|
||||||
#include "server_credentials.h"
|
#include "server_credentials.h"
|
||||||
|
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
|
@ -240,10 +241,11 @@ void init(Local<Object> exports) {
|
||||||
InitWriteFlags(exports);
|
InitWriteFlags(exports);
|
||||||
|
|
||||||
grpc::node::Call::Init(exports);
|
grpc::node::Call::Init(exports);
|
||||||
|
grpc::node::CallCredentials::Init(exports);
|
||||||
grpc::node::Channel::Init(exports);
|
grpc::node::Channel::Init(exports);
|
||||||
|
grpc::node::ChannelCredentials::Init(exports);
|
||||||
grpc::node::Server::Init(exports);
|
grpc::node::Server::Init(exports);
|
||||||
grpc::node::CompletionQueueAsyncWorker::Init(exports);
|
grpc::node::CompletionQueueAsyncWorker::Init(exports);
|
||||||
grpc::node::Credentials::Init(exports);
|
|
||||||
grpc::node::ServerCredentials::Init(exports);
|
grpc::node::ServerCredentials::Init(exports);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -460,7 +460,8 @@ function runTest(address, host_override, test_case, tls, test_ca, done) {
|
||||||
|
|
||||||
if (test.getCreds) {
|
if (test.getCreds) {
|
||||||
test.getCreds(function(err, new_creds) {
|
test.getCreds(function(err, new_creds) {
|
||||||
execute(err, grpc.credentials.combineCredentials(creds, new_creds));
|
execute(err, grpc.credentials.combineChannelCredentials(
|
||||||
|
creds, new_creds));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
execute(null, creds);
|
execute(null, creds);
|
||||||
|
|
|
@ -40,7 +40,9 @@
|
||||||
|
|
||||||
var grpc = require('bindings')('grpc.node');
|
var grpc = require('bindings')('grpc.node');
|
||||||
|
|
||||||
var Credentials = grpc.Credentials;
|
var CallCredentials = grpc.CallCredentials;
|
||||||
|
|
||||||
|
var ChannelCredentials = grpc.ChannelCredentials;
|
||||||
|
|
||||||
var Metadata = require('./metadata.js');
|
var Metadata = require('./metadata.js');
|
||||||
|
|
||||||
|
@ -51,8 +53,9 @@ var Metadata = require('./metadata.js');
|
||||||
* @param {Buffer=} private_key The client certificate private key, if
|
* @param {Buffer=} private_key The client certificate private key, if
|
||||||
* applicable
|
* applicable
|
||||||
* @param {Buffer=} cert_chain The client certificate cert chain, if applicable
|
* @param {Buffer=} cert_chain The client certificate cert chain, if applicable
|
||||||
|
* @return {ChannelCredentials} The SSL Credentials object
|
||||||
*/
|
*/
|
||||||
exports.createSsl = Credentials.createSsl;
|
exports.createSsl = ChannelCredentials.createSsl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a gRPC credentials object from a metadata generation function. This
|
* Create a gRPC credentials object from a metadata generation function. This
|
||||||
|
@ -61,10 +64,10 @@ exports.createSsl = Credentials.createSsl;
|
||||||
* which corresponds to a status code that this library uses.
|
* which corresponds to a status code that this library uses.
|
||||||
* @param {function(String, function(Error, Metadata))} metadata_generator The
|
* @param {function(String, function(Error, Metadata))} metadata_generator The
|
||||||
* function that generates metadata
|
* function that generates metadata
|
||||||
* @return {Credentials} The credentials object
|
* @return {CallCredentials} The credentials object
|
||||||
*/
|
*/
|
||||||
exports.createFromMetadataGenerator = function(metadata_generator) {
|
exports.createFromMetadataGenerator = function(metadata_generator) {
|
||||||
return Credentials.createFromPlugin(function(service_url, callback) {
|
return CallCredentials.createFromPlugin(function(service_url, callback) {
|
||||||
metadata_generator(service_url, function(error, metadata) {
|
metadata_generator(service_url, function(error, metadata) {
|
||||||
var code = grpc.status.OK;
|
var code = grpc.status.OK;
|
||||||
var message = '';
|
var message = '';
|
||||||
|
@ -82,7 +85,7 @@ exports.createFromMetadataGenerator = function(metadata_generator) {
|
||||||
/**
|
/**
|
||||||
* Create a gRPC credential from a Google credential object.
|
* Create a gRPC credential from a Google credential object.
|
||||||
* @param {Object} google_credential The Google credential object to use
|
* @param {Object} google_credential The Google credential object to use
|
||||||
* @return {Credentials} The resulting credentials object
|
* @return {CallCredentials} The resulting credentials object
|
||||||
*/
|
*/
|
||||||
exports.createFromGoogleCredential = function(google_credential) {
|
exports.createFromGoogleCredential = function(google_credential) {
|
||||||
return exports.createFromMetadataGenerator(function(service_url, callback) {
|
return exports.createFromMetadataGenerator(function(service_url, callback) {
|
||||||
|
@ -99,22 +102,39 @@ exports.createFromGoogleCredential = function(google_credential) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combine any number of Credentials into a single credentials object
|
* Combine a ChannelCredentials with any number of CallCredentials into a single
|
||||||
* @param(...Credentials) credentials The Credentials to combine
|
* ChannelCredentials object.
|
||||||
* @return Credentials A credentials object that combines all of the input
|
* @param {ChannelCredentials} channel_credential The ChannelCredentials to
|
||||||
* credentials
|
* start with
|
||||||
|
* @param {...CallCredentials} credentials The CallCredentials to compose
|
||||||
|
* @return ChannelCredentials A credentials object that combines all of the
|
||||||
|
* input credentials
|
||||||
*/
|
*/
|
||||||
exports.combineCredentials = function() {
|
exports.combineChannelCredentials = function(channel_credential) {
|
||||||
var current = arguments[0];
|
var current = channel_credential;
|
||||||
for (var i = 1; i < arguments.length; i++) {
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
current = Credentials.createComposite(current, arguments[i]);
|
current = current.compose(arguments[i]);
|
||||||
}
|
}
|
||||||
return current;
|
return current;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combine any number of CallCredentials into a single CallCredentials object
|
||||||
|
* @param {...CallCredentials} credentials the CallCredentials to compose
|
||||||
|
* @return CallCredentials A credentials object that combines all of the input
|
||||||
|
* credentials
|
||||||
|
*/
|
||||||
|
exports.combineCallCredentials = function() {
|
||||||
|
var current = arguments[0];
|
||||||
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
|
current = current.compose(arguments[i]);
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an insecure credentials object. This is used to create a channel that
|
* Create an insecure credentials object. This is used to create a channel that
|
||||||
* does not use SSL.
|
* does not use SSL.
|
||||||
* @return Credentials The insecure credentials object
|
* @return {ChannelCredentials} The insecure credentials object
|
||||||
*/
|
*/
|
||||||
exports.createInsecure = Credentials.createInsecure;
|
exports.createInsecure = ChannelCredentials.createInsecure;
|
||||||
|
|
|
@ -48,7 +48,7 @@ function getDeadline(timeout_secs) {
|
||||||
return deadline;
|
return deadline;
|
||||||
}
|
}
|
||||||
|
|
||||||
var insecureCreds = grpc.Credentials.createInsecure();
|
var insecureCreds = grpc.ChannelCredentials.createInsecure();
|
||||||
|
|
||||||
describe('call', function() {
|
describe('call', function() {
|
||||||
var channel;
|
var channel;
|
||||||
|
|
|
@ -56,7 +56,7 @@ function multiDone(done, count) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
var insecureCreds = grpc.Credentials.createInsecure();
|
var insecureCreds = grpc.ChannelCredentials.createInsecure();
|
||||||
|
|
||||||
describe('channel', function() {
|
describe('channel', function() {
|
||||||
describe('constructor', function() {
|
describe('constructor', function() {
|
||||||
|
|
|
@ -219,5 +219,25 @@ describe('client credentials', function() {
|
||||||
});
|
});
|
||||||
call.end();
|
call.end();
|
||||||
});
|
});
|
||||||
|
it('should be able to use multiple plugin credentials', function(done) {
|
||||||
|
var altMetadataUpdater = function(service_url, callback) {
|
||||||
|
var metadata = new grpc.Metadata();
|
||||||
|
metadata.set('other_plugin_key', 'other_plugin_value');
|
||||||
|
callback(null, metadata);
|
||||||
|
};
|
||||||
|
var alt_updater_creds = grpc.credentials.createFromMetadataGenerator(
|
||||||
|
altMetadataUpdater);
|
||||||
|
var combined_updater = grpc.credentials.combineCallCredentials(
|
||||||
|
updater_creds, alt_updater_creds);
|
||||||
|
var call = client.unary({}, function(err, data) {
|
||||||
|
assert.ifError(err);
|
||||||
|
}, null, {credentials: updater_creds});
|
||||||
|
call.on('metadata', function(metadata) {
|
||||||
|
assert.deepEqual(metadata.get('plugin_key'), ['plugin_value']);
|
||||||
|
assert.deepEqual(metadata.get('other_plugin_key'),
|
||||||
|
['other_plugin_value']);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -57,7 +57,7 @@ function multiDone(done, count) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var insecureCreds = grpc.Credentials.createInsecure();
|
var insecureCreds = grpc.ChannelCredentials.createInsecure();
|
||||||
|
|
||||||
describe('end-to-end', function() {
|
describe('end-to-end', function() {
|
||||||
var server;
|
var server;
|
||||||
|
|
Loading…
Reference in New Issue