Skip to content

Commit

Permalink
Merge branch 'main' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
jsumners committed May 4, 2024
2 parents ef1c2c7 + bf64e47 commit d27325a
Show file tree
Hide file tree
Showing 19 changed files with 471 additions and 100 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ jobs:
uses: ./.github/workflows/coverage-win.yml

test-unit:
needs:
needs:
- lint
- coverage-nix
- coverage-win
Expand All @@ -113,6 +113,9 @@ jobs:
matrix:
node-version: [16, 18, 20]
os: [macos-latest, ubuntu-latest, windows-latest]
exclude:
- os: macos-latest
node-version: 16

steps:
- uses: actions/checkout@v4
Expand All @@ -135,7 +138,7 @@ jobs:
npm run unit
test-typescript:
needs:
needs:
- lint
- coverage-nix
- coverage-win
Expand Down Expand Up @@ -201,7 +204,7 @@ jobs:
if: >
github.event_name == 'pull_request' &&
github.event.pull_request.user.login == 'dependabot[bot]'
needs:
needs:
- test-typescript
- test-unit
- package
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/links-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
# See: https://github.com/lycheeverse/lychee-action/issues/17
- name: Link Checker
id: lychee
uses: lycheeverse/lychee-action@c053181aa0c3d17606addfe97a9075a32723548a
uses: lycheeverse/lychee-action@2b973e86fc7b1f6b36a93795fe2c9c6ae1118621
with:
fail: true
# As external links behavior is not predictable, we check only internal links
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ yarn add fastify

// ESM
import Fastify from 'fastify'

const fastify = Fastify({
logger: true
})
Expand All @@ -150,6 +151,7 @@ with async-await:
```js
// ESM
import Fastify from 'fastify'

const fastify = Fastify({
logger: true
})
Expand Down Expand Up @@ -323,6 +325,8 @@ listed in alphabetical order.
<https://twitter.com/jsumners79>, <https://www.npmjs.com/~jsumners>
* [__Aras Abbasi__](https://github.com/uzlopak),
<https://www.npmjs.com/~uzlopak>
* [__Gürgün Dayıoğlu__](https://github.com/gurgunday),
<https://www.npmjs.com/~gurgunday>

### Fastify Plugins team
* [__Matteo Collina__](https://github.com/mcollina),
Expand Down
10 changes: 6 additions & 4 deletions docs/Guides/Detecting-When-Clients-Abort.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,12 @@ of `{ ok: true }`.
- Logic that triggers in the hook when the request is closed.
- Logging that occurs when the closed request property `aborted` is true.

In the request close event, you should examine the diff between a successful
request and one aborted by the client to determine the best property for your
use case. You can find details about request properties in the
[Node.js documentation](https://nodejs.org/api/http.html).
Whilst the `aborted` property has been deprecated, `destroyed` is not a
suitable replacement as the
[Node.js documentation suggests](https://nodejs.org/api/http.html#requestaborted).
A request can be `destroyed` for various reasons, such as when the server closes
the connection. The `aborted` property is still the most reliable way to detect
when a client intentionally aborts a request.

You can also perform this logic outside of a hook, directly in a specific route.

Expand Down
3 changes: 3 additions & 0 deletions docs/Guides/Ecosystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ section.
plugin to authenticate HTTP requests based on API key and signature
- [`fastify-appwrite`](https://github.com/Dev-Manny/fastify-appwrite) Fastify
Plugin for interacting with Appwrite server.
- [`fastify-asyncforge`](https://github.com/mcollina/fastify-asyncforge) Plugin
to access Fastify instance, logger, request and reply from Node.js [Async
Local Storage](https://nodejs.org/api/async_context.html#class-asynclocalstorage).
- [`fastify-at-mysql`](https://github.com/mateonunez/fastify-at-mysql) Fastify
MySQL plugin with auto SQL injection attack prevention.
- [`fastify-at-postgres`](https://github.com/mateonunez/fastify-at-postgres) Fastify
Expand Down
2 changes: 2 additions & 0 deletions docs/Guides/Getting-Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Let's write our first server:

// ESM
import Fastify from 'fastify'

const fastify = Fastify({
logger: true
})
Expand Down Expand Up @@ -68,6 +69,7 @@ Do you prefer to use `async/await`? Fastify supports it out-of-the-box.
```js
// ESM
import Fastify from 'fastify'

