Skip to content

Commit

Permalink
Merge branch 'main' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
mcollina committed Nov 22, 2021
2 parents 795e83a + 1552f7d commit f57a435
Show file tree
Hide file tree
Showing 56 changed files with 1,421 additions and 350 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Expand Up @@ -74,7 +74,7 @@ jobs:
needs: test
runs-on: ubuntu-latest
steps:
- uses: fastify/github-action-merge-dependabot@v2.5.0
- uses: fastify/github-action-merge-dependabot@v2.6.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
target: minor
Expand Down
3 changes: 0 additions & 3 deletions .npmignore
@@ -1,15 +1,12 @@
.editorconfig
.gitattributes
.git
.DS_Store
.gitignore
.github
.nyc_output
coverage/
tools/
CODE_OF_CONDUCT.md
CONTRIBUTING.md
.dependabot
.clinic

# test certification
Expand Down
2 changes: 2 additions & 0 deletions build/build-validation.js
Expand Up @@ -25,6 +25,7 @@ const defaultInitOptions = {
connectionTimeout: 0, // 0 sec
keepAliveTimeout: 72000, // 72 seconds
maxRequestsPerSocket: 0, // no limit
requestTimeout: 0, // no limit
bodyLimit: 1024 * 1024, // 1 MiB
caseSensitive: true,
disableRequestLogging: false,
Expand All @@ -47,6 +48,7 @@ const schema = {
connectionTimeout: { type: 'integer', default: defaultInitOptions.connectionTimeout },
keepAliveTimeout: { type: 'integer', default: defaultInitOptions.keepAliveTimeout },
maxRequestsPerSocket: { type: 'integer', default: defaultInitOptions.maxRequestsPerSocket, nullable: true },
requestTimeout: { type: 'integer', default: defaultInitOptions.requestTimeout },
bodyLimit: { type: 'integer', default: defaultInitOptions.bodyLimit },
caseSensitive: { type: 'boolean', default: defaultInitOptions.caseSensitive },
http2: { type: 'boolean' },
Expand Down
11 changes: 11 additions & 0 deletions build/sync-version.js
@@ -0,0 +1,11 @@
'use strict'

const fs = require('fs')
const path = require('path')

// package.json:version -> fastify.js:VERSION
const { version } = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json')).toString('utf8'))

const fastifyJs = path.join(__dirname, '..', 'fastify.js')

fs.writeFileSync(fastifyJs, fs.readFileSync(fastifyJs).toString('utf8').replace(/const\s*VERSION\s*=.*/, `const VERSION = '${version}'`))
2 changes: 2 additions & 0 deletions docs/Ecosystem.md
Expand Up @@ -91,6 +91,7 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
- [`fastify-cloudevents`](https://github.com/smartiniOnGitHub/fastify-cloudevents) Fastify plugin to generate and forward Fastify events in the Cloudevents format.
- [`fastify-cockroachdb`](https://github.com/alex-ppg/fastify-cockroachdb) Fastify plugin to connect to a CockroachDB PostgreSQL instance via the Sequelize ORM.
- [`fastify-couchdb`](https://github.com/nigelhanlon/fastify-couchdb) Fastify plugin to add CouchDB support via [nano](https://github.com/apache/nano).
- [`fastify-crud-generator`](https://github.com/heply/fastify-crud-generator) A plugin to rapidly generate CRUD routes for any entity.
- [`fastify-custom-healthcheck`](https://github.com/gkampitakis/fastify-custom-healthcheck) Fastify plugin to add health route in your server that asserts custom functions.
- [`fastify-decorators`](https://github.com/L2jLiga/fastify-decorators) Fastify plugin that provides the set of TypeScript decorators.
- [`fastify-disablecache`](https://github.com/Fdawgs/fastify-disablecache) Fastify plugin to disable client-side caching, inspired by [nocache](https://github.com/helmetjs/nocache).
Expand Down Expand Up @@ -158,6 +159,7 @@ Plugins maintained by the Fastify team are listed under [Core](#core) while plug
- [`fastify-orientdb`](https://github.com/mahmed8003/fastify-orientdb) Fastify OrientDB connection plugin, with which you can share the OrientDB connection across every part of your server.
- [`fastify-piscina`](https://github.com/piscinajs/fastify-piscina) A worker thread pool plugin using [Piscina](https://github.com/piscinajs/piscina).
- [`fastify-peekaboo`](https://github.com/simone-sanfratello/fastify-peekaboo) Fastify plugin for memoize responses by expressive settings.
- [`fastify-polyglot`](https://github.com/heply/fastify-polyglot) A plugin to handle i18n using [node-polyglot](https://www.npmjs.com/package/node-polyglot).
- [`fastify-postgraphile`](https://github.com/alemagio/fastify-postgraphile) Plugin to integrate [PostGraphile](https://www.graphile.org/postgraphile/) in a Fastify project.
- [`fastify-prettier`](https://github.com/hsynlms/fastify-prettier) A Fastify plugin that uses [prettier](https://github.com/prettier/prettier) under the hood to beautify outgoing responses and/or other things in the Fastify server.
- [`fastify-print-routes`](https://github.com/ShogunPanda/fastify-print-routes) A Fastify plugin that prints all available routes.
Expand Down
32 changes: 32 additions & 0 deletions docs/Getting-Started.md
Expand Up @@ -262,6 +262,24 @@ async function routes (fastify, options) {
}
return result
})

const animalBodyJsonSchema = {
type: 'object',
required: ['animal'],
properties: {
animal: { type: 'string' },
},
}

const schema = {
body: animalBodyJsonSchema,
}

fastify.post('/animals', { schema }, async (request, reply) => {
// we can use the `request.body` object to get the data sent by the client
const result = await collection.insertOne({ animal: request.body.animal })
return result
})
}

module.exports = routes
Expand Down Expand Up @@ -363,6 +381,20 @@ fastify.get('/', opts, async (request, reply) => {
By specifying a schema as shown, you can speed up serialization by a factor of 2-3. This also helps to protect against leakage of potentially sensitive data, since Fastify will serialize only the data present in the response schema.
Read [Validation and Serialization](Validation-and-Serialization.md) to learn more.

<a name="request-payload"></a>
### Parsing request payloads
Fastify parses `'application/json'` and `'text/plain'` request payloads natively, with the result accessible from the [Fastify request](Request.md) object at `request.body`.<br>
The following example returns the parsed body of a request back to the client:

```js
const opts = {}
fastify.post('/', opts, async (request, reply) => {
return request.body
})
```

Read [Content Type Parser](ContentTypeParser.md) to learn more about Fastify's default parsing functionality and how to support other content types.

<a name="extend-server"></a>
### Extend your server
Fastify is built to be extremely extensible and minimal, we believe that a bare-bones framework is all that is necessary to make great applications possible.<br>
Expand Down
2 changes: 1 addition & 1 deletion docs/Hooks.md
Expand Up @@ -220,7 +220,7 @@ fastify.addHook('onTimeout', async (request, reply) => {
await asyncMethod()
})
```
`onTimeout` is useful if you need to monitor the request timed out in your service (if the `connectionTimeout` property is set on the Fastify instance). The `onTimeout` hook is executed when a request is timed out and the HTTP socket has been hanged up. Therefore ,you will not be able to send data to the client.
`onTimeout` is useful if you need to monitor the request timed out in your service (if the `connectionTimeout` property is set on the Fastify instance). The `onTimeout` hook is executed when a request is timed out and the HTTP socket has been hanged up. Therefore, you will not be able to send data to the client.


### Manage Errors from a hook
Expand Down
24 changes: 23 additions & 1 deletion docs/Logging.md
Expand Up @@ -2,6 +2,7 @@

## Logging

### Enable logging
Logging is disabled by default, and you can enable it by passing
`{ logger: true }` or `{ logger: { level: 'info' } }` when you create
a fastify instance. Note that if the logger is disabled, it is impossible to
Expand All @@ -11,13 +12,34 @@ this purpose.

As Fastify is focused on performance, it uses [pino](https://github.com/pinojs/pino) as its logger, with the default log level, when enabled, set to `'info'`.

Enabling the logger is extremely easy:
Enabling the production JSON logger:

```js
const fastify = require('fastify')({
logger: true
})
```

Enabling the logger with appropriate configuration for both local development and production environment requires bit more configuration:
```js
const fastify = require('fastify')({
logger: {
prettyPrint:
environment === 'development'
? {
translateTime: 'HH:MM:ss Z',
ignore: 'pid,hostname'
}
: false
}
})
```
⚠️ `pino-pretty` needs to be installed as a dev dependency, it is not included by default for performance reasons.

### Usage
You can use the logger like this in your route handlers:

```js
fastify.get('/', options, function (request, reply) {
request.log.info('Some info about the current request')
reply.send({ hello: 'world' })
Expand Down
2 changes: 1 addition & 1 deletion docs/Plugins.md
Expand Up @@ -4,7 +4,7 @@
Fastify allows the user to extend its functionalities with plugins.
A plugin can be a set of routes, a server [decorator](Decorators.md), or whatever. The API that you will need to use one or more plugins, is `register`.<br>

By default, `register` creates a *new scope*, this means that if you make some changes to the Fastify instance (via `decorate`), this change will not be reflected by the current context ancestors, but only to its sons. This feature allows us to achieve plugin *encapsulation* and *inheritance*, in this way we create a *direct acyclic graph* (DAG) and we will not have issues caused by cross dependencies.
By default, `register` creates a *new scope*, this means that if you make some changes to the Fastify instance (via `decorate`), this change will not be reflected by the current context ancestors, but only to its descendants. This feature allows us to achieve plugin *encapsulation* and *inheritance*, in this way we create a *direct acyclic graph* (DAG) and we will not have issues caused by cross dependencies.

You already see in the [getting started](Getting-Started.md#register) section how using this API is pretty straightforward.
```
Expand Down
74 changes: 55 additions & 19 deletions docs/Recommendations.md
Expand Up @@ -166,62 +166,94 @@ backend static-backend
### Nginx

```nginx
# This upstream block groups 3 servers into one named backend fastify_app
# with 2 primary servers distributed via round-robin
# and one backup which is used when the first 2 are not reachable
# This also assumes your fastify servers are listening on port 80.
# more info: http://nginx.org/en/docs/http/ngx_http_upstream_module.html
upstream fastify_app {
# more info: http://nginx.org/en/docs/http/ngx_http_upstream_module.html
server 10.10.11.1:80;
server 10.10.11.2:80;
server 10.10.11.3:80 backup;
}
# This server block asks NGINX to respond with a redirect when
# an incoming request from port 80 (typically plain HTTP), to
# the same request URL but with HTTPS as protocol.
# This block is optional, and usually used if you are handling
# SSL termination in NGINX, like in the example here.
server {
# default server
# default server is a special parameter to ask NGINX
# to set this server block to the default for this address/port
# which in this case is any address and port 80
listen 80 default_server;
listen [::]:80 default_server;
# specify host
# With a server_name directive you can also ask NGINX to
# use this server block only with matching server name(s)
# listen 80;
# listen [::]:80;
# server_name example.tld;
# This matches all paths from the request and responds with
# the redirect mentioned above.
location / {
return 301 https://$host$request_uri;
}
}
# This server block asks NGINX to respond to requests from
# port 443 with SSL enabled and accept HTTP/2 connections.
# This is where the request is then proxied to the fastify_app
# server group via port 3000.
server {
# default server
# This listen directive asks NGINX to accept requests
# coming to any address, port 443, with SSL, and HTTP/2
# if possible.
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
# specify host
# With a server_name directive you can also ask NGINX to
# use this server block only with matching server name(s)
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name example.tld;
# public private keys
# Your SSL/TLS certificate (chain) and secret key in the PEM format
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/private.pem;
ssl_trusted_certificate /path/to/chain.pem;
# use https://ssl-config.mozilla.org/ for best practice configuration
# A generic best practice baseline for based
# on https://ssl-config.mozilla.org/
ssl_session_timeout 1d;
ssl_session_cache shared:FastifyApp:10m;
ssl_session_tickets off;
# modern configuration
# This tells NGINX to only accept TLS 1.3, which should be fine
# with most modern browsers including IE 11 with certain updates.
# If you want to support older browsers you might need to add
# additional fallback protocols.
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
# This adds a header that tells browsers to only ever use HTTPS
# with this server.
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP stapling
# The following directives are only necessary if you want to
# enable OCSP Stapling.
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/chain.pem;
# custom resolver
# Custom nameserver to resolve upstream server names
# resolver 127.0.0.1;
# This section matches all paths and proxies it to the backend server
# group specified above. Note the additional headers that forward
# information about the original request. You might want to set
# trustProxy to the address of your NGINX server so the X-Forwarded
* fields are used by fastify.
location / {
# more info: http://nginx.org/en/docs/http/ngx_http_proxy_module.html
proxy_http_version 1.1;
Expand All @@ -232,8 +264,12 @@ server {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://fastify_app:3000;
# This is the directive that proxies requests to the specified server.
# If you are using an upstream group, then you do not need to specify a port.
# If you are directly proxying to a server e.g.
# proxy_pass http://127.0.0.1:3000 then specify a port.
proxy_pass http://fastify_app;
}
}
```
Expand Down
13 changes: 13 additions & 0 deletions docs/Reply.md
Expand Up @@ -7,6 +7,7 @@
- [.statusCode](#statusCode)
- [.server](#server)
- [.header(key, value)](#headerkey-value)
- [set-cookie](#set-cookie)
- [.headers(object)](#headersobject)
- [.getHeader(key)](#getheaderkey)
- [.getHeaders()](#getheaders)
Expand Down Expand Up @@ -109,6 +110,18 @@ fastify.get('/', async function (req, rep) {
Sets a response header. If the value is omitted or undefined, it is coerced
to `''`.

<a name="set-cookie"></a>
- ### set-cookie
- While sending different values as cookie with `set-cookie` as the key, every value will be sent as cookie instead of replacing the previous value.

```js
reply.header('set-cookie', 'foo');
reply.header('set-cookie', 'bar');
```
- The browser will only consider the latest reference of a key for `set-cookie` header. The fact that this is done this way is to avoid parsing the set-cookie header when you add it in the reply and speeds up the serialization of the reply.

- To reset the `set-cookie`, you need to make an explicit call to `reply.removeHeader('set-cookie')`, read more about `.removeHeader(key)` [here](#removeheaderkey).

For more information, see [`http.ServerResponse#setHeader`](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_response_setheader_name_value).

<a name="headers"></a>
Expand Down
2 changes: 1 addition & 1 deletion docs/Request.md
Expand Up @@ -4,7 +4,7 @@
The first parameter of the handler function is `Request`.<br>
Request is a core Fastify object containing the following fields:
- `query` - the parsed querystring, its format is specified by [`querystringParser`](Server.md#querystringparser)
- `body` - the body
- `body` - the request payload, see [Content Type Parser](ContentTypeParser.md) for details on what request payloads Fastify natively parses and how to support other content types
- `params` - the params matching the URL
- [`headers`](#headers) - the headers getter and setter
- `raw` - the incoming HTTP request from Node core
Expand Down
2 changes: 2 additions & 0 deletions docs/Routes.md
Expand Up @@ -52,6 +52,8 @@ They need to be in
* `preSerialization(request, reply, payload, done)`: a [function](Hooks.md#preserialization) called just before the serialization, it could also be an array of functions.
* `onSend(request, reply, payload, done)`: a [function](Hooks.md#route-hooks) called right before a response is sent, it could also be an array of functions.
* `onResponse(request, reply, done)`: a [function](Hooks.md#onresponse) called when a response has been sent, so you will not be able to send more data to the client. It could also be an array of functions.
* `onTimeout(request, reply, done)`: a [function](Hooks.md#ontimeout) called when a request is timed out and the HTTP socket has been hanged up.
* `onError(request, reply, error, done)`: a [function](Hooks.md#onerror) called when an Error is thrown or send to the client by the route handler.
* `handler(request, reply)`: the function that will handle this request. The [Fastify server](Server.md) will be bound to `this` when the handler is called. Note: using an arrow function will break the binding of `this`.
* `errorHandler(error, request, reply)`: a custom error handler for the scope of the request. Overrides the default error global handler, and anything set by [`setErrorHandler`](Server.md#setErrorHandler), for requests to the route. To access the default handler, you can access `instance.errorHandler`. Note that this will point to fastify's default `errorHandler` only if a plugin hasn't overridden it already.
* `validatorCompiler({ schema, method, url, httpPart })`: function that builds schemas for request validations. See the [Validation and Serialization](Validation-and-Serialization.md#schema-validator) documentation.
Expand Down
12 changes: 12 additions & 0 deletions docs/Server.md
Expand Up @@ -13,6 +13,7 @@ document describes the properties available in that options object.
- [connectionTimeout](./Server.md#connectiontimeout)
- [keepAliveTimeout](./Server.md#keepalivetimeout)
- [maxRequestsPerSocket](./Server.md#maxRequestsPerSocket)
- [requestTimeout](./Server.md#requestTimeout)
- [ignoreTrailingSlash](./Server.md#ignoretrailingslash)
- [maxParamLength](./Server.md#maxparamlength)
- [onProtoPoisoning](./Server.md#onprotopoisoning)
Expand Down Expand Up @@ -94,6 +95,17 @@ is in use. Also, when `serverFactory` option is specified, this option is ignore
+ Default: `0` (no limit)

<a name="factory-request-timeout"></a>
### `requestTimeout`

Defines the maximum number of milliseconds for receiving the entire request from the client.
[`server.requestTimeout` property](https://nodejs.org/dist/latest/docs/api/http.html#http_server_requesttimeout)
to understand the effect of this option. Also, when `serverFactory` option is specified, this option is ignored.
It must be set to a non-zero value (e.g. 120 seconds) to protect against potential Denial-of-Service attacks in case the server is deployed without a reverse proxy in front.
> At the time of this writing, only node version greater or equal to 14.11.0 support this option. Check the Node.js documentation for availability in the version you are running.
+ Default: `0` (no limit)

<a name="factory-ignore-slash"></a>
### `ignoreTrailingSlash`

Expand Down

0 comments on commit f57a435

Please sign in to comment.