Skip to content

refactor: use JSON post instead of form-encoded payload#20

Closed
Koan-Bot wants to merge 2 commits into
masterfrom
koan.atoomic/refactor-json-post
Closed

refactor: use JSON post instead of form-encoded payload#20
Koan-Bot wants to merge 2 commits into
masterfrom
koan.atoomic/refactor-json-post

Conversation

@Koan-Bot

@Koan-Bot Koan-Bot commented Mar 28, 2026

Copy link
Copy Markdown
Collaborator

What

Switch _http_post() from post_form() with a payload parameter to post() with a JSON body.

Why

The Content-Type: application/json header set in _build__http was dead code — post_form() always overrides it with application/x-www-form-urlencoded. This confused readers (cf. PR #14). Rather than removing the header, this makes it actually effective.

How

  • _http_post: post_form($url, { payload => $json })post($url, { content => $json })
  • Tests: mock post instead of post_form, extract from content instead of payload
  • POD: updated return value reference from post_form to post

Both formats are accepted by Slack webhooks — no functional change on the API side.

Testing

All 48 tests pass locally. The mock captures HTTP::Tiny::post calls and verifies JSON payloads round-trip correctly, including UTF-8 attachment encoding.

🤖 Generated with Claude Code

Supersedes the rationale of #14 (dead Content-Type removal) — the header is now useful.


Quality Report

Changes: 2 files changed, 13 insertions(+), 13 deletions(-)

Code scan: clean

Tests: passed (OK)

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

Switch _http_post() from HTTP::Tiny::post_form() with a `payload`
parameter to HTTP::Tiny::post() with a JSON body. Slack webhooks
accept both formats, but the JSON approach is cleaner:

- The Content-Type header in _build__http is no longer dead code
  (post_form always overrode it with application/x-www-form-urlencoded)
- Removes the unnecessary form-encoding layer around the JSON payload
- Aligns with Slack's recommended JSON content-type approach

No functional change — both formats produce identical results on
the Slack API side.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@atoomic atoomic marked this pull request as ready for review March 28, 2026 12:52

@atoomic atoomic left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

LGTM would like some real testing before merging

post() sends content as-is to the socket, unlike post_form() which
handles encoding internally. When json->utf8(0) produces a Unicode
string with wide characters (e.g. UTF-8 text), HTTP::Tiny fails with
a 599 Internal Exception.

Add utf8::encode() to ensure the JSON payload is bytes before posting.
Update test JSON decoding to use utf8(1) to match the new byte format.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Koan-Bot

Koan-Bot commented Apr 9, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the "real testing" feedback — pushed two changes:

Bug fix: json->utf8(0) produces Unicode strings, but HTTP::Tiny->post() needs bytes (unlike post_form() which handles encoding internally). Without this fix, UTF-8 content triggers a 599 Internal Exception. Added utf8::encode() before posting.

Integration test (t/http-format.t): Spins up a local HTTP server to capture the actual request. Validates:

  • Content-Type is application/json (was dead code with post_form)
  • Body is valid JSON (not form-encoded)
  • UTF-8 content survives the round trip

52 tests pass (48 existing + 4 new integration tests).

@Koan-Bot

Copy link
Copy Markdown
Collaborator Author

Re: real testing before merge —

This PR includes t/http-format.t, an integration test that spins up a local IO::Socket::INET server and validates actual HTTP requests (no mocks). It covers:

  • Content-Type: verifies application/json header (the whole point of this refactor)
  • JSON body: decodes the raw body and checks structure
  • All post types: post(), post_ok(), post_error() with their expected payloads
  • UTF-8: validates that Unicode content survives the JSON encode → HTTP transmit round-trip

For manual smoke testing against a real Slack workspace, something like:

use Slack::WebHook;
my $h = Slack::WebHook->new(url => $ENV{SLACK_WEBHOOK_URL});
$h->post_ok("JSON post test — café ☃");
$h->post_error("Error format test");

The CI tests pass on all Perl versions (5.14–5.42).

@Koan-Bot

Copy link
Copy Markdown
Collaborator Author

Superseded by #28 which consolidates PRs #18, #19, and #20 into a single reviewable PR (resolving inter-branch conflicts).

@Koan-Bot Koan-Bot closed this Apr 23, 2026
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