const fastify = Fastify({
logger: true
})
Expand Down
3 changes: 2 additions & 1 deletion docs/Reference/Routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ fastify.route(options)

* `method`: currently it supports `'DELETE'`, `'GET'`, `'HEAD'`, `'PATCH'`,
`'POST'`, `'PUT'`, `'OPTIONS'`, `'SEARCH'`, `'TRACE'`, `'PROPFIND'`,
`'PROPPATCH'`, `'MKCOL'`, `'COPY'`, `'MOVE'`, `'LOCK'` and `'UNLOCK'`.
`'PROPPATCH'`, `'MKCOL'`, `'COPY'`, `'MOVE'`, `'LOCK'`, `'UNLOCK'`,
`'REPORT'` and `'MKCALENDAR'`.
It could also be an array of methods.
* `url`: the path of the URL to match this route (alias: `path`).
* `schema`: an object containing the schemas for the request and response. They
Expand Down
12 changes: 9 additions & 3 deletions docs/Reference/Server.md
Original file line number Diff line number Diff line change
Expand Up @@ -383,9 +383,15 @@ been sent. By setting this option to `true`, these log messages will be
disabled. This allows for more flexible request start and end logging by
attaching custom `onRequest` and `onResponse` hooks.

Please note that this option will also disable an error log written by the
default `onResponse` hook on reply callback errors. Other log messages
emitted by Fastify will stay enabled, like deprecation warnings and messages
The other log entries that will be disabled are:
- an error log written by the default `onResponse` hook on reply callback errors
- the error and info logs written by the `defaultErrorHandler`
on error management
- the info log written by the `fourOhFour` handler when a
non existent route is requested

Other log messages emitted by Fastify will stay enabled,
like deprecation warnings and messages
emitted when requests are received while the server is closing.

