Skip to content

Commit

Permalink
Update: 92e4e19...c872f0b
Browse files Browse the repository at this point in the history
  • Loading branch information
fralonra committed Dec 4, 2021
1 parent a951d0a commit 12b3f21
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 18 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
@@ -0,0 +1,3 @@
{
"editor.formatOnSave": false
}
4 changes: 2 additions & 2 deletions docs/ContentTypeParser.md
Expand Up @@ -83,15 +83,15 @@ fastify.addContentTypeParser('text/xml', function (request, payload, done) {
})

// 移除内建的 content type 解析器。这时只有上文添加的 text/html 解析器可用。
fastiy.removeContentTypeParser(['application/json', 'text/plain'])
Fastiy.removeContentTypeParser(['application/json', 'text/plain'])
```

#### removeAllContentTypeParsers

在上文的例子中,你需要明确指定所有你想移除的 content type。但你也可以使用 `removeAllContentTypeParsers`直接移除所有现存的 content type 解析器。在下面的例子里,我们实现了一样的效果,但不再需要手动指定 content type 了。和 `removeContentTypeParser` 一样,该 API 也支持封装。当你想注册一个[能捕获所有 content type 的解析器](#Catch-All),且忽略内建的解析器时,这个 API 特别有用。

```js
fastiy.removeAllContentTypeParsers()
Fastiy.removeAllContentTypeParsers()

