Skip to content

Commit 009d76c

Browse files
support custom API host and port configuration. fixes #389
1 parent 6938342 commit 009d76c

File tree

8 files changed

+150
-52
lines changed

8 files changed

+150
-52
lines changed

lib/common/util.js

+8
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,14 @@ function makeAuthorizedRequest(config) {
380380

381381
var authorize = gsa(config);
382382

383+
if (config.customApi) {
384+
// Using a custom API override. Do not use `google-service-account` for
385+
// authentication. (ex: connecting to a local Datastore server)
386+
authorize = function(reqOpts, callback) {
387+
callback(null, reqOpts);
388+
};
389+
}
390+
383391
function makeRequest(reqOpts, callback) {
384392
var tokenRefreshAttempts = 0;
385393
reqOpts.headers = reqOpts.headers || {};

lib/datastore/dataset.js

+14
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ var SCOPES = [
7878
* `credentials` object.
7979
* @param {object=} options.credentials - Credentials object, used in place of
8080
* a `keyFilename`.
81+
* @param {string=} options.host - Override the default API endpoint used to
82+
* reach the Datastore. This is useful for connecting to your local
83+
* Datastore server.
84+
* @param {number=} options.port - Useful with `options.host` to set the port.
8185
* @param {string} options.namespace - Namespace to isolate transactions to.
8286
*
8387
* @example
@@ -93,12 +97,22 @@ function Dataset(options) {
9397

9498
options = options || {};
9599

100+
if (options.host && options.host.indexOf('http') !== 0) {
101+
throw new Error('A protocol must be included when specifying a host.');
102+
}
103+
96104
this.makeAuthorizedRequest_ = util.makeAuthorizedRequest({
105+
customApi: typeof options.host !== 'undefined',
97106
credentials: options.credentials,
98107
keyFile: options.keyFilename,
99108
scopes: SCOPES
100109
});
101110

111+
this.api = {
112+
host: options.host || 'https://www.googleapis.com',
113+
port: util.is(options.port, 'number') ? options.port : 443
114+
};
115+
102116
this.namespace = options.namespace;
103117
this.projectId = options.projectId;
104118
}

lib/datastore/request.js

+18-13
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020

2121
'use strict';
2222

23-
var https = require('https');
2423
var streamEvents = require('stream-events');
24+
var request = require('request');
2525
var through = require('through2');
2626

2727
/**
@@ -42,12 +42,6 @@ var pb = require('./pb.js');
4242
*/
4343
var util = require('../common/util.js');
4444

45-
/**
46-
* @const {string} Host to send with API requests.
47-
* @private
48-
*/
49-
var GOOGLE_APIS_HOST = 'www.googleapis.com';
50-
5145
/**
5246
* @const {string} Non-transaction mode key.
5347
* @private
@@ -595,8 +589,13 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) {
595589

596590
var reqOpts = {
597591
method: 'POST',
598-
host: GOOGLE_APIS_HOST,
599-
path: '/datastore/v1beta2/datasets/' + this.projectId + '/' + method,
592+
uri: util.format('{host}:{port}/{path}/{projectId}/{method}', {
593+
host: this.api.host,
594+
port: this.api.port,
595+
path: 'datastore/v1beta2/datasets',
596+
projectId: this.projectId,
597+
method: method
598+
}),
600599
headers: {
601600
'Content-Type': 'application/x-protobuf'
602601
}
@@ -609,7 +608,14 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) {
609608
return;
610609
}
611610

612-
var remoteStream = https.request(authorizedReqOpts, function(resp) {
611+
authorizedReqOpts.headers = authorizedReqOpts.headers || {};
612+
authorizedReqOpts.headers['Content-Length'] = pbRequest.length;
613+
614+
var apiRequest = request(authorizedReqOpts);
615+
616+
apiRequest.on('error', callback);
617+
618+
apiRequest.on('response', function(resp) {
613619
var buffer = new Buffer('');
614620
resp.on('data', function(chunk) {
615621
buffer = Buffer.concat([buffer, chunk]);
@@ -624,9 +630,8 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) {
624630
});
625631
});
626632
});
627-
remoteStream.on('error', callback);
628-
remoteStream.write(pbRequest);
629-
remoteStream.end();
633+
634+
apiRequest.end(pbRequest);
630635
}
631636
});
632637
};

lib/datastore/transaction.js

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ var extend = require('extend');
6161
*/
6262
function Transaction(dataset, projectId) {
6363
this.id = null;
64+
this.api = dataset.api;
6465
this.makeAuthorizedRequest_ = dataset.makeAuthorizedRequest_;
6566
this.projectId = projectId;
6667

test/common/util.js

+25-8
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,25 @@ describe('common/util', function() {
299299
util.makeAuthorizedRequest(config);
300300
});
301301

302+
it('should not authenticate requests with a custom API', function(done) {
303+
var makeRequest = util.makeAuthorizedRequest({ customApi: true });
304+
305+
var gsaCalled = false;
306+
gsa_Override = function() {
307+
gsaCalled = true;
308+
};
309+
310+
makeRequest({}, {
311+
onAuthorized: function(err) {
312+
assert.ifError(err);
313+
assert.strictEqual(gsaCalled, false);
314+
done();
315+
}
316+
});
317+
});
318+
302319
it('should return gsa.getCredentials function', function() {
303-
var getCredentials = util.makeAuthorizedRequest().getCredentials;
320+
var getCredentials = util.makeAuthorizedRequest({}).getCredentials;
304321
assert.equal(typeof getCredentials, 'function');
305322
});
306323

@@ -313,7 +330,7 @@ describe('common/util', function() {
313330
};
314331
};
315332

316-
var makeRequest = util.makeAuthorizedRequest();
333+
var makeRequest = util.makeAuthorizedRequest({});
317334
makeRequest({});
318335
});
319336

@@ -326,7 +343,7 @@ describe('common/util', function() {
326343
};
327344
};
328345

329-
var makeRequest = util.makeAuthorizedRequest();
346+
var makeRequest = util.makeAuthorizedRequest({});
330347
makeRequest({ headers: { 'User-Agent': 'test' } });
331348
});
332349

