From fb13e3834f5ff050aa8ec75d64a79c4991e82480 Mon Sep 17 00:00:00 2001 From: DanMat Date: Mon, 7 Sep 2026 17:18:41 -0400 Subject: [PATCH] Send a User-Agent from the HTTP client (fixes Dev.to edge 403) PHP's curl sends no User-Agent by default, and Dev.to's edge (Varnish) answers a no-UA request with an empty-bodied HTTP 403 before it reaches the Forem API. That, not the post body, was failing every syndication: proven server-side, the same GET returns 403 with no UA and 200 with any UA. CurlHttpClient now sends a descriptive User-Agent (overridable), which also benefits Hashnode. Co-Authored-By: Claude Opus 4.8 --- src/CurlHttpClient.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/CurlHttpClient.php b/src/CurlHttpClient.php index e910f27..9d70597 100644 --- a/src/CurlHttpClient.php +++ b/src/CurlHttpClient.php @@ -11,8 +11,10 @@ */ final class CurlHttpClient implements HttpClient { - public function __construct(private int $timeoutSeconds = 15) - { + public function __construct( + private int $timeoutSeconds = 15, + private string $userAgent = 'NimbusCMS-Blog/1.0 (+https://nimbuscms.dev)', + ) { } public function send(string $method, string $url, array $headers, ?string $body): array @@ -31,6 +33,10 @@ public function send(string $method, string $url, array $headers, ?string $body) CURLOPT_HTTPHEADER => $headerLines, CURLOPT_TIMEOUT => $this->timeoutSeconds, CURLOPT_CONNECTTIMEOUT => $this->timeoutSeconds, + // A User-Agent is required: PHP's curl sends none by default, and some + // platform edges (e.g. Dev.to's Varnish) answer a no-UA request with an + // empty-bodied 403 before it ever reaches the API. + CURLOPT_USERAGENT => $this->userAgent, ]); if ($body !== null) { curl_setopt($ch, CURLOPT_POSTFIELDS, $body);