Skip to content

Commit a11254b

Browse files
integrate support for GAE dev
1 parent cd9487a commit a11254b

File tree

4 files changed

+111
-18
lines changed

4 files changed

+111
-18
lines changed

lib/common/util.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,21 @@ function makeWritableStream(dup, options, onComplete) {
344344
module.exports.makeWritableStream = makeWritableStream;
345345

346346
function makeAuthorizedRequest(config) {
347-
var GAE_OR_GCE = !config || (!config.credentials && !config.keyFile);
347+
var ENV = {
348+
GAE_DEV: process.env.GAE_LONG_APP_ID && !process.env.GAE_VM,
349+
NO_CREDENTIALS: !config || (!config.credentials && !config.keyFile)
350+
};
351+
352+
var authorize;
353+
354+
if (ENV.GAE_DEV && ENV.NO_CREDENTIALS) {
355+
// Google App Engine Development mode doesn't require authorization.
356+
authorize = function(reqOpts, callback) {
357+
callback(null, reqOpts);
358+
};
359+
} else {
360+
authorize = gsa(config);
361+
}
348362

349363
var missingCredentialsError = new Error();
350364
missingCredentialsError.message = [
@@ -357,8 +371,6 @@ function makeAuthorizedRequest(config) {
357371
'\n'
358372
].join('');
359373

360-
var authorize = gsa(config);
361-
362374
function makeRequest(reqOpts, callback) {
363375
var tokenRefreshAttempts = 0;
364376
reqOpts.headers = reqOpts.headers || {};
@@ -371,9 +383,8 @@ function makeAuthorizedRequest(config) {
371383

372384
function onAuthorizedRequest(err, authorizedReqOpts) {
373385
if (err) {
374-
if (GAE_OR_GCE && err.code === 'ENOTFOUND') {
375-
// The metadata server wasn't found. The user must not actually be in
376-
// a GAE or GCE environment.
386+
if (ENV.NO_CREDENTIALS && err.code === 'ENOTFOUND') {
387+
// The metadata server wasn't found. This must not be GAE or GCE.
377388
throw missingCredentialsError;
378389
}
379390

@@ -385,8 +396,7 @@ function makeAuthorizedRequest(config) {
385396

386397
// For detecting Sign errors on io.js (1.x) (or node 0.11.x)
387398
// E.g. errors in form: error:code:PEM routines:PEM_read_bio:error_name
388-
var pemError = err.message &&
389-
err.message.indexOf('error:') !== -1;
399+
var pemError = err.message && err.message.indexOf('error:') !== -1;
390400

391401
if (err.message === 'SignFinal error' || pemError) {
392402
err.message = [
@@ -412,6 +422,12 @@ function makeAuthorizedRequest(config) {
412422
}
413423

414424
makeRequest.getCredentials = authorize.getCredentials;
425+
makeRequest.getEnvironment = function() {
426+
return {
427+
GAE_DEV: ENV.GAE_DEV,
428+
NO_CREDENTIALS: ENV.NO_CREDENTIALS
429+
};
430+
};
415431

416432
return makeRequest;
417433
}

lib/datastore/dataset.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ function Dataset(options) {
9191
return new Dataset(options);
9292
}
9393

94-
options = options || {};
94+
this.options = options = options || {};
9595

9696
this.makeAuthorizedRequest_ = util.makeAuthorizedRequest({
9797
credentials: options.credentials,

lib/datastore/request.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
'use strict';
2222

23+
var http = require('http');
2324
var https = require('https');
2425
var streamEvents = require('stream-events');
2526
var through = require('through2');
@@ -209,7 +210,7 @@ DatastoreRequest.prototype.get = function(keys, callback) {
209210
* //-
210211
* var companyKey = dataset.key(['Company', 123]);
211212
* var productKey = dataset.key(['Product', 'Computer']);
212-
*
213+
*
213214
* dataset.save([
214215
* {
215216
* key: companyKey,
@@ -492,6 +493,8 @@ DatastoreRequest.prototype.allocateIds = function(incompleteKey, n, callback) {
492493
* Make a request to the API endpoint. Properties to indicate a transactional or
493494
* non-transactional operation are added automatically.
494495
*
496+
* @todo Handle non-HTTP 200 cases.
497+
*
495498
* @param {string} method - Datastore action (allocateIds, commit, etc.).
496499
* @param {object=} body - Request configuration object.
497500
* @param {function} callback - The callback function.
@@ -507,7 +510,8 @@ DatastoreRequest.prototype.allocateIds = function(incompleteKey, n, callback) {
507510
* transaction.makeReq('commit', deleteRequest, function(err) {});
508511
*/
509512
DatastoreRequest.prototype.makeReq_ = function(method, body, callback) {
510-
// TODO: Handle non-HTTP 200 cases.
513+
var ENV = this.makeAuthorizedRequest_.getEnvironment();
514+
511515
if (!callback) {
512516
callback = body;
513517
body = {};
@@ -550,7 +554,17 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) {
550554
return;
551555
}
552556

553-
var remoteStream = https.request(authorizedReqOpts, function(resp) {
557+
var remoteStream;
558+
559+
if (ENV.GAE_DEV && ENV.NO_CREDENTIALS) {
560+
authorizedReqOpts.host = process.env.API_HOST;
561+
authorizedReqOpts.port = process.env.GAE_SERVER_PORT;
562+
remoteStream = http.request(authorizedReqOpts);
563+
} else {
564+
remoteStream = https.request(authorizedReqOpts);
565+
}
566+
567+
remoteStream.on('response', function(resp) {
554568
var buffer = new Buffer('');
555569
resp.on('data', function(chunk) {
556570
buffer = Buffer.concat([buffer, chunk]);

test/datastore/request.js

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ var assert = require('assert');
2222
var ByteBuffer = require('bytebuffer');
2323
var entity = require('../../lib/datastore/entity.js');
2424
var extend = require('extend');
25+
var http = require('http');
2526
var https = require('https');
2627
var mockery = require('mockery');
2728
var mockRespGet = require('../testdata/response_get.json');
@@ -39,6 +40,15 @@ extend(true, https, {
3940
}
4041
});
4142

43+
var httpRequestCached = http.request;
44+
var httpRequestOverride = util.noop;
45+
46+
extend(true, http, {
47+
request: function() {
48+
return httpRequestOverride.apply(this, util.toArray(arguments));
49+
}
50+
});
51+
4252
// Create a protobuf "FakeMethod" request & response.
4353
pb.FakeMethodRequest = function() {
4454
this.toBuffer = function() {
@@ -62,6 +72,7 @@ describe('Request', function() {
6272
before(function() {
6373
mockery.registerMock('./pb.js', pb);
6474
mockery.registerMock('https', https);
75+
mockery.registerMock('http', http);
6576
mockery.enable({
6677
useCleanCache: true,
6778
warnOnUnregistered: false
@@ -73,6 +84,7 @@ describe('Request', function() {
7384
mockery.deregisterAll();
7485
mockery.disable();
7586
httpsRequestOverride = httpsRequestCached;
87+
httpRequestOverride = httpRequestCached;
7688
});
7789

7890
beforeEach(function() {
@@ -85,6 +97,9 @@ describe('Request', function() {
8597
request.makeAuthorizedRequest_ = function(req, callback) {
8698
(callback.onAuthorized || callback)(null, req);
8799
};
100+
request.makeAuthorizedRequest_.getEnvironment = function() {
101+
return {};
102+
};
88103
});
89104

90105
describe('get', function() {
@@ -487,10 +502,13 @@ describe('Request', function() {
487502
assert.equal(opts.headers['Content-Type'], 'application/x-protobuf');
488503
done();
489504
};
505+
request.makeAuthorizedRequest_.getEnvironment = function() {
506+
return {};
507+
};
490508
request.makeReq_(method, {}, util.noop);
491509
});
492510

493-
it('should make https request', function(done) {
511+
it('should make https request if not gae dev and no creds', function(done) {
494512
var mockRequest = { mock: 'request' };
495513
httpsRequestOverride = function(req) {
496514
assert.deepEqual(req, mockRequest);
@@ -500,6 +518,45 @@ describe('Request', function() {
500518
request.makeAuthorizedRequest_ = function(opts, callback) {
501519
(callback.onAuthorized || callback)(null, mockRequest);
502520
};
521+
request.makeAuthorizedRequest_.getEnvironment = function() {
522+
return {
523+
GAE_DEV: false,
524+
NO_CREDENTIALS: false
525+
};
526+
};
527+
request.makeReq_('commit', {}, util.noop);
528+
});
529+
530+
it('should make http call to API_HOST if no credentials', function(done) {
531+
var mockRequest = { mock: 'request' };
532+
533+
var API_HOST_CACHED = process.env.API_HOST;
534+
var GAE_SERVER_PORT_CACHED = process.env.GAE_SERVER_PORT;
535+
536+
process.env.API_HOST = 'API_HOST';
537+
process.env.GAE_SERVER_PORT = 99;
538+
539+
httpRequestOverride = function(req) {
540+
assert.deepEqual(req, mockRequest);
541+
assert.equal(req.host, process.env.API_HOST);
542+
assert.equal(req.port, process.env.GAE_SERVER_PORT);
543+
544+
done();
545+
546+
process.env.API_HOST = API_HOST_CACHED;
547+
process.env.GAE_SERVER_PORT = GAE_SERVER_PORT_CACHED;
548+
549+
return new stream.Writable();
550+
};
551+
request.makeAuthorizedRequest_ = function(opts, callback) {
552+
(callback.onAuthorized || callback)(null, mockRequest);
553+
};
554+
request.makeAuthorizedRequest_.getEnvironment = function() {
555+
return {
556+
GAE_DEV: true,
557+
NO_CREDENTIALS: true
558+
};
559+
};
503560
request.makeReq_('commit', {}, util.noop);
504561
});
505562

@@ -521,11 +578,14 @@ describe('Request', function() {
521578
pbFakeMethodResponseDecode = function() {
522579
done();
523580
};
524-
httpsRequestOverride = function(req, callback) {
525-
var ws = new stream.Writable();
526-
callback(ws);
527-
ws.emit('end');
528-
return ws;
581+
httpsRequestOverride = function() {
582+
var requestStream = new stream.PassThrough();
583+
var responseStream = new stream.PassThrough();
584+
setImmediate(function() {
585+
requestStream.emit('response', responseStream);
586+
responseStream.end();
587+
});
588+
return requestStream;
529589
};
530590
request.makeReq_('fakeMethod', util.noop);
531591
});
@@ -535,6 +595,9 @@ describe('Request', function() {
535595
request.createAuthorizedRequest_ = function(opts, callback) {
536596
(callback.onAuthorized || callback)();
537597
};
598+
request.makeAuthorizedRequest_.getEnvironment = function() {
599+
return {};
600+
};
538601
});
539602

540603
describe('commit', function() {

0 commit comments

Comments
 (0)