Skip to content

Accept HTTP::Request and HTTP::Response in validate - #5

Merged
plicease merged 1 commit into
mainfrom
graham/http-message
Oct 15, 2026
Merged

plicease merged 1 commit into
mainfrom
graham/http-message

Conversation

@plicease

Copy link
Copy Markdown
Member

Closes #3.

validate now accepts HTTP::Request and HTTP::Response as the named request and response:

$humbug->validate(request => $http_request);
$humbug->validate(request => $http_request, response => $http_response);
$humbug->validate(response => $http_response);   # uses $http_response->request

The conversion lives in OpenAPI::Humbug::Adapter::HTTPMessage, documented as internal. It turns the objects into the existing request/response hashes, which then go through the usual argument checks and encoding. The sidecar, wire protocol and transport are unchanged, and there's no adapter registry.

Behaviour (documented under HTTP::MESSAGE in the POD)

  • Which request:

    • With response => $http_response and no request, the response's own request ($http_response->request) is used, even with validate => { request => 0, response => 1 }, because the sidecar needs it to find the operation.
    • A response with no associated request is an argument error.
    • An explicit request (object or hash) always wins, even when it differs.
    • A response hash on its own is still an error.
  • No positional form: validate($http_response) is an argument error that says to pass it as response =>.

  • Optional: HTTP::Message is never loaded by this module, and the adapter is loaded only when one of these objects is passed. In META.json it is a runtime suggests and a test recommends. A test hides HTTP::Message and checks that hashref callers work and nothing related gets loaded.

  • Read-only: objects are never changed. HTTP::Message's headers, header and content would generate the body (and rewrite Content-Type) for a message built with parts/add_part. Such a message is rejected before any of those are called, and the test checks it is left unchanged. The tests also compare Data::Dumper snapshots of the request and response before and after.

  • URL: the request's URI without fragment or credentials (cleared explicitly). It must be absolute with a scheme and host. HTTP::Request has no base URL and Host gives no scheme, so a relative URI is an argument error, not a guess.

  • Headers: every line is sent, and repeated lines (Set-Cookie) stay separate and in order. What HTTP::Headers loses is documented, not reconstructed:

    • the order between different names (it uses its own grouping, then alphabetical);
    • the original casing of names.

    Folded values are unfolded to a space (RFC 9112 §5.2); otherwise the sidecar would reject the raw line break. Values that are objects (e.g. URI) are stringified.

  • Body: raw content, never decoded_content. Content from a code reference, or held as parts, is an argument error.

  • Absent vs empty: the same RFC 9112 §6.3 rules as the Mojo adapter.

    • Request: has a body if it has content, Content-Length or Transfer-Encoding.
    • Response: no body for HEAD (when the request is known), 1xx, 204 or 304; any other response has one, possibly empty.

Tests

  • t/openapi_humbug__http_message.t: in-memory against the fake transport, checking the exact wire form. Covers request-only, request plus response, response with its associated request, response without one, positional response rejected, explicit request winning, response-only checks keeping the request, repeated Set-Cookie, binary/non-ASCII/empty header values, folded values, raw/binary/empty/absent bodies, absolute/relative URIs and missing scheme/host, messages that can't be converted, and objects left unchanged.
  • t/openapi_humbug__no_http_message.t: hashref callers with HTTP::Message hidden.
  • t/integration.t: request, response with its request, and response-only checks against the real humbug.

CI

maint/cip-before-install now also installs HTTP::Message, so these tests run in the linux workflow.

🤖 Generated with Claude Code

validate now takes an HTTP::Request and/or HTTP::Response as the named
request and response. A response given without a request brings its own
($response->request), which is used even when only the response is
checked; an explicit request always wins. The private
OpenAPI::Humbug::Adapter::HTTPMessage converts them to the existing
hashes; it is loaded only when one of those objects is passed, and
HTTP::Message stays optional (suggested). The objects are only read,
never changed.

Closes #3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@plicease
plicease merged commit 83e5e35 into main Oct 15, 2026
4 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.

Support HTTP::Request and HTTP::Response in validate()

1 participant