You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							196 lines
						
					
					
						
							5.7 KiB
						
					
					
				
			
		
		
	
	
							196 lines
						
					
					
						
							5.7 KiB
						
					
					
				<h1 align="center">Fastify</h1>
 | 
						|
 | 
						|
## Encapsulation
 | 
						|
<a id="encapsulation"></a>
 | 
						|
 | 
						|
A fundamental feature of Fastify is the "encapsulation context." The
 | 
						|
encapsulation context governs which [decorators](./Decorators.md), registered
 | 
						|
[hooks](./Hooks.md), and [plugins](./Plugins.md) are available to
 | 
						|
[routes](./Routes.md). A visual representation of the encapsulation context
 | 
						|
is shown in the following figure:
 | 
						|
 | 
						|

 | 
						|
 | 
						|
In the above figure, there are several entities:
 | 
						|
 | 
						|
1. The _root context_
 | 
						|
2. Three _root plugins_
 | 
						|
3. Two _child contexts_ where each _child context_ has
 | 
						|
    * Two _child plugins_
 | 
						|
    * One _grandchild context_ where each _grandchild context_ has
 | 
						|
        - Three _child plugins_
 | 
						|
 | 
						|
Every _child context_ and _grandchild context_ has access to the _root plugins_.
 | 
						|
Within each _child context_, the _grandchild contexts_ have access to the
 | 
						|
_child plugins_ registered within the containing _child context_, but the
 | 
						|
containing _child context_ **does not** have access to the _child plugins_
 | 
						|
registered within its _grandchild context_.
 | 
						|
 | 
						|
Given that everything in Fastify is a [plugin](./Plugins.md), except for the
 | 
						|
_root context_, every "context" and "plugin" in this example is a plugin
 | 
						|
that can consist of decorators, hooks, plugins, and routes. Thus, to put
 | 
						|
this example into concrete terms, consider a basic scenario of a REST API
 | 
						|
server that has three routes: the first route (`/one`) requires authentication,
 | 
						|
the second route (`/two`) does not, and the third route (`/three`) has
 | 
						|
access to the same context as the second route. Using
 | 
						|
[@fastify/bearer-auth][bearer] to provide the authentication, the code for this
 | 
						|
example is as follows:
 | 
						|
 | 
						|
```js
 | 
						|
'use strict'
 | 
						|
 | 
						|
const fastify = require('fastify')()
 | 
						|
 | 
						|
fastify.decorateRequest('answer', 42)
 | 
						|
 | 
						|
fastify.register(async function authenticatedContext (childServer) {
 | 
						|
  childServer.register(require('@fastify/bearer-auth'), { keys: ['abc123'] })
 | 
						|
 | 
						|
  childServer.route({
 | 
						|
    path: '/one',
 | 
						|
    method: 'GET',
 | 
						|
    handler (request, response) {
 | 
						|
      response.send({
 | 
						|
        answer: request.answer,
 | 
						|
        // request.foo will be undefined as it's only defined in publicContext
 | 
						|
        foo: request.foo,
 | 
						|
        // request.bar will be undefined as it's only defined in grandchildContext
 | 
						|
        bar: request.bar
 | 
						|
      })
 | 
						|
    }
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
fastify.register(async function publicContext (childServer) {
 | 
						|
  childServer.decorateRequest('foo', 'foo')
 | 
						|
 | 
						|
  childServer.route({
 | 
						|
    path: '/two',
 | 
						|
    method: 'GET',
 | 
						|
    handler (request, response) {
 | 
						|
      response.send({
 | 
						|
        answer: request.answer,
 | 
						|
        foo: request.foo,
 | 
						|
        // request.bar will be undefined as it's only defined in grandchildContext
 | 
						|
        bar: request.bar
 | 
						|
      })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  childServer.register(async function grandchildContext (grandchildServer) {
 | 
						|
    grandchildServer.decorateRequest('bar', 'bar')
 | 
						|
 | 
						|
    grandchildServer.route({
 | 
						|
      path: '/three',
 | 
						|
      method: 'GET',
 | 
						|
      handler (request, response) {
 | 
						|
        response.send({
 | 
						|
          answer: request.answer,
 | 
						|
          foo: request.foo,
 | 
						|
          bar: request.bar
 | 
						|
        })
 | 
						|
      }
 | 
						|
    })
 | 
						|
  })
 | 
						|
})
 | 
						|
 | 
						|
fastify.listen(8000)
 | 
						|
```
 | 
						|
 | 
						|