fastify.addContentTypeParser('text/xml', function (request, payload, done) {
xmlParser(payload, function (err, body) {
Expand Down
78 changes: 75 additions & 3 deletions docs/Getting-Started.md
Expand Up @@ -21,6 +21,13 @@ yarn add fastify
让我们开始编写第一个服务器吧:
```js
// 加载框架并新建实例

// ESM
import Fastify from 'fastify'
const fastify = Fastify({
logger: true
})
// CommonJs
const fastify = require('fastify')({
logger: true
})
Expand All @@ -36,13 +43,19 @@ fastify.listen(3000, function (err, address) {
fastify.log.error(err)
process.exit(1)
}
fastify.log.info(`server listening on ${address}`)
// 服务器监听地址:${address}
})
```

更喜欢使用 `async/await`?Fastify 对其提供了开箱即用的支持。<br>
*(我们还建议使用 [make-promises-safe](https://github.com/mcollina/make-promises-safe) 来避免文件描述符 (file descriptor) 及内存的泄露)*
```js
// ESM
import Fastify from 'fastify'
const fastify = Fastify({
logger: true
})
// CommonJs
const fastify = require('fastify')({
logger: true
})
Expand Down Expand Up @@ -89,6 +102,26 @@ start()
在深入之前,先来看看插件系统是如何工作的吧!<br>
让我们新建一个基本的服务器,但这回我们把路由 (route) 的声明从入口文件转移到一个外部文件。(参阅[路由声明](Routes.md))。
```js
// ESM
import Fastify from 'fastify'
import firstRoute from './our-first-route'
const fastify = Fastify({
logger: true
})

fastify.register(firstRoute)

fastify.listen(3000, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// 服务器监听地址:${address}
})
```

```js
// CommonJs
const fastify = require('fastify')({
logger: true
})
Expand All @@ -100,7 +133,7 @@ fastify.listen(3000, function (err, address) {
fastify.log.error(err)
process.exit(1)
}
fastify.log.info(`server listening on ${address}`)
// 服务器监听地址:${address}
})
```

Expand Down Expand Up @@ -132,6 +165,28 @@ npm i --save fastify-plugin fastify-mongodb

**server.js**
```js
// ESM
import Fastify from 'fastify'
import dbConnector from './our-db-connector'
import firstRoute from './our-first-route'

const fastify = Fastify({
logger: true
})
fastify.register(dbConnector)
fastify.register(firstRoute)

fastify.listen(3000, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// 服务器监听地址:${address}
})
```

```js
// CommonJs
const fastify = require('fastify')({
logger: true
})
Expand All @@ -144,13 +199,30 @@ fastify.listen(3000, function (err, address) {
fastify.log.error(err)
process.exit(1)
}
fastify.log.info(`server listening on ${address}`)
// 服务器监听地址:${address}
})

```

**our-db-connector.js**
```js
// ESM
import fastifyPlugin from 'fastify-plugin'
import fastifyMongo from 'fastify-mongodb'

async function dbConnector (fastify, options) {
fastify.register(fastifyMongo, {
url: 'mongodb://localhost:27017/test_database'
})
}

// 用 fastify-plugin 包装插件,以使插件中声明的装饰器、钩子函数暴露在根作用域里。
module.exports = fastifyPlugin(dbConnector)

```

```js
// CommonJs
const fastifyPlugin = require('fastify-plugin')

async function dbConnector (fastify, options) {
Expand Down
34 changes: 34 additions & 0 deletions docs/Hooks.md
Expand Up @@ -543,3 +543,37 @@ fastify.route({
```

****:两个选项都接受一个函数数组作为参数。

## 诊断通道钩子

> **注:** `诊断通道` (diagnostics_channel) 是当前 Node.js 的试验特性,
> 因此,其 API 即便在补丁版本中也可能会发生变动。
> 对于 Fastify 支持的 Node.js 版本,不兼容 `诊断通道` 的,
> 将会使用 [polyfill](https://www.npmjs.com/package/diagnostics_channel)
> 而 polyfill 都不支持的版本将无法使用该特性。
当前版本在初始化时,会有一个[`诊断通道`](https://nodejs.org/api/diagnostics_channel.html)发布 `'fastify.initialization'` 事件。此时,Fastify 的实例将会作为回调函数参数的一个属性,该实例可以添加钩子、插件、路由及其他任意内容。

举例来说,某个监控工具可以如下使用(当然这是一个简化的例子)。在典型的“探测工具优先加载 (require instrumentation
tools first)”风格下,这段代码会在被监控的应用初始化时加载。

```js
const tracer = /* 某个监控工具 */
const dc = require('diagnostics_channel')
const channel = dc.channel('fastify.initialization')
const spans = new WeakMap()

channel.subscribe(function ({ fastify }) {
fastify.addHook('onRequest', (request, reply, done) => {
const span = tracer.startSpan('fastify.request')
spans.set(request, span)
done()
})

fastify.addHook('onResponse', (request, reply, done) => {
const span = spans.get(request)
span.finish()
done()
})
})
```
2 changes: 1 addition & 1 deletion docs/Lifecycle.md
Expand Up @@ -19,7 +19,7 @@ Incoming Request
4**/5** ◀─┴─▶ preValidation Hook
415 ◀─┴─▶ Validation
400 ◀─┴─▶ Validation
4**/5** ◀─┴─▶ preHandler Hook
Expand Down
81 changes: 80 additions & 1 deletion docs/Recommendations.md
Expand Up @@ -27,7 +27,9 @@ Fastify 团队**强烈**地认为上述做法是一种反面模式,是非常
1. 应用需要处理多域名。
1. 应用需要处理静态资源,例如 jpeg 文件。

反向代理的解决方案有很多种,例如 AWS 与 GCP,具体根据环境来择用。对于上述的案例,我们可以使用 [HAProxy][haproxy]
反向代理的解决方案有很多种,例如 AWS 与 GCP,具体根据环境来择用。对于上述的案例,我们可以使用 [HAProxy][haproxy][Nginx][nginx]

### HAProxy

```conf
# global 定义了 HAProxy 实例的基础配置。
Expand Down Expand Up @@ -134,6 +136,83 @@ backend static-backend
[why-use]: https://web.archive.org/web/20190821102906/https://medium.com/intrinsic/why-should-i-use-a-reverse-proxy-if-node-js-is-production-ready-5a079408b2ca
[haproxy]: https://www.haproxy.org/

### Nginx

```nginx
upstream fastify_app {
# 更多信息请见: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;
}
server {
# 默认服务器
listen 80 default_server;
listen [::]:80 default_server;
# 指定端口
# listen 80;
# listen [::]:80;
# server_name example.tld;
location / {
return 301 https://$host$request_uri;
}
}
server {
# 默认服务器
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
# 指定端口
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name example.tld;
# 密钥
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/private.pem;
ssl_trusted_certificate /path/to/chain.pem;
# 通过 https://ssl-config.mozilla.org/ 生成最佳配置
ssl_session_timeout 1d;
ssl_session_cache shared:FastifyApp:10m;
ssl_session_tickets off;
# 现代化配置
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# HTTP 严格传输安全 (HSTS) (需要 ngx_http_headers_module 模块) (63072000 秒)
add_header Strict-Transport-Security "max-age=63072000" always;
# 在线证书状态协议缓存 (OCSP stapling)
ssl_stapling on;
ssl_stapling_verify on;
# 自定义域名解析器 (resolver)
# resolver 127.0.0.1;
location / {
# 更多信息请见:http://nginx.org/en/docs/http/ngx_http_proxy_module.html
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
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;
}
}
```

[nginx]: https://nginx.org/

## Kubernetes
<a id="kubernetes"></a>

Expand Down
2 changes: 1 addition & 1 deletion docs/Reply.md
Expand Up @@ -339,7 +339,7 @@ fastify.get('/', {
})
```

如果你想完全自定义错误处理,请看 [`setErrorHandler`](Server.md#seterrorhandler) API。<br>
如果你想自定义错误处理,请看 [`setErrorHandler`](Server.md#seterrorhandler) API。<br>
*注:当自定义错误处理时,你需要自行记录日志*

API:
Expand Down
6 changes: 3 additions & 3 deletions docs/Request.md
Expand Up @@ -3,18 +3,18 @@
## Request
处理函数的第一个参数是 `Request`.<br>
Request 是 Fastify 的核心对象,包含了以下字段:
- `query` - 解析后的 querystring
- `query` - 解析后的 querystring,其格式由 [`querystringParser`](Server.md#querystringParser) 指定。
- `body` - 消息主体
- `params` - URL 参数
- [`headers`](#headers) - header 的 getter 与 setter
- `raw` - Node 原生的 HTTP 请求
- `req` *(不推荐,请使用 `.raw`)* - Node 原生的 HTTP 请求
- `server` - Fastify 服务器的实例,以当前的[封装上下文](Encapsulation.md)为作用域。
- `id` - 请求 id
- `id` - 请求 ID
- `log` - 请求的日志实例
- `ip` - 请求方的 ip 地址
- `ips` - x-forwarder-for header 中保存的请求源 ip 数组,按访问先后排序 (仅当 [`trustProxy`](Server.md#factory-trust-proxy) 开启时有效)
- `hostname` - 请求方的主机名 (当 [`trustProxy`](Server.md#factory-trust-proxy) 启用时,从 `X-Forwarded-Host` header 中获取)
- `hostname` - 请求方的主机名 (当 [`trustProxy`](Server.md#factory-trust-proxy) 启用时,从 `X-Forwarded-Host` header 中获取)。为了兼容 HTTP/2,当没有相关 header 存在时,将返回 `:authority`
- `protocol` - 请求协议 (`https``http`)
- `method` - 请求方法
- `url` - 请求路径
Expand Down

0 comments on commit 12b3f21

Please sign in to comment.