Skip to content

Do not send a response body for 204/304, per RFC 9110 - #155

Open
bcordis wants to merge 1 commit into
joomla-framework:4.x-devfrom
bcordis:fix-204-304-body-4x
Open

bcordis wants to merge 1 commit into
joomla-framework:4.x-devfrom
bcordis:fix-204-304-body-4x

Conversation

@bcordis

@bcordis bcordis commented Oct 2, 2026 •

Copy link
Copy Markdown

Summary

respond() unconditionally echoes the response body regardless of status code. Per RFC 9110 §15.3.5 (204 No Content) and §15.4.5 (304 Not Modified), neither response may include a message body.

Also skips the Content-Type header specifically for 204, since a 204 has no representation to describe. 304 deliberately keeps it -- per §15.4.5 a 304 is expected to carry the same representation metadata headers the 200 it validates would have sent; only the body is withheld.

Found via

A real Joomla CMS API DELETE: PHP's built-in dev server plus a strict HTTP/1.1 client (Playwright's Node HTTP client) fails to parse the response at all (Parse Error: Data after \Connection: close``), because the 204 carries a non-empty JSON:API body. Apache is more lenient about the extra bytes, which is likely why this has gone unnoticed in practice.

Reported at joomla/joomla-cms#48553, traced to this package per @brianteeman's comment there.

Testing

Two new tests added, mirroring the existing testRespond()/testRespondWithAllowedCaching() pattern: one asserting no body and no Content-Type for 204, one asserting no body but Content-Type preserved for 304. Full existing suite still passes.

Companion PR

Same fix on 3.x-dev, since Joomla 5 still pins joomla/application ^3.0: #156

respond() unconditionally echoed the response body regardless of
status code. Per RFC 9110 §15.3.5 (204 No Content) and §15.4.5 (304
Not Modified), neither response may include a message body.

Confirmed via a real Joomla CMS API DELETE: PHP's built-in dev server
plus a strict HTTP/1.1 client (Playwright's Node HTTP client) fails to
parse the response at all ("Parse Error: Data after `Connection:
close`"), because a 204 is carrying a non-empty JSON:API body. Apache
is more lenient about the extra bytes, which is likely why this has
gone unnoticed.

Also skips the Content-Type header specifically for 204, since a 204
has no representation to describe. 304 keeps it deliberately -- per
RFC 9110 §15.4.5 a 304 is expected to carry the same representation
metadata headers the 200 it validates would have sent; only the body
is withheld.

Reported at joomla/joomla-cms#48553, traced
upstream to this package per @brianteeman's comment there.
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.

1 participant