@@ -339,7 +356,7 @@ describe('common/util', function() {
339356
};
340357
};
341358

342-
var makeRequest = util.makeAuthorizedRequest();
359+
var makeRequest = util.makeAuthorizedRequest({});
343360
makeRequest({}, function(err) {
344361
assert.equal(err, error);
345362
done();
@@ -392,7 +409,7 @@ describe('common/util', function() {
392409
};
393410
};
394411

395-
var makeRequest = util.makeAuthorizedRequest();
412+
var makeRequest = util.makeAuthorizedRequest({});
396413
makeRequest({}, function (err) {
397414
assert.equal(attempts, expectedAttempts);
398415
assert.equal(err, error);
@@ -407,7 +424,7 @@ describe('common/util', function() {
407424
};
408425
};
409426

410-
var makeRequest = util.makeAuthorizedRequest();
427+
var makeRequest = util.makeAuthorizedRequest({});
411428
makeRequest({}, { onAuthorized: done });
412429
});
413430

@@ -420,7 +437,7 @@ describe('common/util', function() {
420437
};
421438
};
422439

423-
var makeRequest = util.makeAuthorizedRequest();
440+
var makeRequest = util.makeAuthorizedRequest({});
424441
makeRequest({}, {
425442
onAuthorized: function(err) {
426443
assert.equal(err, error);
@@ -443,7 +460,7 @@ describe('common/util', function() {
443460
done();
444461
};
445462

446-
var makeRequest = util.makeAuthorizedRequest();
463+
var makeRequest = util.makeAuthorizedRequest({});
447464
makeRequest({}, assert.ifError);
448465
});
449466
});

test/datastore/dataset.js

+14
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@ var Dataset = require('../../lib/datastore/dataset');
2323
var util = require('../../lib/common/util.js');
2424

2525
describe('Dataset', function() {
26+
describe('instantiation', function() {
27+
it('should set default API connection details', function() {
28+
var ds = new Dataset();
29+
assert.equal(ds.api.host, 'https://www.googleapis.com');
30+
assert.equal(ds.api.port, 443);
31+
});
32+
33+
it('should set API connection details', function() {
34+
var ds = new Dataset({ host: 'http://localhost', port: 8080 });
35+
assert.equal(ds.api.host, 'http://localhost');
36+
assert.equal(ds.api.port, 8080);
37+
});
38+
});
39+
2640
describe('key', function() {
2741
it('should return key scoped by default namespace', function() {
2842
var ds = new Dataset({ projectId: 'test', namespace: 'my-ns' });

0 commit comments

Comments
 (0)