diff --git a/README.md b/README.md index eacf5a8..91117b7 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,9 @@ server.listen(process.env.PORT || 8080); ## Options * `fetchContext(request)` - Function that returns a promise of the context, that is an object that maps fragment id to fragment url, to be able to override urls of the fragments on the page, defaults to `Promise.resolve({})` -* `fetchTemplate(request, parseTemplate)` - Function that should fetch the template, call `parseTemplate` and return a promise of the result. Useful to implement your own way to retrieve and cache the templates, e.g. from s3. -Default implementation [`lib/fetch-template.js`](https://github.com/zalando/tailor/blob/master/lib/fetch-template.js) fetches the template from the file system +* `fetchTemplate(request, parseTemplate, eventEmitter)` - Function that should fetch the template, call `parseTemplate` and return a promise of the result. Useful to implement your own way to retrieve and cache the templates, e.g. from s3. +Default implementation [`lib/fetch-template.js`](https://github.com/zalando/tailor/blob/master/lib/fetch-template.js) fetches the template from the file system. +`eventEmitter` allow you to emit your own events that you can catch like native [Tailor events](https://github.com/zalando/tailor/blob/master/docs/Events.md). * `templatesPath` - To specify the path where the templates are stored locally, Defaults to `/templates/` * `fragmentTag` - Name of the fragment tag, defaults to `fragment` * `handledTags` - An array of custom tags, check [`tests/handle-tag`](https://github.com/zalando/tailor/blob/master/tests/handle-tag.js) for more info diff --git a/docs/Events.md b/docs/Events.md index 7d29dba..79353af 100644 --- a/docs/Events.md +++ b/docs/Events.md @@ -20,5 +20,19 @@ Events may be used for logging and monitoring. Check [perf/benchmark.js](https:/ * Error: `fragment:error(request, fragment.attributes, error)` in case of socket error, timeout, 50x * Fallback: `fragment:fallback(request, fragment.attributes, error)` in case of timeout/error from the fragment if the *fallback-src* is specified +## Custom events + +It is possible to emit custom event during template fetching. You need to override `fetchTemplate` Tailor option. `fetchTemplate` is Tailor event emitter that you can use to emit your own events like this : + +```js +const fetchTemplate = (request, parseTemplate, eventEmitter) => { + // [Your logic] + + eventEmitter.emit('myEvent', {foo: 'bar' }); + + parseTemplate(); +} +``` + **Note:** `fragment:response`, `fragment:fallback` and `fragment:error` are mutually exclusive. `fragment:end` happens only in case of successful response. diff --git a/lib/request-handler.js b/lib/request-handler.js index f1132d4..a1b7a4f 100644 --- a/lib/request-handler.js +++ b/lib/request-handler.js @@ -64,7 +64,7 @@ module.exports = function processRequest(options, request, response) { this.emit('context:error', request, err); return {}; }); - const templatePromise = fetchTemplate(request, parseTemplate); + const templatePromise = fetchTemplate(request, parseTemplate, this); const responseHeaders = { // Disable cache in browsers and proxies 'Cache-Control': 'no-cache, no-store, must-revalidate', diff --git a/tests/tailor.events.js b/tests/tailor.events.js index 7d854b7..f0e05e9 100644 --- a/tests/tailor.events.js +++ b/tests/tailor.events.js @@ -16,8 +16,9 @@ describe('Tailor events', () => { tailor = new Tailor({ fetchContext: mockContext, pipeDefinition: () => Buffer.from(''), - fetchTemplate: (request, parseTemplate) => { + fetchTemplate: (request, parseTemplate, tailor) => { const template = mockTemplate(request); + tailor.emit('customEvent', 'bar'); if (template) { return parseTemplate(template); } else { @@ -159,4 +160,22 @@ describe('Tailor events', () => { response.on('end', done); }); }); + + it('emits a custom event on fetching Template', done => { + const onCustomEvent = sinon.spy(); + nock('https://fragment') + .get('/') + .reply(200, 'hello'); + mockTemplate.returns(''); + tailor.on('customEvent', onCustomEvent); + http.get('http://localhost:8080/template', response => { + response.resume(); + response.on('end', () => { + const foo = onCustomEvent.args[0][0]; + assert.equal(foo, 'bar'); + assert.equal(onCustomEvent.callCount, 1); + done(); + }); + }); + }); });