Skip to content
This repository has been archived by the owner on Sep 23, 2021. It is now read-only.

Commit

Permalink
feat(server): process post request body (#180), closes #179
Browse files Browse the repository at this point in the history
  • Loading branch information
rofe authored Apr 11, 2019
1 parent 9c61890 commit 4292fc7
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 9 deletions.
21 changes: 17 additions & 4 deletions src/HelixServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function executeTemplate(ctx) {

Module._nodeModulePaths = nodeModulePathsFn;

return Promise.resolve(mod.main({
const actionParams = {
__ow_headers: owHeaders,
__ow_method: ctx.method.toLowerCase(),
__ow_logger: ctx.logger,
Expand All @@ -87,7 +87,14 @@ function executeTemplate(ctx) {
params: querystring.stringify(ctx._params),
REPO_RAW_ROOT: `${ctx.strain.content.rawRoot}/`, // the pipeline needs the final slash here
REPO_API_ROOT: `${ctx.strain.content.apiRoot}/`,
}));
};
if (ctx.body) {
// add post params to action params
Object.keys(ctx.body).forEach((key) => {
actionParams[key] = ctx.body[key];
});
}
return Promise.resolve(mod.main(actionParams));
/* eslint-enable no-underscore-dangle */
}

Expand Down Expand Up @@ -124,7 +131,11 @@ class HelixServer extends EventEmitter {
resolveWithFullResponse: true,
}),
}));
this._app.get('*', async (req, res) => {

// read JSON request body
this._app.use(express.json());

const handler = async (req, res) => {
const ctx = new RequestContext(req, this._project);
ctx.logger = log;

Expand Down Expand Up @@ -194,7 +205,9 @@ class HelixServer extends EventEmitter {
res.status(err.code || 500).send();
});
}
});
};
this._app.get('*', handler);
this._app.post('*', handler);
}

withPort(port) {
Expand Down
14 changes: 14 additions & 0 deletions src/RequestContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ module.exports = class RequestContext {
} else {
this._mount = '';
}
if (req.body && Object.entries(req.body).length > 0) {
this._body = req.body;
}

const lastSlash = this._path.lastIndexOf('/');
let lastDot = this._path.lastIndexOf('.');
Expand Down Expand Up @@ -122,6 +125,14 @@ module.exports = class RequestContext {
return this._cfg;
}

/**
* The request body.
* @returns {Object}
*/
get body() {
return this._body;
}

/**
* The path to the resource in the repository.
* @returns {string}
Expand Down Expand Up @@ -213,6 +224,9 @@ module.exports = class RequestContext {
headers: this.headers,
params: this.params,
};
if (this.body) {
o.body = this.body;
}
return o;
}
};
77 changes: 72 additions & 5 deletions test/hlx_server_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,18 @@ async function setupProject(srcDir, root, initGit = true) {
return dir;
}

async function assertHttp(url, status, spec, subst) {
// todo: use replay ?

async function assertHttp(config, status, spec, subst) {
return new Promise((resolve, reject) => {
const data = [];
http.get(url, (res) => {
const requestHandler = (res) => {
try {
assert.equal(res.statusCode, status);
} catch (e) {
res.resume();
reject(e);
}

res
.on('data', (chunk) => {
data.push(chunk);
Expand Down Expand Up @@ -94,9 +95,27 @@ async function assertHttp(url, status, spec, subst) {
reject(e);
}
});
}).on('error', (e) => {
};
const errorHandler = (e) => {
reject(e);
});
};
if (typeof config === 'string') {
// use as URL and do GET
http.get(config, requestHandler).on('error', errorHandler);
} else {
// do POST
const postStr = config.postData ? JSON.stringify(config.postData) : '';
const { options } = config;
options.method = 'POST';
options.headers = {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postStr),
};
const req = http.request(options, requestHandler);
req.on('error', errorHandler);
req.write(postStr);
req.end();
}
});
}

Expand Down Expand Up @@ -582,4 +601,52 @@ describe('Helix Server', () => {
await project.stop();
}
});

it('serve post request', async () => {
const cwd = path.join(SPEC_ROOT, 'local');
const project = new HelixProject()
.withCwd(cwd)
.withBuildDir('./build')
.withHttpPort(0);
await project.init();
try {
await project.start();
await assertHttp({
options: {
hostname: 'localhost',
port: project.server.port,
path: '/index.html',
},
postData: {},
}, 200, 'expected_index.html');
} finally {
await project.stop();
}
});

it('serve post with custom content.body', async () => {
const cwd = path.join(SPEC_ROOT, 'local');
const project = new HelixProject()
.withCwd(cwd)
.withBuildDir('./build')
.withHttpPort(0);
await project.init();
try {
await project.start();
await assertHttp({
options: {
hostname: 'localhost',
port: project.server.port,
path: '/index.post.html',
},
postData: {
content: {
body: 'Hello, universe',
},
},
}, 200, 'expected_index_post.html');
} finally {
await project.stop();
}
});
});
1 change: 1 addition & 0 deletions test/specs/expected_index_post.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<html><head>Test</head><body>Hello, universe. path=/index.md</body></html>
19 changes: 19 additions & 0 deletions test/specs/local/build/post_html.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2018 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
const { utils } = require('./helper.js');

/* eslint-disable */
module.exports.main = function main(params) {
return {
body: `<html><head>Test</head><body>${params.content.body}. path=${params.path}</body></html>`,
}
};
31 changes: 31 additions & 0 deletions test/utils_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,35 @@ describe('Utils Test', () => {
url: '/content/index.foo.html',
},
},
{
url: '/content/index.post.html',
valid: true,
path: '/content/index.post.html',
resourcePath: '/content/index',
selector: 'post',
extension: 'html',
method: 'POST',
body: {
content: {
body: 'Test',
},
},
expectedJson: {
extension: 'html',
headers: {},
params: {},
method: 'POST',
path: '/content/index.post.html',
resourcePath: '/content/index',
selector: 'post',
url: '/content/index.post.html',
body: {
content: {
body: 'Test',
},
},
},
},
];

TESTS.forEach((t) => {
Expand All @@ -106,6 +135,8 @@ describe('Utils Test', () => {
url: t.url,
query: t.query,
headers: t.headers,
body: t.body || undefined,
method: t.method || undefined,
};
const p = new RequestContext(mockReq, t.config || mockConfig);
assert.equal(p.url, t.url);
Expand Down

0 comments on commit 4292fc7

Please sign in to comment.