Skip to content

Use with_body instead of with_body_text_plain for JSON responses#529

Open
ChristianPavilonis wants to merge 2 commits intomainfrom
fix/json-content-type
Open

Use with_body instead of with_body_text_plain for JSON responses#529
ChristianPavilonis wants to merge 2 commits intomainfrom
fix/json-content-type

Conversation

@ChristianPavilonis
Copy link
Collaborator

@ChristianPavilonis ChristianPavilonis commented Mar 19, 2026

Summary

  • Fix JSON API responses returning Content-Type: text/plain instead of application/json
  • with_body_text_plain() silently overrides the Content-Type header set by with_content_type(APPLICATION_JSON) on the preceding line, breaking automated clients that check Content-Type before parsing
  • Replace with with_body() which sets the body without clobbering headers

Changes

File Change
crates/common/src/request_signing/endpoints.rs Replace with_body_text_plain()with_body() across all 6 response sites (discovery, verify signature, rotate key success/error, deactivate key success/error)

Closes

Closes #424

Test plan

  • cargo test --workspace
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo fmt --all -- --check
  • JS tests: cd crates/js/lib && npx vitest run
  • JS format: cd crates/js/lib && npm run format
  • Docs format: cd docs && npm run format
  • WASM build: cargo build --bin trusted-server-fastly --release --target wasm32-wasip1
  • Manual testing via fastly compute serve

Checklist

  • Changes follow CLAUDE.md conventions
  • No unwrap() in production code — use expect("should ...")
  • Uses tracing macros (not println!)
  • New code has tests
  • No secrets or credentials committed

@ChristianPavilonis ChristianPavilonis marked this pull request as ready for review March 19, 2026 20:59
@aram356 aram356 assigned aram356 and ChristianPavilonis and unassigned aram356 Mar 20, 2026
Copy link
Collaborator

@prk-Jr prk-Jr left a comment

Choose a reason for hiding this comment

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

👍 Looks good

Copy link
Collaborator

@aram356 aram356 left a comment

Choose a reason for hiding this comment

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

@ChristianPavilonis Please resolve conflicts

The with_body_text_plain method sets Content-Type to text/plain,
overriding the APPLICATION_JSON type set by with_content_type.
Replace all 6 occurrences in request signing endpoints with
with_body which preserves the previously set Content-Type.

Closes #424
Copy link
Collaborator

@aram356 aram356 left a comment

Choose a reason for hiding this comment

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

Summary

Clean fix for with_body_text_plain() clobbering the Content-Type: application/json header at all 6 JSON response sites. The switch to with_body() is correct. However, the bug remains undetectable by the test suite — a regression test for the Content-Type header is needed.

Blocking

🔧 wrench

  • Missing Content-Type assertion in tests: None of the existing tests check the Content-Type header on responses. The bug this PR fixes could silently regress. At least one test should assert resp.get_content_type() == Some(APPLICATION_JSON). (crates/trusted-server-core/src/request_signing/endpoints.rs)

Non-blocking

⛏ nitpick

  • PR checklist template mentions "tracing macros": The checklist says "Uses tracing macros (not println!)" but the project convention is log macros per CLAUDE.md. Template issue only — the actual code correctly uses log::debug!.

🌱 seedling

  • Consider a helper for JSON responses: There are 6 nearly-identical response construction patterns in this file. A small helper like fn json_response(status: u16, body: &str) -> Response would eliminate this class of bug entirely. Not for this PR, but worth considering.

CI Status

  • fmt: PASS
  • clippy: PASS
  • rust tests: PASS
  • js tests: PASS
  • integration tests: PASS
  • browser integration tests: PASS
  • CodeQL: PASS

Ok(Response::from_status(200)
.with_content_type(fastly::mime::APPLICATION_JSON)
.with_body_text_plain(&json))
.with_body(json))
Copy link
Collaborator

Choose a reason for hiding this comment

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

🔧 wrench — No test asserts the Content-Type header.

This exact bug existed because none of the existing tests check Content-Type on responses — they only parse the body. After this fix, the bug is still undetectable by the test suite and could silently regress.

At minimum, one test (e.g., test_handle_verify_signature_valid or test_handle_trusted_server_discovery) should assert:

assert_eq!(
    resp.get_content_type(),
    Some(fastly::mime::APPLICATION_JSON),
    "should return application/json content type"
);

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.

with_body_text_plain may override APPLICATION_JSON Content-Type

3 participants