From e387c91b4cab7b30dd04850dcb3eb1cb9293bc22 Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Fri, 22 May 2026 22:15:37 +0200 Subject: [PATCH] =?UTF-8?q?fix(http=5Frequest):=20drop=20"2>&1"=20on=20Win?= =?UTF-8?q?dows=20=E2=80=94=20CreateProcessW=20has=20no=20shell?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit POSIX popen routes via /bin/sh -c, so "2>&1" is a shell redirect. On Windows we use CreateProcessW directly (no shell): curl receives "2>&1" as a positional arg, treats it as a second URL, and fails with exit 3 "URL rejected: Bad hostname". Stderr is already merged into the same pipe via STARTUPINFOW.hStdError on Windows, so the redirect is also unnecessary there. Guard with #ifndef _WIN32. Also adds FN_HTTP_DEBUG env var to dump the cmdline + req.url for future bug triage (zero-cost when unset). Detected via agents_dashboard.exe --connect-test against https://agents.organic-machine.com — same .exe with the fix now returns "OK 11" in <2s. Co-Authored-By: Claude Opus 4.7 (1M context) --- cpp/functions/core/http_request.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/cpp/functions/core/http_request.cpp b/cpp/functions/core/http_request.cpp index bb196165..4f481a03 100644 --- a/cpp/functions/core/http_request.cpp +++ b/cpp/functions/core/http_request.cpp @@ -269,8 +269,21 @@ Response request(const Request& req) { } cmd << ' ' << sh_q(req.url) - << " -o " << sh_q(tmp_body_out) - << " 2>&1"; + << " -o " << sh_q(tmp_body_out); + + // On POSIX we go through /bin/sh -c via popen, so `2>&1` is a shell redirect. + // On Windows we use CreateProcessW (no shell): `2>&1` would be passed as an + // extra positional arg to curl, which treats it as a second URL → "Bad + // hostname" (exit 3). stderr is already merged via STARTUPINFOW.hStdError. +#ifndef _WIN32 + cmd << " 2>&1"; +#endif + + if (std::getenv("FN_HTTP_DEBUG")) { + fprintf(stderr, "[fn_http debug] cmdline: %s\n", cmd.str().c_str()); + fprintf(stderr, "[fn_http debug] req.url=[%s] len=%zu\n", + req.url.c_str(), req.url.size()); + } // Capture stderr (curl prints transport errors to stderr with -sS). std::string curl_stderr;