Skip to content

Improve implicit FormData detection. Add tests.#1539

Open
aphofstede wants to merge 2 commits intoacacode:mainfrom
aphofstede:fix/1538-content-type-detection
Open

Improve implicit FormData detection. Add tests.#1539
aphofstede wants to merge 2 commits intoacacode:mainfrom
aphofstede:fix/1538-content-type-detection

Conversation

@aphofstede
Copy link

@aphofstede aphofstede commented Dec 2, 2025

Avoid matching "File" type usage too broadly.
Fixes #1538


Note

Use precise regex matching to detect actual File/binary request bodies as FormData and add tests covering custom formats and false positives.

  • Schema Routes (src/schema-routes/schema-routes.ts):
    • Refine implicit FormData detection: replace simple substring check with escaped regex that matches whole File/binary types (including arrays/unions) while avoiding false positives (e.g., FileType).
  • Tests (tests/spec/implicitFormData/):
    • Add OpenAPI schema (schema.json), test (basic.test.ts), and snapshot verifying:
      • File/binary properties trigger FormData.
      • Custom formats mapping to non-File types (e.g., FileType) do not.
      • Custom formats mapping to File do.
      • Component names containing "File" do not trigger FormData.

Written by Cursor Bugbot for commit 4a39905. This will update automatically on new commits. Configure here.

@changeset-bot
Copy link

changeset-bot bot commented Dec 2, 2025

⚠️ No Changeset found

Latest commit: 54adc23

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@aphofstede aphofstede force-pushed the fix/1538-content-type-detection branch from e12e441 to 4a39905 Compare December 2, 2025 18:23
@aphofstede aphofstede changed the title Improve implicit form data detection. Add tests. Improve implicit FormFata detection. Add tests. Dec 4, 2025
@smorimoto
Copy link
Collaborator

bugbot run

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no bugs!


@aphofstede aphofstede changed the title Improve implicit FormFata detection. Add tests. Improve implicit FormData detection. Add tests. Dec 18, 2025
@aphofstede
Copy link
Author

You want to merge it @smorimoto?

Copilot AI review requested due to automatic review settings February 26, 2026 13:54
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refines the “implicit FormData detection” workaround so it only triggers for actual File/binary request body types (avoiding false positives like FileType), and adds a dedicated spec fixture to lock in the intended behavior (Fixes #1538).

Changes:

  • Tighten implicit FormData detection in SchemaRoutes by replacing a substring check with a more precise regex match.
  • Add a new OpenAPI spec fixture and a Vitest snapshot test covering true positives (file/binary) and false positives (custom formats / component names containing File).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/schema-routes/schema-routes.ts Updates the implicit FormData detection heuristic to avoid matching File* type names too broadly.
tests/spec/implicitFormData/schema.json Adds a spec fixture with endpoints exercising file/binary detection and multiple false-positive scenarios.
tests/spec/implicitFormData/basic.test.ts Adds a snapshot test that generates a client from the fixture and asserts the expected ContentType selection.
tests/spec/implicitFormData/__snapshots__/basic.test.ts.snap Captures the expected generated output for the new spec test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +583 to +589
// Match e.g. ": File" followed by word boundary, array brackets, or union/nullable syntax
// This prevents false positives like ": FileType" or ": SomeFile"
// Escape special regex characters (getSchemaType can theoretically return complex types like "File | null" or "UtilRequiredKeys<File, ...>")
const escapedType = dataType.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
return new RegExp(`:\\s*${escapedType}(?:\\[\\]|\\s*\\||\\b|$)`).test(
content,
);
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

The regex only matches : File followed by []/|/word-boundary, but it won’t match array types produced as : (File)[] (or : (File | null)[]) because of the leading (. If request bodies can contain arrays of file/binary, the workaround will miss them and keep contentKind as JSON. Consider allowing optional parentheses around the matched type (e.g., match :\s*\(?${type}\)? before handling []/unions), or add a dedicated branch to handle the (...)[] form.

Suggested change
// Match e.g. ": File" followed by word boundary, array brackets, or union/nullable syntax
// This prevents false positives like ": FileType" or ": SomeFile"
// Escape special regex characters (getSchemaType can theoretically return complex types like "File | null" or "UtilRequiredKeys<File, ...>")
const escapedType = dataType.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
return new RegExp(`:\\s*${escapedType}(?:\\[\\]|\\s*\\||\\b|$)`).test(
content,
);
// Match e.g. ": File" or ": (File)" (optionally with unions like "(File | null)")
// followed by word boundary, array brackets, or union/nullable syntax.
// This prevents false positives like ": FileType" or ": SomeFile".
// Escape special regex characters (getSchemaType can theoretically return complex types like "File | null" or "UtilRequiredKeys<File, ...>")
const escapedType = dataType.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
// Allow either a bare type or a parenthesized form that may contain unions, e.g. "(File | null)".
const pattern = `:\\s*(?:\\(\\s*${escapedType}(?:\\s*\\|[^)]*)?\\)|${escapedType})(?:\\[\\]|\\s*\\||\\b|$)`;
return new RegExp(pattern).test(content);

Copilot uses AI. Check for mistakes.
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.

Custom type named FileXyz triggers content type workaround

3 participants