Skip to content

feat(validate): support async validation within defineValidatedHandler#1491

Merged
pi0 merged 1 commit into
h3js:mainfrom
sandros94:feat/async-validated-handler
Jul 20, 2026
Merged

feat(validate): support async validation within defineValidatedHandler#1491
pi0 merged 1 commit into
h3js:mainfrom
sandros94:feat/async-validated-handler

Conversation

@sandros94

@sandros94 sandros94 commented Jul 20, 2026

Copy link
Copy Markdown
Member

Discussed in #1437

This is the first PR of hopefully a few related to improving validation strictness and related type support within h3's toolset.

In this change I solely focus on adding async support for query and header validaiton within defineValidatedHandler that were previously sync-only.

Summary by CodeRabbit

  • New Features

    • Added support for asynchronous validation of request bodies, headers, and query parameters.
    • Async validation results are now correctly awaited before handlers run.
  • Bug Fixes

    • Invalid asynchronously validated inputs now return the expected validation errors and HTTP 400 responses.
    • Preserved existing custom validation error behavior.

`defineValidatedHandler`'s query and headers
@sandros94
sandros94 requested a review from pi0 as a code owner July 20, 2026 16:48
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Asynchronous schema validation is supported for request headers and URL queries. Validated handlers now await request and URL validation, and handler tests cover successful validation plus invalid body, header, and query cases.

Changes

Async validation support

Layer / File(s) Summary
Awaitable validation helpers
src/utils/internal/validate.ts
validatedRequest, validatedURL, and the shared validation helper now await asynchronous schema results.
Handler integration and coverage
src/handler.ts, test/handler.test.ts
defineValidatedHandler awaits validated request and URL values, with tests for valid and invalid asynchronous refinements.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: pi0, pi0

Poem

I’m a bunny with a schema to check,
Awaiting each carrot-shaped request.
Headers and queries hop safely through,
Bodies get tested for names that are taboo.
With promises tucked under my ear,
Valid handlers now always appear.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding async validation support in defineValidatedHandler.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/utils/internal/validate.ts (1)

91-97: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Fix variable naming for consistency.

Consider renaming validatedheaders to validatedHeaders to follow camelCase conventions.

♻️ Proposed refactor
-    const validatedheaders = await validateSource(
+    const validatedHeaders = await validateSource(
       "headers",
       Object.fromEntries(req.headers.entries()),
       validate.headers as StandardSchemaV1<Record<string, string>>,
       validate.onError,
     );
-    for (const [key, value] of Object.entries(validatedheaders)) {
+    for (const [key, value] of Object.entries(validatedHeaders)) {
       req.headers.set(key, value);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/internal/validate.ts` around lines 91 - 97, Rename the local
variable validatedheaders to validatedHeaders in the validation flow, including
its declaration and the Object.entries iteration, while preserving the existing
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/utils/internal/validate.ts`:
- Around line 91-97: Rename the local variable validatedheaders to
validatedHeaders in the validation flow, including its declaration and the
Object.entries iteration, while preserving the existing behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c3e97fa2-2738-487c-bc2f-4f258e81b917

📥 Commits

Reviewing files that changed from the base of the PR and between 6257713 and bab34c1.

📒 Files selected for processing (3)
  • src/handler.ts
  • src/utils/internal/validate.ts
  • test/handler.test.ts

@pi0

pi0 commented Jul 20, 2026

Copy link
Copy Markdown
Member

Only can you double check it is all compliant with standard-schema?

@sandros94

sandros94 commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

Only can you double check it is all compliant with standard-schema?

yes, ~standard.validate() can both be sync and async, depending on how the schema validation was constructed/used.

I've added some new zod tests that do have a async refines, which forces ~standard.validate() to be a promise

EDIT: the upstream standard-schema example for sync-only usage is for libs that might not support async operations, like some sort of hooks, but we have no such limitation

onError?: OnValidateError,
): T {
const result = fn["~standard"].validate(data);
if (result instanceof Promise) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do later but Promise chaining should be prefered over forced async keyword (it forces code to resume in next tick even if not needed to!) part of why H3Core is fast is that we avoid async/await

@pi0 pi0 changed the title fix(validate): support async validation within defineValidatedHandler feat(validate): support async validation within defineValidatedHandler Jul 20, 2026
@pi0
pi0 merged commit 0a9d5f9 into h3js:main Jul 20, 2026
7 checks passed
@sandros94
sandros94 deleted the feat/async-validated-handler branch July 21, 2026 11:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants