Skip to content

fix!: validate HTTP message statusCode and store it as int - #52

Merged
VisualBean merged 3 commits into
ByteBardOrg:vnextfrom
bielu:fix/http-status-code-diagnostics
Oct 17, 2026
Merged

VisualBean merged 3 commits into
ByteBardOrg:vnextfrom
bielu:fix/http-status-code-diagnostics

Conversation

@bielu

@bielu bielu commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Problem

HttpMessageBinding parsed statusCode like this:

if (int.TryParse(n.GetScalarValue(), out var code))
{
    a.StatusCode = (HttpStatusCode)code;
}

That caused three problems:

  1. A value that isn't an integer was silently ignored. statusCode: not-found reads with no errors, StatusCode stays null, and the field is gone when the document is written back. It's the same silent drop fix: report invalid MQTT and ROS2 binding scalars as errors #48 fixed for the MQTT and ROS2 fields.
  2. Out-of-range values were accepted with no warning. RFC 9110 §15 defines status codes as three-digit integers from 100 to 599, but statusCode: 42, 0 or 600 read without any diagnostic.
  3. System.Net.HttpStatusCode doesn't cover real-world codes. It defines only 61 of the 500 codes in 100–599. Missing ones include 425 Too Early (RFC 8470, IANA-registered), nginx 499, Cloudflare 520–530 and 599. Thanks to the enum cast they still round-tripped, but they couldn't be named, ToString() printed a bare number, and Enum.IsDefined returned false, so the type implied they were invalid.

Change

  • statusCode is parsed with n.GetIntegerValue(), so a non-integer value records Value could not parse to integer. in diagnostic.Errors.
  • A value outside 100–599 records statusCode <n> is not a valid HTTP status code. It must be between 100 and 599., with a pointer to the field. The value is still kept on the binding, so the document can be written back unchanged.
  • ⚠️ Breaking: HttpMessageBinding.StatusCode is now int? instead of HttpStatusCode?, as agreed in review. To migrate, cast when assigning from the enum, e.g. StatusCode = (int)HttpStatusCode.OK. The YAML/JSON output is unchanged, since it was already written as a number.

The range check lives in the binding parser rather than in a validation rule. The validation rules are in the core ByteBard.AsyncAPI assembly, which can't reference ByteBard.AsyncAPI.Bindings.

Tests

In HttpBindings_Should:

  • V3_HttpMessageBinding_ReadsStatusCode: a valid 404 reads as 404.
  • V3_HttpMessageBinding_WithInvalidStatusCode_ReportsError (not-found, 200.5).
  • V3_HttpMessageBinding_WithValidStatusCode_ReportsNoErrorAndRoundTrips (100, 599, plus 425, 499 and 520, none of which are HttpStatusCode members): no error, and each is written back.
  • V3_HttpMessageBinding_WithOutOfRangeStatusCode_ReportsErrorAndKeepsValue (0, 42, 99, 600, -200): checks the error and its pointer, that the value is kept, and that it is written back.
  • The existing serialization tests now assign StatusCode = 200.

The full suite (331 tests) passes on net8.0/net9.0/net10.0.

🤖 Generated with Claude Code

HttpMessageBinding parsed `statusCode` with int.TryParse and ignored the
value when parsing failed, so e.g. `statusCode: not-found` was read with
no diagnostics and dropped on write. It now uses GetIntegerValue(), which
records "Value could not parse to integer." like the other bindings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 28 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 35c1b83c-5d03-4b5e-98cf-620bab4b5e54
📥 Commits

Reviewing files that changed from the base of the PR and between a13c612 and a27d822.

📒 Files selected for processing: 2
  • src/ByteBard.AsyncAPI.Bindings/Http/HttpMessageBinding.cs
  • test/ByteBard.AsyncAPI.Tests/Bindings/Http/HttpBindings_Should.cs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@bielu
bielu marked this pull request as ready for review October 17, 2026 17:47
@bielu
bielu requested a review from VisualBean as a code owner October 17, 2026 17:47
@VisualBean

VisualBean commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

HttpStatusCode doesn't contain all status codes, unfortunately.
I wonder if we should change the enum or if its fine as is (since we are changing this anyway).

I agree on the potential validation

RFC 9110 defines status codes as three-digit integers from 100 to 599.
Values outside that range (e.g. `statusCode: 42`) were accepted without
any diagnostic. They are now reported in diagnostic.Errors with a
pointer to the field. The value is still kept on the binding so the
document can be written back unchanged.

The check lives in the binding parser because the core validation rules
cannot reference the bindings assembly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bielu bielu changed the title fix: report invalid HTTP message statusCode as an error fix: report invalid or out-of-range HTTP message statusCode as an error Oct 17, 2026
@bielu

bielu commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

Good point. I checked: HttpStatusCode only defines 61 of the 500 codes in 100–599 (no 418, 425, 499, 520–530, 599…). It doesn't lose data though: the enum is an int underneath, so (HttpStatusCode)418 reads fine and we write (int)StatusCode, so it round-trips as statusCode: 418. The tests in this PR already round-trip values the enum doesn't define (599, 42). The downside is only on the API side (ToString() gives "418", Enum.IsDefined is false, and a switch can't name them).

I'd keep this PR as the parsing/range fix and switch StatusCode to int? in a follow-up, since that changes the public API. Happy to fold it in here instead if you'd rather take the break now while 3.1 is still beta. Your call.

@VisualBean

Copy link
Copy Markdown
Contributor

Good point. I checked: HttpStatusCode only defines 61 of the 500 codes in 100–599 (no 418, 425, 499, 520–530, 599…). It doesn't lose data though: the enum is an int underneath, so (HttpStatusCode)418 reads fine and we write (int)StatusCode, so it round-trips as statusCode: 418. The tests in this PR already round-trip values the enum doesn't define (599, 42). The downside is only on the API side (ToString() gives "418", Enum.IsDefined is false, and a switch can't name them).

I'd keep this PR as the parsing/range fix and switch StatusCode to int? in a follow-up, since that changes the public API. Happy to fold it in here instead if you'd rather take the break now while 3.1 is still beta. Your call.

I think int would be better or one of the newer status code types (i forget the name). This lib has always been about type correctness, so the enum feels like a miss on my behalf.
I am good with doing it in a followup though, but I'll leave that up to you. Id prefer the break in 3.1 👍

System.Net.HttpStatusCode only defines 61 of the 500 codes in 100-599.
Codes such as 425 Too Early (RFC 8470), nginx 499 or Cloudflare 520
round-tripped through the enum cast, but could not be named, printed as
bare numbers and failed Enum.IsDefined, so the type implied they were
invalid. StatusCode is now a plain int?, validated by the 100-599 range
check.

BREAKING CHANGE: `HttpMessageBinding.StatusCode` is now `int?` instead of
`HttpStatusCode?`. Cast when assigning from the enum, e.g.
`StatusCode = (int)HttpStatusCode.OK`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bielu bielu changed the title fix: report invalid or out-of-range HTTP message statusCode as an error fix!: validate HTTP message statusCode and store it as int Oct 17, 2026
@bielu

bielu commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

@VisualBean done :)

@VisualBean
VisualBean merged commit 70e73db into ByteBardOrg:vnext Oct 17, 2026
8 checks passed
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