fastify / fastify/fastify

compileSerializationSchema reuses the first serializer when metadata changes

Open
#6,987 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
37.1k
Forks
3k
Avg merge
1d 15h
Merged PRs (30d)
13

Description

### Description

`reply.compileSerializationSchema()` forwards `httpStatus` and `contentType` to a custom serializer compiler, but its cache is keyed only by the schema object. Reusing the same schema object with different metadata therefore returns the serializer compiled for the first call.

This is present on `main` at `1beaf7e72d24b2fc63a02a7f5806772a00e45454`:

- [`compileSerializationSchema` checks and stores by schema identity only](https://github.com/fastify/fastify/blob/1beaf7e72d24b2fc63a02a7f5806772a00e45454/lib/reply.js#L373-L408)
- [The documentation says both optional values are forwarded to a custom compiler](https://github.com/fastify/fastify/blob/1beaf7e72d24b2fc63a02a7f5806772a00e45454/docs/Reference/Reply.md#L426-L437)

### Reproduction

```js
const Fastify = require('fastify')

const app = Fastify()
const compiled = []

app.setSerializerCompiler(({ httpStatus, contentType }) => {
compiled.push({ httpStatus, contentType })
return (data) => JSON.stringify({ httpStatus, contentType, data })
})

app.get('/', (_request, reply) => {
const schema = { type: 'object' }
const first = reply.compileSerializationSchema(schema, '200', 'application/json')
const second = reply.compileSerializationSchema(schema, '201', 'application/vnd.example+json')

return {
sameFunction: first === second,
compiled,
first: first({ value: 1 }),
second: second({ value: 2 }),
}
})

app.inject({ method: 'GET', url: '/' }).then(({ payload }) => console.log(payload))
```

### Actual behavior

The compiler is invoked once, `sameFunction` is `true`, and both calls use the `200` / `application/json` metadata captured by the first serializer.

### Expected behavior

Changing `httpStatus` or `contentType` should produce (or retrieve) a serializer compiled for that metadata tuple.

### Possible direction

Keep the weak schema identity cache, but store serializers below it by `httpStatus` and `contentType`, including a stable representation for omitted values.

I found this while benchmarking an automated code-review workflow and manually verified the source path and reproduction before reporting it.

Contributor guide

Open the contributing guide

Research direction

Read lib/reply.js at compileSerializationSchema and compare its cache behavior with the forwarding contract in docs/Reference/Reply.md. Use the supplied reproduction to verify the behavior; done when serializers are reused only for identical schema and metadata tuples and metadata changes produce matching serializers.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.