Skip to content

feat(infer): resolve known content types via mimetype instead of no-op#61

Merged
nao1215 merged 1 commit into
mainfrom
fix/issue-59-infer-builtin-mimetype
May 31, 2026
Merged

feat(infer): resolve known content types via mimetype instead of no-op#61
nao1215 merged 1 commit into
mainfrom
fix/issue-59-infer-builtin-mimetype

Conversation

@nao1215

@nao1215 nao1215 commented May 31, 2026

Copy link
Copy Markdown
Owner

Summary

multipartkit/infer.content_type_from_filename and content_type_from_bytes were default no-ops that returned None for every input, including well-known types ("a.png", the PNG magic header, etc.). This made the public infer helpers surprising: a caller asking for the content type of photo.png got None. Issue #59 asks for real inference; the chosen resolution (option 1) is to delegate to the sibling nao1215/mimetype package, which already maintains the IANA + magic-byte tables.

This reverses the v0.13.0 (#52) decision to ship these helpers as documented no-ops. That decision was pinned by test/regression_infer_default_test.gleam; this PR rewrites that file to assert the new contract.

Changes

content_type_from_filename and content_type_from_bytes now delegate to mimetype.filename_to_mime_type_strict / mimetype.detect_strict, returning Some(mimetype.essence_of(_)) for recognised input and None otherwise (option.from_result |> option.map(essence_of)). nao1215/mimetype is added as a runtime dependency (>= 0.24.0 and < 1.0.0).

Inference into the form builder stays opt-in. infer.default_inferer() is intentionally kept a no-op, so add_file_auto still falls through to application/octet-stream and never changes a content type implicitly. A new infer.builtin_inferer() wires the two helpers into an Inferer, so callers can opt in with form.add_file_auto_with(form, ..., infer.builtin_inferer()) without writing the mimetype wiring themselves.

test/regression_infer_default_test.gleam is rewritten to assert: the #59 DoD (known extensions and magic-byte signatures resolve to the expected MIME strings; unknown / empty input is None), that default_inferer() is still a no-op, and that builtin_inferer() resolves.

Docstrings, the README feature bullet, and the CHANGELOG are updated.

Design Decisions

Option 1 (delegate to mimetype) was chosen over option 2 (inline a built-in table) because an inline table would duplicate, and inevitably drift from, the table that the sibling mimetype package already maintains — the very duplication the infer docstrings already steered callers away from. Delegating gives full IANA + magic-byte coverage with no duplicate maintenance.

default_inferer() is deliberately left a no-op rather than wired to mimetype, so add_file_auto's behaviour is unchanged and inference remains an explicit opt-in (builtin_inferer() or a custom Inferer). This keeps the form builder from silently changing content types when the dependency resolves an extension.

Notes

This PR also restores the ## [0.13.0] - 2026-05-20 CHANGELOG header, which was accidentally dropped in #60 — without it, the released 0.13.0 entries (#52, #51, #50) were sitting under [Unreleased].

mimetype.detect_strict classifies arbitrary printable-ASCII input as text/plain; this is reachable only through the direct helper / builtin_inferer (never through add_file_auto), and is documented on content_type_from_bytes.

Closes #59

@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@nao1215, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 20 minutes and 20 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9ccf476f-5ec5-4220-9fb8-7f63a8ceff5d

📥 Commits

Reviewing files that changed from the base of the PR and between b18c0ed and b5d4e0b.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • README.md
  • gleam.toml
  • manifest.toml
  • src/multipartkit/form.gleam
  • src/multipartkit/infer.gleam
  • test/regression_infer_default_test.gleam
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-59-infer-builtin-mimetype

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 and usage tips.

@nao1215 nao1215 merged commit 866d07f into main May 31, 2026
5 checks passed
@nao1215 nao1215 deleted the fix/issue-59-infer-builtin-mimetype branch May 31, 2026 08:30
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.

REGRESSION: infer.content_type_from_filename / from_bytes still return None for known PNG / JSON / PDF / GIF (closes #52 not effective)

1 participant