The above server example shows all of the encapsulation concepts outlined in the
 | 
						|
original diagram:
 | 
						|
 | 
						|
1. Each _child context_ (`authenticatedContext`, `publicContext`, and
 | 
						|
`grandchildContext`) has access to the `answer` request decorator defined in
 | 
						|
the _root context_.
 | 
						|
2. Only the `authenticatedContext` has access to the `@fastify/bearer-auth`
 | 
						|
plugin.
 | 
						|
3. Both the `publicContext` and `grandchildContext` have access to the `foo`
 | 
						|
request decorator.
 | 
						|
4. Only the `grandchildContext` has access to the `bar` request decorator.
 | 
						|
 | 
						|
To see this, start the server and issue requests:
 | 
						|
 | 
						|
```sh
 | 
						|
# curl -H 'authorization: Bearer abc123' http://127.0.0.1:8000/one
 | 
						|
{"answer":42}
 | 
						|
# curl http://127.0.0.1:8000/two
 | 
						|
{"answer":42,"foo":"foo"}
 | 
						|
# curl http://127.0.0.1:8000/three
 | 
						|
{"answer":42,"foo":"foo","bar":"bar"}
 | 
						|
```
 | 
						|
 | 
						|
[bearer]: https://github.com/fastify/fastify-bearer-auth
 | 
						|
 | 
						|
## Sharing Between Contexts
 | 
						|
<a id="shared-context"></a>
 | 
						|
 | 
						|
Notice that each context in the prior example inherits _only_ from the parent
 | 
						|
contexts. Parent contexts cannot access any entities within their descendent
 | 
						|
contexts. This default is occasionally not desired. In such cases, the
 | 
						|
encapsulation context can be broken through the usage of
 | 
						|
[fastify-plugin][fastify-plugin] such that anything registered in a descendent
 | 
						|
context is available to the containing parent context.
 | 
						|
 | 
						|
Assuming the `publicContext` needs access to the `bar` decorator defined
 | 
						|
within the `grandchildContext` in the previous example, the code can be
 | 
						|
rewritten to:
 | 
						|
 | 
						|
```js
 | 
						|
'use strict'
 | 
						|
 | 
						|
const fastify = require('fastify')()
 | 
						|
const fastifyPlugin = require('fastify-plugin')
 | 
						|
 | 
						|
fastify.decorateRequest('answer', 42)
 | 
						|
 | 
						|
// `authenticatedContext` omitted for clarity
 | 
						|
 | 
						|
fastify.register(async function publicContext (childServer) {
 | 
						|
  childServer.decorateRequest('foo', 'foo')
 | 
						|
 | 
						|
  childServer.route({
 | 
						|
    path: '/two',
 | 
						|
    method: 'GET',
 | 
						|
    handler (request, response) {
 | 
						|
      response.send({
 | 
						|
        answer: request.answer,
 | 
						|
        foo: request.foo,
 | 
						|
        bar: request.bar
 | 
						|
      })
 | 
						|
    }
 | 
						|
  })
 | 
						|
 | 
						|
  childServer.register(fastifyPlugin(grandchildContext))
 | 
						|
 | 
						|
  async function grandchildContext (grandchildServer) {
 | 
						|
    grandchildServer.decorateRequest('bar', 'bar')
 | 
						|
 | 
						|
    grandchildServer.route({
 | 
						|
      path: '/three',
 | 
						|
      method: 'GET',
 | 
						|
      handler (request, response) {
 | 
						|
        response.send({
 | 
						|
          answer: request.answer,
 | 
						|
          foo: request.foo,
 | 
						|
          bar: request.bar
 | 
						|
        })
 | 
						|
      }
 | 
						|
    })
 | 
						|
  }
 | 
						|
})
 | 
						|
 | 
						|
fastify.listen(8000)
 | 
						|
```
 | 
						|
 | 
						|
Restarting the server and re-issuing the requests for `/two` and `/three`:
 | 
						|
 | 
						|
```sh
 | 
						|
# curl http://127.0.0.1:8000/two
 | 
						|
{"answer":42,"foo":"foo","bar":"bar"}
 | 
						|
# curl http://127.0.0.1:8000/three
 | 
						|
{"answer":42,"foo":"foo","bar":"bar"}
 | 
						|
```
 | 
						|
 | 
						|
[fastify-plugin]: https://github.com/fastify/fastify-plugin
 |