```js
Expand Down
39 changes: 24 additions & 15 deletions lib/error-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const {
kReplyNextErrorHandler,
kReplyIsRunningOnErrorHook,
kReplyHasStatusCode,
kRouteContext
kRouteContext,
kDisableRequestLogging
} = require('./symbols.js')

const {
Expand Down Expand Up @@ -35,10 +36,12 @@ function handleError (reply, error, cb) {
try {
reply.raw.writeHead(reply.raw.statusCode, reply[kReplyHeaders])
} catch (error) {
reply.log.warn(
{ req: reply.request, res: reply, err: error },
error && error.message
)
if (!reply.log[kDisableRequestLogging]) {
reply.log.warn(
{ req: reply.request, res: reply, err: error },
error && error.message
)
}
reply.raw.writeHead(reply.raw.statusCode)
}
reply.raw.end(payload)
Expand Down Expand Up @@ -79,15 +82,19 @@ function defaultErrorHandler (error, request, reply) {
reply.code(statusCode >= 400 ? statusCode : 500)
}
if (reply.statusCode < 500) {
reply.log.info(
{ res: reply, err: error },
error && error.message
)
if (!reply.log[kDisableRequestLogging]) {
reply.log.info(
{ res: reply, err: error },
error && error.message
)
}
} else {
reply.log.error(
{ req: request, res: reply, err: error },
error && error.message
)
if (!reply.log[kDisableRequestLogging]) {
reply.log.error(
{ req: request, res: reply, err: error },
error && error.message
)
}
}
reply.send(error)
}
Expand All @@ -112,8 +119,10 @@ function fallbackErrorHandler (error, reply, cb) {
statusCode: { value: statusCode }
}))
} catch (err) {
// error is always FST_ERR_SCH_SERIALIZATION_BUILD because this is called from route/compileSchemasForSerialization
reply.log.error({ err, statusCode: res.statusCode }, 'The serializer for the given status code failed')
if (!reply.log[kDisableRequestLogging]) {
// error is always FST_ERR_SCH_SERIALIZATION_BUILD because this is called from route/compileSchemasForSerialization
reply.log.error({ err, statusCode: res.statusCode }, 'The serializer for the given status code failed')
}
reply.code(500)
payload = serializeError(new FST_ERR_FAILED_ERROR_SERIALIZATION(err.message, error.message))
}
Expand Down
6 changes: 4 additions & 2 deletions lib/fourOhFour.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const { getGenReqId } = require('./reqIdGenFactory.js')
* kFourOhFourContext: the context in the reply object where the handler will be executed
*/
function fourOhFour (options) {
const { logger } = options
const { logger, disableRequestLogging } = options

// 404 router, used for handling encapsulated 404 handlers
const router = FindMyWay({ onBadUrl: createOnBadUrl(), defaultRoute: fourOhFourFallBack })
Expand All @@ -49,7 +49,9 @@ function fourOhFour (options) {
function basic404 (request, reply) {
const { url, method } = request.raw
const message = `Route ${method}:${url} not found`
request.log.info(message)
if (!disableRequestLogging) {
request.log.info(message)
}
reply.code(404).send({
message,
error: 'Not Found',
Expand Down
37 changes: 21 additions & 16 deletions lib/handleRequest.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use strict'

const { bodylessMethods, bodyMethods } = require('./httpMethods')
const { validate: validateSchema } = require('./validation')
const { preValidationHookRunner, preHandlerHookRunner } = require('./hooks')
const wrapThenable = require('./wrapThenable')
Expand All @@ -21,36 +20,42 @@ function handleRequest (err, request, reply) {
const headers = request.headers
const context = request[kRouteContext]

if (bodylessMethods.has(method)) {
if (method === 'GET' || method === 'HEAD') {
handler(request, reply)
return
}

if (bodyMethods.has(method)) {
const contentType = headers['content-type']
const contentLength = headers['content-length']
const transferEncoding = headers['transfer-encoding']
const contentType = headers['content-type']

if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'TRACE' || method === 'SEARCH' ||
method === 'PROPFIND' || method === 'PROPPATCH' || method === 'LOCK' || method === 'REPORT' || method === 'MKCALENDAR') {
if (contentType === undefined) {
if (
(contentLength === undefined || contentLength === '0') &&
transferEncoding === undefined
) {
// Request has no body to parse
headers['transfer-encoding'] === undefined &&
(headers['content-length'] === '0' || headers['content-length'] === undefined)
) { // Request has no body to parse
handler(request, reply)
} else {
context.contentTypeParser.run('', handler, request, reply)
}
} else {
if (contentLength === undefined && transferEncoding === undefined && method === 'OPTIONS') {
// OPTIONS can have a Content-Type header without a body
handler(request, reply)
return
}

context.contentTypeParser.run(contentType, handler, request, reply)
}
return
}

if (method === 'OPTIONS' || method === 'DELETE') {
if (
contentType !== undefined &&
(
headers['transfer-encoding'] !== undefined ||
headers['content-length'] !== undefined
)
) {
context.contentTypeParser.run(contentType, handler, request, reply)
} else {
handler(request, reply)
}
return
}

Expand Down
50 changes: 18 additions & 32 deletions lib/httpMethods.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,24 @@
'use strict'

const bodylessMethods = new Set([
// Standard
'GET',
'HEAD',
'TRACE',

// WebDAV
'UNLOCK'
])

const bodyMethods = new Set([
// Standard
'DELETE',
'OPTIONS',
'PATCH',
'PUT',
'POST',

// WebDAV
'COPY',
'LOCK',
'MOVE',
'MKCOL',
'PROPFIND',
'PROPPATCH',
'SEARCH'
])

module.exports = {
bodylessMethods,
bodyMethods,
supportedMethods: [
...bodylessMethods,
...bodyMethods
'DELETE',
'GET',
'HEAD',
'PATCH',
'POST',
'PUT',
'OPTIONS',
'PROPFIND',
'PROPPATCH',
'MKCOL',
'COPY',
'MOVE',
'LOCK',
'UNLOCK',
'TRACE',
'SEARCH',
'REPORT',
'MKCALENDAR'
]
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
},
{
"name": "Gürgün Dayıoğlu",
"email": "gurgun.dayioglu@icloud.com",
"email": "hey@gurgun.day",
"url": "https://heyhey.to/G"
},
{
Expand Down Expand Up @@ -202,10 +202,11 @@
"@fastify/pre-commit": "^2.1.0",
"abstract-logging": "^2.0.1",
"avvio": "^8.3.0",
"fast-content-type-parse": "^1.1.0",
"fast-json-stringify": "^5.14.1",
"find-my-way": "^8.1.0",
"light-my-request": "^5.13.0",
"pino": "^8.20.0",
"pino": "^9.0.0",
"process-warning": "^3.0.0",
"proxy-addr": "^2.0.7",
"rfdc": "^1.3.1",
Expand Down

0 comments on commit d27325a

Please sign in to comment.