strong-tie/inbound-calls
0
1<h1 align="center">Fastify</h1>2 3## Encapsulation4<a id="encapsulation"></a>5 6A fundamental feature of Fastify is the "encapsulation context." The7encapsulation context governs which [decorators](./Decorators.md), registered8[hooks](./Hooks.md), and [plugins](./Plugins.md) are available to9[routes](./Routes.md). A visual representation of the encapsulation context10is shown in the following figure:11 1213 14In the above figure, there are several entities:15 161. The _root context_172. Three _root plugins_183. Two _child contexts_ where each _child context_ has19 * Two _child plugins_20 * One _grandchild context_ where each _grandchild context_ has21 - Three _child plugins_22 23Every _child context_ and _grandchild context_ has access to the _root plugins_.24Within each _child context_, the _grandchild contexts_ have access to the25_child plugins_ registered within the containing _child context_, but the26containing _child context_ **does not** have access to the _child plugins_27registered within its _grandchild context_.28 29Given that everything in Fastify is a [plugin](./Plugins.md), except for the30_root context_, every "context" and "plugin" in this example is a plugin31that can consist of decorators, hooks, plugins, and routes. Thus, to put32this example into concrete terms, consider a basic scenario of a REST API33server that has three routes: the first route (`/one`) requires authentication,34the second route (`/two`) does not, and the third route (`/three`) has35access to the same context as the second route. Using36[@fastify/bearer-auth][bearer] to provide the authentication, the code for this37example is as follows:38 39```js40'use strict'41 42const fastify = require('fastify')()43 44fastify.decorateRequest('answer', 42)45 46fastify.register(async function authenticatedContext (childServer) {47 childServer.register(require('@fastify/bearer-auth'), { keys: ['abc123'] })48 49 childServer.route({50 path: '/one',51 method: 'GET',52 handler (request, response) {53 response.send({54 answer: request.answer,55 // request.foo will be undefined as it's only defined in publicContext56 foo: request.foo,57 // request.bar will be undefined as it's only defined in grandchildContext58 bar: request.bar59 })60 }61 })62})63 64fastify.register(async function publicContext (childServer) {65 childServer.decorateRequest('foo', 'foo')66 67 childServer.route({68 path: '/two',69 method: 'GET',70 handler (request, response) {71 response.send({72 answer: request.answer,73 foo: request.foo,74 // request.bar will be undefined as it's only defined in grandchildContext75 bar: request.bar76 })77 }78 })79 80 childServer.register(async function grandchildContext (grandchildServer) {81 grandchildServer.decorateRequest('bar', 'bar')82 83 grandchildServer.route({84 path: '/three',85 method: 'GET',86 handler (request, response) {87 response.send({88 answer: request.answer,89 foo: request.foo,90 bar: request.bar91 })92 }93 })94 })95})96 97fastify.listen({ port: 8000 })98```99 100The above server example shows all of the encapsulation concepts outlined in the101original diagram:102 1031. Each _child context_ (`authenticatedContext`, `publicContext`, and104`grandchildContext`) has access to the `answer` request decorator defined in105the _root context_.1062. Only the `authenticatedContext` has access to the `@fastify/bearer-auth`107plugin.1083. Both the `publicContext` and `grandchildContext` have access to the `foo`109request decorator.1104. Only the `grandchildContext` has access to the `bar` request decorator.111 112To see this, start the server and issue requests:113 114```sh115# curl -H 'authorization: Bearer abc123' http://127.0.0.1:8000/one116{"answer":42}117# curl http://127.0.0.1:8000/two118{"answer":42,"foo":"foo"}119# curl http://127.0.0.1:8000/three120{"answer":42,"foo":"foo","bar":"bar"}121```122 123[bearer]: https://github.com/fastify/fastify-bearer-auth124 125## Sharing Between Contexts126<a id="shared-context"></a>127 128Notice that each context in the prior example inherits _only_ from the parent129contexts. Parent contexts cannot access any entities within their descendent130contexts. This default is occasionally not desired. In such cases, the131encapsulation context can be broken through the usage of132[fastify-plugin][fastify-plugin] such that anything registered in a descendent133context is available to the containing parent context.134 135Assuming the `publicContext` needs access to the `bar` decorator defined136within the `grandchildContext` in the previous example, the code can be137rewritten as:138 139```js140'use strict'141 142const fastify = require('fastify')()143const fastifyPlugin = require('fastify-plugin')144 145fastify.decorateRequest('answer', 42)146 147// `authenticatedContext` omitted for clarity148 149fastify.register(async function publicContext (childServer) {150 childServer.decorateRequest('foo', 'foo')151 152 childServer.route({153 path: '/two',154 method: 'GET',155 handler (request, response) {156 response.send({157 answer: request.answer,158 foo: request.foo,159 bar: request.bar160 })161 }162 })163 164 childServer.register(fastifyPlugin(grandchildContext))165 166 async function grandchildContext (grandchildServer) {167 grandchildServer.decorateRequest('bar', 'bar')168 169 grandchildServer.route({170 path: '/three',171 method: 'GET',172 handler (request, response) {173 response.send({174 answer: request.answer,175 foo: request.foo,176 bar: request.bar177 })178 }179 })180 }181})182 183fastify.listen({ port: 8000 })184```185 186Restarting the server and re-issuing the requests for `/two` and `/three`:187 188```sh189# curl http://127.0.0.1:8000/two190{"answer":42,"foo":"foo","bar":"bar"}191# curl http://127.0.0.1:8000/three192{"answer":42,"foo":"foo","bar":"bar"}193```194 195[fastify-plugin]: https://github.com/fastify/fastify-plugin196 