This repository has been archived by the owner on Feb 27, 2022. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(request): add base request class
- Loading branch information
1 parent
941a074
commit e50291f
Showing
4 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
'use strict' | ||
|
||
/* | ||
* adonis-vow | ||
* | ||
* (c) Harminder Virk <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
const Macroable = require('macroable') | ||
const nodeCookie = require('node-cookie') | ||
|
||
module.exports = function () { | ||
/** | ||
* This is base request class to be used | ||
* by other request clients. For example: | ||
* Api client and browser client. | ||
* | ||
* @class BaseRequest | ||
* @constructor | ||
*/ | ||
class Request extends Macroable { | ||
constructor (Config) { | ||
super() | ||
this.Config = Config | ||
this._cookies = [] | ||
this._hooks = { | ||
before: [], | ||
after: [] | ||
} | ||
} | ||
|
||
/** | ||
* Returns an array of cookies to be | ||
* set as header | ||
* | ||
* @method cookies | ||
* | ||
* @return {Array} | ||
*/ | ||
get cookies () { | ||
return this._cookies | ||
} | ||
|
||
/** | ||
* Add a cookie to the request | ||
* | ||
* @method cookie | ||
* | ||
* @param {String} key | ||
* @param {Mixed} value | ||
* | ||
* @chainable | ||
*/ | ||
cookie (key, value) { | ||
const appKey = this.Config.get('app.appKey') | ||
value = nodeCookie.packValue(value, appKey, !!appKey) | ||
this._cookies.push({ key, value }) | ||
return this | ||
} | ||
|
||
/** | ||
* Add a new hook before request starts | ||
* | ||
* @method before | ||
* | ||
* @param {Function} fn | ||
* | ||
* @chainable | ||
*/ | ||
before (fn) { | ||
this._hooks.before.push(fn) | ||
return this | ||
} | ||
|
||
/** | ||
* Add a new hook for after request completes | ||
* | ||
* @method after | ||
* | ||
* @param {Function} fn | ||
* | ||
* @chainable | ||
*/ | ||
after (fn) { | ||
this._hooks.after.push(fn) | ||
return this | ||
} | ||
|
||
/** | ||
* Execute request hooks in sequence | ||
* | ||
* @method exec | ||
* | ||
* @param {String} event - Must be `before` or `after` | ||
* | ||
* @return {void} | ||
*/ | ||
async exec (event) { | ||
if (event !== 'before' && event !== 'after') { | ||
throw new Error(`${event} is not a valid hook event for vow request`) | ||
} | ||
|
||
const hooks = this._hooks[event] | ||
for (const hook of hooks) { | ||
await hook(this) | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Properties for macroable | ||
*/ | ||
Request._macros = {} | ||
Request._getters = {} | ||
|
||
return Request | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
'use strict' | ||
|
||
/* | ||
* adonis-vow | ||
* | ||
* (c) Harminder Virk <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
const test = require('japa') | ||
const { Config } = require('@adonisjs/sink') | ||
const Request = require('../../src/Request')() | ||
const nodeCookie = require('node-cookie') | ||
const sleep = function (time) { | ||
return new Promise((resolve) => { | ||
setTimeout(resolve, time) | ||
}) | ||
} | ||
|
||
test.group('Request', (group) => { | ||
group.beforeEach(() => { | ||
Request.hydrate() | ||
}) | ||
|
||
test('instantiate request', (assert) => { | ||
const request = new Request(new Config()) | ||
assert.instanceOf(request, Request) | ||
}) | ||
|
||
test('define request getter', (assert) => { | ||
Request.getter('foo', () => 'bar') | ||
const request = new Request(new Config()) | ||
assert.equal(request.foo, 'bar') | ||
}) | ||
|
||
test('define request macro', (assert) => { | ||
Request.macro('foo', () => 'bar') | ||
const request = new Request(new Config()) | ||
assert.equal(request.foo(), 'bar') | ||
}) | ||
|
||
test('add new cookie', (assert) => { | ||
const request = new Request(new Config()) | ||
request.cookie('name', 'foo') | ||
assert.deepEqual(request.cookies, [{ key: 'name', value: 'foo' }]) | ||
}) | ||
|
||
test('add encrypted cookie', (assert) => { | ||
const config = new Config() | ||
config.set('app.appKey', 'alongrandomstring') | ||
|
||
const request = new Request(config) | ||
request.cookie('name', 'foo') | ||
assert.equal(nodeCookie.unPackValue(request.cookies[0].value, config.get('app.appKey'), true), 'foo') | ||
}) | ||
|
||
test('add before request hook', (assert) => { | ||
const request = new Request(new Config()) | ||
const fn = function () {} | ||
request.before(fn) | ||
assert.deepEqual(request._hooks.before, [fn]) | ||
}) | ||
|
||
test('add after request hook', (assert) => { | ||
const request = new Request(new Config()) | ||
const fn = function () {} | ||
request.after(fn) | ||
assert.deepEqual(request._hooks.after, [fn]) | ||
}) | ||
|
||
test('execute hooks in sequence', async (assert) => { | ||
const request = new Request(new Config()) | ||
const stack = [] | ||
request.before(() => { | ||
stack.push('1') | ||
}) | ||
|
||
request.before(async () => { | ||
await sleep(100) | ||
stack.push('2') | ||
}) | ||
|
||
request.before(() => { | ||
stack.push('3') | ||
}) | ||
|
||
await request.exec('before') | ||
assert.deepEqual(stack, ['1', '2', '3']) | ||
}) | ||
|
||
test('throw exception when invalid hook type is passed', async (assert) => { | ||
assert.plan(1) | ||
|
||
const request = new Request(new Config()) | ||
const stack = [] | ||
request.before(() => { | ||
stack.push('1') | ||
}) | ||
|
||
request.before(async () => { | ||
await sleep(100) | ||
stack.push('2') | ||
}) | ||
|
||
request.before(() => { | ||
stack.push('3') | ||
}) | ||
|
||
try { | ||
await request.exec('foo') | ||
} catch ({ message }) { | ||
assert.equal(message, 'foo is not a valid hook event for vow request') | ||
} | ||
}) | ||
|
||
test('should have access to request instance inside hook', async (assert) => { | ||
assert.plan(1) | ||
const request = new Request(new Config()) | ||
|
||
request.before((req) => { | ||
assert.deepEqual(req, request) | ||
}) | ||
await request.exec('before') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters