Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HelloHTTP: Make Node 8 XSS-safe + add POST support #891

Merged
merged 3 commits into from
Nov 14, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion functions/helloworld/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ exports.helloGET = (req, res) => {
*/
// [START functions_tips_terminate]
exports.helloHttp = (req, res) => {
res.send(`Hello ${escapeHtml(req.body.name || 'World')}!`);
res.send(`Hello ${escapeHtml(req.query.name || req.body.name || 'World')}!`);
};
// [END functions_helloworld_http]

Expand Down
12 changes: 11 additions & 1 deletion functions/helloworld/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,17 @@ test.cb(`helloGET: should print hello world`, (t) => {
.end(t.end);
});

test.cb(`helloHttp: should print a name`, (t) => {
test.cb(`helloHttp: should print a name via GET`, (t) => {
supertest(BASE_URL)
.get(`/helloHttp?name=John`)
.expect(200)
.expect((response) => {
t.is(response.text, 'Hello John!');
})
.end(t.end);
});

test.cb(`helloHttp: should print a name via POST`, (t) => {
supertest(BASE_URL)
.post(`/helloHttp`)
.send({ name: 'John' })
Expand Down
16 changes: 16 additions & 0 deletions functions/node8/.gcloudignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore

node_modules
4 changes: 3 additions & 1 deletion functions/node8/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
* More info: https://expressjs.com/en/api.html#res
*/
// [START functions_tips_terminate_node8]
const escapeHtml = require('escape-html');

exports.helloHttp = (req, res) => {
res.send(`Hello ${req.body.name || 'World'}!`);
res.send(`Hello ${escapeHtml(req.query.name || req.body.name || 'World')}!`);
};
// [END functions_tips_terminate_node8]

Expand Down
4 changes: 3 additions & 1 deletion functions/node8/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
"uuid": "^3.3.2"
},
"dependencies": {

"request": "^2.88.0",
"request-promise-native": "^1.0.5",
"@google-cloud/firestore": "^0.18.0"
"@google-cloud/firestore": "^0.18.0",
"escape-html": "^1.0.3"
}
}
40 changes: 39 additions & 1 deletion functions/node8/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ function getSample () {
test.beforeEach(utils.stubConsole);
test.afterEach.always(utils.restoreConsole);

test.serial('should respond to HTTP requests', t => {
test.serial('should respond to HTTP POST', t => {
const sample = getSample();

const reqMock = {
query: {},
body: {
name: 'foo'
}
Expand All @@ -61,6 +62,43 @@ test.serial('should respond to HTTP requests', t => {
t.true(resMock.send.calledWith('Hello foo!'));
});

test.serial('should respond to HTTP GET', t => {
const sample = getSample();

const reqMock = {
query: {
name: 'foo'
},
body: {}
};

const resMock = {
send: sinon.stub()
};

sample.program.helloHttp(reqMock, resMock);
t.true(resMock.send.calledWith('Hello foo!'));
});

test.serial('should escape XSS', t => {
const sample = getSample();

const xssQuery = '<script></script>';
const reqMock = {
query: {},
body: {
name: xssQuery
}
};

const resMock = {
send: sinon.stub()
};

sample.program.helloHttp(reqMock, resMock);
t.false(resMock.send.calledWith(xssQuery));
});

test.serial('should monitor Firebase RTDB', t => {
const sample = getSample();

Expand Down