← All articles and news

Development

Fastify: JSON validation and testing invalid requests

Define input and response schemas and test a rejected request without opening a network port.

MerMiko2 min read

Treat validation as an application boundary

Validate client data before logic that writes to a database. A schema describes the data shape; it does not replace authorization, rate limits or business rules. Set text-length limits and meaningful numeric ranges. Do not build executable schemas from user-submitted code.

Define input and output

This example assumes a Node.js project with Fastify and ES modules. Match the Node version to the framework release. The response schema determines which fields are serialized.

import Fastify from "fastify";
const app = Fastify();
app.post("/notes", {
  schema: {
    body: {
      type: "object",
      required: ["text"],
      properties: {
        text: { type: "string", minLength: 1, maxLength: 500 }
      }
    },
    response: {
      201: { type: "object", properties: { ok: { type: "boolean" } } }
    }
  }
}, async (request, reply) => {
  return reply.code(201).send({ ok: true });
});

The example does not persist a note. A real application must check the user’s identity and permission before writing. Validator defaults may modify inputs; decide whether type coercion or removal of additional properties is appropriate, and test that policy explicitly.

Test rejected input

const result = await app.inject({
  method: "POST",
  url: "/notes",
  payload: { text: "" }
});
if (result.statusCode !== 400) throw new Error("Expected 400");
await app.close();

Add a valid request, a missing field and an oversized string. inject exercises routing without opening a public port. Avoid testing only the exact wording of an error: verify the status and that persistence logic did not run.

Keep expensive I/O out of structural validation

Database account checks or external API calls belong in a suitable hook after structural validation. Limit body size, request volume and operation duration separately. Never return raw exceptions, secrets or database connection details to clients.

Sources and documentation

Source links are retained for checking dates, availability and original context.

Continue reading

Guide library Latest news