Skip to content

Commit

Permalink
Merge pull request #407 from stephenplusplus/spp--support-local-datas…
Browse files Browse the repository at this point in the history
…tore

support local datastore
  • Loading branch information
ryanseys committed Feb 24, 2015
2 parents 19ca624 + 78358d4 commit fe10aa5
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 53 deletions.
12 changes: 11 additions & 1 deletion lib/common/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,17 @@ function makeAuthorizedRequest(config) {
'\n'
].join('');

var authorize = gsa(config);
var authorize;

if (config.customEndpoint) {
// Using a custom API override. Do not use `google-service-account` for
// authentication. (ex: connecting to a local Datastore server)
authorize = function(reqOpts, callback) {
callback(null, reqOpts);
};
} else {
authorize = gsa(config);
}

function makeRequest(reqOpts, callback) {
var tokenRefreshAttempts = 0;
Expand Down
19 changes: 19 additions & 0 deletions lib/datastore/dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,24 @@ var SCOPES = [
* `credentials` object.
* @param {object=} options.credentials - Credentials object, used in place of
* a `keyFilename`.
* @param {string=} options.apiEndpoint - Override the default API endpoint used
* to reach Datastore. This is useful for connecting to your local Datastore
* server (usually "http://localhost:8080").
* @param {string} options.namespace - Namespace to isolate transactions to.
*
* @example
* var dataset = datastore.dataset({
* projectId: 'my-project',
* keyFilename: '/path/to/keyfile.json'
* });
*
* //-
* // Connect to your local Datastore server.
* //-
* var dataset = datastore.dataset({
* projectId: 'my-project',
* apiEndpoint: 'http://localhost:8080'
* });
*/
function Dataset(options) {
if (!(this instanceof Dataset)) {
Expand All @@ -94,11 +105,19 @@ function Dataset(options) {
options = options || {};

this.makeAuthorizedRequest_ = util.makeAuthorizedRequest({
customEndpoint: typeof options.apiEndpoint !== 'undefined',
credentials: options.credentials,
keyFile: options.keyFilename,
scopes: SCOPES
});

if (options.apiEndpoint && options.apiEndpoint.indexOf('http') !== 0) {
options.apiEndpoint = 'http://' + options.apiEndpoint;
}

this.apiEndpoint = options.apiEndpoint || 'https://www.googleapis.com';
this.apiEndpoint = this.apiEndpoint.replace(/\/*$/, '');

this.namespace = options.namespace;
this.projectId = options.projectId;
}
Expand Down
30 changes: 17 additions & 13 deletions lib/datastore/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@

'use strict';

var https = require('https');
var streamEvents = require('stream-events');
var request = require('request');
var through = require('through2');

/**
Expand All @@ -42,12 +42,6 @@ var pb = require('./pb.js');
*/
var util = require('../common/util.js');

/**
* @const {string} Host to send with API requests.
* @private
*/
var GOOGLE_APIS_HOST = 'www.googleapis.com';

/**
* @const {string} Non-transaction mode key.
* @private
Expand Down Expand Up @@ -595,8 +589,12 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) {

var reqOpts = {
method: 'POST',
host: GOOGLE_APIS_HOST,
path: '/datastore/v1beta2/datasets/' + this.projectId + '/' + method,
uri: util.format('{apiEndpoint}/{path}/{projectId}/{method}', {
apiEndpoint: this.apiEndpoint,
path: 'datastore/v1beta2/datasets',
projectId: this.projectId,
method: method
}),
headers: {
'Content-Type': 'application/x-protobuf'
}
Expand All @@ -609,7 +607,14 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) {
return;
}

var remoteStream = https.request(authorizedReqOpts, function(resp) {
authorizedReqOpts.headers = authorizedReqOpts.headers || {};
authorizedReqOpts.headers['Content-Length'] = pbRequest.length;

var apiRequest = request(authorizedReqOpts);

apiRequest.on('error', callback);

apiRequest.on('response', function(resp) {
var buffer = new Buffer('');
resp.on('data', function(chunk) {
buffer = Buffer.concat([buffer, chunk]);
Expand All @@ -624,9 +629,8 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) {
});
});
});
remoteStream.on('error', callback);
remoteStream.write(pbRequest);
remoteStream.end();

apiRequest.end(pbRequest);
}
});
};
Expand Down
1 change: 1 addition & 0 deletions lib/datastore/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ var extend = require('extend');
*/
function Transaction(dataset, projectId) {
this.id = null;
this.apiEndpoint = dataset.apiEndpoint;
this.makeAuthorizedRequest_ = dataset.makeAuthorizedRequest_;
this.projectId = projectId;

Expand Down
33 changes: 25 additions & 8 deletions test/common/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,25 @@ describe('common/util', function() {
util.makeAuthorizedRequest(config);
});

it('should not authenticate requests with a custom API', function(done) {
var makeRequest = util.makeAuthorizedRequest({ customEndpoint: true });

var gsaCalled = false;
gsa_Override = function() {
gsaCalled = true;
};

makeRequest({}, {
onAuthorized: function(err) {
assert.ifError(err);
assert.strictEqual(gsaCalled, false);
done();
}
});
});

it('should return gsa.getCredentials function', function() {
var getCredentials = util.makeAuthorizedRequest().getCredentials;
var getCredentials = util.makeAuthorizedRequest({}).getCredentials;
assert.equal(typeof getCredentials, 'function');
});

Expand All @@ -313,7 +330,7 @@ describe('common/util', function() {
};
};

var makeRequest = util.makeAuthorizedRequest();
var makeRequest = util.makeAuthorizedRequest({});
makeRequest({});
});

Expand All @@ -326,7 +343,7 @@ describe('common/util', function() {
};
};

var makeRequest = util.makeAuthorizedRequest();
var makeRequest = util.makeAuthorizedRequest({});
makeRequest({ headers: { 'User-Agent': 'test' } });
});

Expand All @@ -339,7 +356,7 @@ describe('common/util', function() {
};
};

var makeRequest = util.makeAuthorizedRequest();
var makeRequest = util.makeAuthorizedRequest({});
makeRequest({}, function(err) {
assert.equal(err, error);
done();
Expand Down Expand Up @@ -392,7 +409,7 @@ describe('common/util', function() {
};
};

var makeRequest = util.makeAuthorizedRequest();
var makeRequest = util.makeAuthorizedRequest({});
makeRequest({}, function (err) {
assert.equal(attempts, expectedAttempts);
assert.equal(err, error);
Expand All @@ -407,7 +424,7 @@ describe('common/util', function() {
};
};

var makeRequest = util.makeAuthorizedRequest();
var makeRequest = util.makeAuthorizedRequest({});
makeRequest({}, { onAuthorized: done });
});

Expand All @@ -420,7 +437,7 @@ describe('common/util', function() {
};
};

var makeRequest = util.makeAuthorizedRequest();
var makeRequest = util.makeAuthorizedRequest({});
makeRequest({}, {
onAuthorized: function(err) {
assert.equal(err, error);
Expand All @@ -443,7 +460,7 @@ describe('common/util', function() {
done();
};

var makeRequest = util.makeAuthorizedRequest();
var makeRequest = util.makeAuthorizedRequest({});
makeRequest({}, assert.ifError);
});
});
Expand Down
27 changes: 27 additions & 0 deletions test/datastore/dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,33 @@ var Dataset = require('../../lib/datastore/dataset');
var util = require('../../lib/common/util.js');

describe('Dataset', function() {
describe('instantiation', function() {
it('should set default API connection details', function() {
var ds = new Dataset();
assert.equal(ds.apiEndpoint, 'https://www.googleapis.com');
});

it('should set API connection details', function() {
var ds = new Dataset({ apiEndpoint: 'http://localhost:8080' });
assert.equal(ds.apiEndpoint, 'http://localhost:8080');
});

it('should remove slashes from the apiEndpoint', function() {
var ds1 = new Dataset({ apiEndpoint: 'http://localhost:8080' });
var ds2 = new Dataset({ apiEndpoint: 'http://localhost:8080/' });
var ds3 = new Dataset({ apiEndpoint: 'http://localhost:8080//' });

assert.equal(ds1.apiEndpoint, 'http://localhost:8080');
assert.equal(ds2.apiEndpoint, 'http://localhost:8080');
assert.equal(ds3.apiEndpoint, 'http://localhost:8080');
});

it('should default to http if protocol is unspecified', function() {
var ds = new Dataset({ apiEndpoint: 'localhost:8080' });
assert.equal(ds.apiEndpoint, 'http://localhost:8080');
});
});

describe('key', function() {
it('should return key scoped by default namespace', function() {
var ds = new Dataset({ projectId: 'test', namespace: 'my-ns' });
Expand Down
Loading

0 comments on commit fe10aa5

Please sign in to comment.