From 2fc07f97cd787b4032967d17aa6e6c6bc6d7496e Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Fri, 24 Jun 2016 16:21:05 -0400 Subject: [PATCH 1/6] Use the callback body instead of response.body that may not be set --- src/cloud-code/HTTPResponse.js | 18 +++++++++++++++--- src/cloud-code/httpRequest.js | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/cloud-code/HTTPResponse.js b/src/cloud-code/HTTPResponse.js index f234f332db..7956e76c87 100644 --- a/src/cloud-code/HTTPResponse.js +++ b/src/cloud-code/HTTPResponse.js @@ -1,15 +1,27 @@ export default class HTTPResponse { - constructor(response) { + constructor(response, body) { this.status = response.statusCode; this.headers = response.headers; - this.buffer = response.body; this.cookies = response.headers["set-cookie"]; + + this.body = body; + if (typeof body == 'string') { + this._text = body; + } else if (Buffer.isBuffer(body)) { + this.buffer = body; + } else if (typeof body == 'object') { + this._data = body; + } } get text() { - return this.buffer.toString('utf-8'); + if (!this._text && this.buffer) { + this._text = this.buffer.toString('utf-8'); + } + return this._text; } + get data() { if (!this._data) { try { diff --git a/src/cloud-code/httpRequest.js b/src/cloud-code/httpRequest.js index ccea11c80d..820500733d 100644 --- a/src/cloud-code/httpRequest.js +++ b/src/cloud-code/httpRequest.js @@ -62,7 +62,7 @@ module.exports = function(options) { } return promise.reject(error); } - let httpResponse = new HTTPResponse(response); + let httpResponse = new HTTPResponse(response, body); // Consider <200 && >= 400 as errors if (httpResponse.status < 200 || httpResponse.status >= 400) { From 421b841e6ed488e3177851859e8c1899d814cfd2 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Fri, 24 Jun 2016 17:04:43 -0400 Subject: [PATCH 2/6] Adds test to handle undefined responses --- spec/HTTPRequest.spec.js | 9 +++++++++ src/cloud-code/HTTPResponse.js | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/spec/HTTPRequest.spec.js b/spec/HTTPRequest.spec.js index e4096f5b9b..53f8a57847 100644 --- a/spec/HTTPRequest.spec.js +++ b/spec/HTTPRequest.spec.js @@ -1,6 +1,7 @@ 'use strict'; var httpRequest = require("../src/cloud-code/httpRequest"), + HTTPResponse = require('../src/cloud-code/HTTPResponse').default, bodyParser = require('body-parser'), express = require("express"); @@ -245,4 +246,12 @@ describe("httpRequest", () => { }) }); + it('should not crash with undefined body', () => { + let httpResponse = new HTTPResponse({}); + expect(httpResponse.body).toBeUndefined(); + expect(httpResponse.data).toBeUndefined(); + expect(httpResponse.text).toBeUndefined(); + expect(httpResponse.buffer).toBeUndefined(); + }) + }); diff --git a/src/cloud-code/HTTPResponse.js b/src/cloud-code/HTTPResponse.js index 7956e76c87..c3964f7f9e 100644 --- a/src/cloud-code/HTTPResponse.js +++ b/src/cloud-code/HTTPResponse.js @@ -2,8 +2,8 @@ export default class HTTPResponse { constructor(response, body) { this.status = response.statusCode; - this.headers = response.headers; - this.cookies = response.headers["set-cookie"]; + this.headers = response.headers || {}; + this.cookies = this.headers["set-cookie"]; this.body = body; if (typeof body == 'string') { From 330f559ae584b9262df1c8234dd820c9ec4e629b Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Sat, 25 Jun 2016 10:18:24 -0400 Subject: [PATCH 3/6] Adds toJSON method to properly serialize HTTPResponse --- spec/HTTPRequest.spec.js | 37 +++++++++++++++++++++++++++++++++- src/cloud-code/HTTPResponse.js | 11 ++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/spec/HTTPRequest.spec.js b/spec/HTTPRequest.spec.js index 53f8a57847..7b2f10e819 100644 --- a/spec/HTTPRequest.spec.js +++ b/spec/HTTPRequest.spec.js @@ -252,6 +252,41 @@ describe("httpRequest", () => { expect(httpResponse.data).toBeUndefined(); expect(httpResponse.text).toBeUndefined(); expect(httpResponse.buffer).toBeUndefined(); - }) + }); + + it('serialized httpResponse correctly with body string', () => { + let httpResponse = new HTTPResponse({}, 'hello'); + let serialized = JSON.stringify(httpResponse); + let result = JSON.parse(serialized); + expect(result.text).toBe('hello'); + expect(result.data).toBe(undefined); + expect(result.body).toBe('hello'); + }); + + it('serialized httpResponse correctly with body object', () => { + let httpResponse = new HTTPResponse({}, {foo: "bar"}); + let serialized = JSON.stringify(httpResponse); + let result = JSON.parse(serialized); + expect(result.text).toEqual('{"foo":"bar"}'); + expect(result.data).toEqual({foo: 'bar'}); + expect(result.body).toEqual({foo: 'bar'}); + }); + + it('serialized httpResponse correctly with body buffer string', () => { + let httpResponse = new HTTPResponse({}, new Buffer('hello')); + let serialized = JSON.stringify(httpResponse); + let result = JSON.parse(serialized); + expect(result.text).toBe('hello'); + expect(result.data).toBe(undefined); + }); + + it('serialized httpResponse correctly with body buffer JSON Object', () => { + let json = '{"foo":"bar"}'; + let httpResponse = new HTTPResponse({}, new Buffer(json)); + let serialized = JSON.stringify(httpResponse); + let result = JSON.parse(serialized); + expect(result.text).toEqual('{"foo":"bar"}'); + expect(result.data).toEqual({foo: 'bar'}); + }); }); diff --git a/src/cloud-code/HTTPResponse.js b/src/cloud-code/HTTPResponse.js index c3964f7f9e..dc822a7e98 100644 --- a/src/cloud-code/HTTPResponse.js +++ b/src/cloud-code/HTTPResponse.js @@ -18,6 +18,8 @@ export default class HTTPResponse { get text() { if (!this._text && this.buffer) { this._text = this.buffer.toString('utf-8'); + } else if (!this._text && this._data) { + this._text = JSON.stringify(this._data); } return this._text; } @@ -30,4 +32,13 @@ export default class HTTPResponse { } return this._data; } + + toJSON() { + let plainObject = Object.assign({}, this); + plainObject.text = this.text; + plainObject.data = this.data; + delete plainObject._text; + delete plainObject._data; + return plainObject; + } } From 412c87f99d642b213a93af4de754d991f39338b5 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Sat, 25 Jun 2016 11:42:32 -0400 Subject: [PATCH 4/6] Use ES5 defineProperty to make keys enumerable --- spec/HTTPRequest.spec.js | 30 ++++++++++++++++++++ src/cloud-code/HTTPResponse.js | 52 ++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/spec/HTTPRequest.spec.js b/spec/HTTPRequest.spec.js index 7b2f10e819..02f21e7b11 100644 --- a/spec/HTTPRequest.spec.js +++ b/spec/HTTPRequest.spec.js @@ -256,6 +256,10 @@ describe("httpRequest", () => { it('serialized httpResponse correctly with body string', () => { let httpResponse = new HTTPResponse({}, 'hello'); + expect(httpResponse.text).toBe('hello'); + expect(httpResponse.data).toBe(undefined); + expect(httpResponse.body).toBe('hello'); + let serialized = JSON.stringify(httpResponse); let result = JSON.parse(serialized); expect(result.text).toBe('hello'); @@ -265,8 +269,14 @@ describe("httpRequest", () => { it('serialized httpResponse correctly with body object', () => { let httpResponse = new HTTPResponse({}, {foo: "bar"}); + let encodedResponse = Parse._encode(httpResponse); let serialized = JSON.stringify(httpResponse); let result = JSON.parse(serialized); + + expect(httpResponse.text).toEqual('{"foo":"bar"}'); + expect(httpResponse.data).toEqual({foo: 'bar'}); + expect(httpResponse.body).toEqual({foo: 'bar'}); + expect(result.text).toEqual('{"foo":"bar"}'); expect(result.data).toEqual({foo: 'bar'}); expect(result.body).toEqual({foo: 'bar'}); @@ -274,6 +284,9 @@ describe("httpRequest", () => { it('serialized httpResponse correctly with body buffer string', () => { let httpResponse = new HTTPResponse({}, new Buffer('hello')); + expect(httpResponse.text).toBe('hello'); + expect(httpResponse.data).toBe(undefined); + let serialized = JSON.stringify(httpResponse); let result = JSON.parse(serialized); expect(result.text).toBe('hello'); @@ -289,4 +302,21 @@ describe("httpRequest", () => { expect(result.data).toEqual({foo: 'bar'}); }); + it('serialized httpResponse with Parse._encode should be allright', () => { + let json = '{"foo":"bar"}'; + let httpResponse = new HTTPResponse({}, new Buffer(json)); + let encoded = Parse._encode(httpResponse); + let foundData, foundText = false; + for(var key in encoded) { + if (key == 'data') { + foundData = true; + } + if (key == 'text') { + foundText = true; + } + } + expect(foundData).toBe(true); + expect(foundText).toBe(true); + }); + }); diff --git a/src/cloud-code/HTTPResponse.js b/src/cloud-code/HTTPResponse.js index dc822a7e98..ed4c0e9420 100644 --- a/src/cloud-code/HTTPResponse.js +++ b/src/cloud-code/HTTPResponse.js @@ -1,44 +1,46 @@ export default class HTTPResponse { constructor(response, body) { + let _text, _data; this.status = response.statusCode; this.headers = response.headers || {}; this.cookies = this.headers["set-cookie"]; this.body = body; if (typeof body == 'string') { - this._text = body; + _text = body; } else if (Buffer.isBuffer(body)) { this.buffer = body; } else if (typeof body == 'object') { - this._data = body; + _data = body; } - } - - get text() { - if (!this._text && this.buffer) { - this._text = this.buffer.toString('utf-8'); - } else if (!this._text && this._data) { - this._text = JSON.stringify(this._data); + + let getText = () => { + if (!_text && this.buffer) { + _text = this.buffer.toString('utf-8'); + } else if (!_text && _data) { + _text = JSON.stringify(_data); + } + return _text; } - return this._text; - } - get data() { - if (!this._data) { - try { - this._data = JSON.parse(this.text); - } catch (e) {} + let getData = () => { + if (!_data) { + try { + _data = JSON.parse(getText()); + } catch (e) {} + } + return _data; } - return this._data; - } - toJSON() { - let plainObject = Object.assign({}, this); - plainObject.text = this.text; - plainObject.data = this.data; - delete plainObject._text; - delete plainObject._data; - return plainObject; + Object.defineProperty(this, 'text', { + enumerable: true, + get: getText + }); + + Object.defineProperty(this, 'data', { + enumerable: true, + get: getData + }); } } From 37d0443c845bea82d7103fe35e2f8b88d4f21e67 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Sat, 25 Jun 2016 13:09:34 -0400 Subject: [PATCH 5/6] removes body key from serialization --- spec/HTTPRequest.spec.js | 10 +++++++--- src/cloud-code/HTTPResponse.js | 7 +++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/spec/HTTPRequest.spec.js b/spec/HTTPRequest.spec.js index 02f21e7b11..cb34fe70bb 100644 --- a/spec/HTTPRequest.spec.js +++ b/spec/HTTPRequest.spec.js @@ -264,7 +264,7 @@ describe("httpRequest", () => { let result = JSON.parse(serialized); expect(result.text).toBe('hello'); expect(result.data).toBe(undefined); - expect(result.body).toBe('hello'); + expect(result.body).toBe(undefined); }); it('serialized httpResponse correctly with body object', () => { @@ -279,7 +279,7 @@ describe("httpRequest", () => { expect(result.text).toEqual('{"foo":"bar"}'); expect(result.data).toEqual({foo: 'bar'}); - expect(result.body).toEqual({foo: 'bar'}); + expect(result.body).toEqual(undefined); }); it('serialized httpResponse correctly with body buffer string', () => { @@ -306,7 +306,7 @@ describe("httpRequest", () => { let json = '{"foo":"bar"}'; let httpResponse = new HTTPResponse({}, new Buffer(json)); let encoded = Parse._encode(httpResponse); - let foundData, foundText = false; + let foundData, foundText, foundBody = false; for(var key in encoded) { if (key == 'data') { foundData = true; @@ -314,9 +314,13 @@ describe("httpRequest", () => { if (key == 'text') { foundText = true; } + if (key == 'body') { + foundBody = true; + } } expect(foundData).toBe(true); expect(foundText).toBe(true); + expect(foundBody).toBe(false); }); }); diff --git a/src/cloud-code/HTTPResponse.js b/src/cloud-code/HTTPResponse.js index ed4c0e9420..8b7da88a37 100644 --- a/src/cloud-code/HTTPResponse.js +++ b/src/cloud-code/HTTPResponse.js @@ -5,8 +5,7 @@ export default class HTTPResponse { this.status = response.statusCode; this.headers = response.headers || {}; this.cookies = this.headers["set-cookie"]; - - this.body = body; + if (typeof body == 'string') { _text = body; } else if (Buffer.isBuffer(body)) { @@ -33,6 +32,10 @@ export default class HTTPResponse { return _data; } + Object.defineProperty(this, 'body', { + get: () => { return body } + }); + Object.defineProperty(this, 'text', { enumerable: true, get: getText From 0271730df501050e49f8c138f6e0ac3e1f6aab27 Mon Sep 17 00:00:00 2001 From: Florent Vilmart Date: Sat, 25 Jun 2016 13:42:21 -0400 Subject: [PATCH 6/6] Indent nits --- src/cloud-code/HTTPResponse.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cloud-code/HTTPResponse.js b/src/cloud-code/HTTPResponse.js index 8b7da88a37..8359860ee6 100644 --- a/src/cloud-code/HTTPResponse.js +++ b/src/cloud-code/HTTPResponse.js @@ -16,20 +16,20 @@ export default class HTTPResponse { let getText = () => { if (!_text && this.buffer) { - _text = this.buffer.toString('utf-8'); - } else if (!_text && _data) { - _text = JSON.stringify(_data); - } - return _text; + _text = this.buffer.toString('utf-8'); + } else if (!_text && _data) { + _text = JSON.stringify(_data); + } + return _text; } let getData = () => { if (!_data) { - try { - _data = JSON.parse(getText()); - } catch (e) {} - } - return _data; + try { + _data = JSON.parse(getText()); + } catch (e) {} + } + return _data; } Object.defineProperty(this, 'body', {