mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
fix(fetch): print request body for application/x-www-form-urlencoded in curl logs (#22849)
### What does this PR do? fixes an issue where fetch requests with `Content-Type: application/x-www-form-urlencoded` would not include the request body in curl logs when `BUN_CONFIG_VERBOSE_FETCH=curl` is enabled previously, only JSON and text-based content types were recognized as safe-to-print in the curl formatter. This change updates the allow-list to also handle `application/x-www-form-urlencoded`, ensuring bodies for common form submissions are shown in logs ### How did you verify your code works? - added `Content-Type: application/x-www-form-urlencoded` to a fetch request and confirmed that `BUN_CONFIG_VERBOSE_FETCH=curl` now outputs a `--data-raw` section with the encoded body - verified the fix against the reproduction script provided in issue #12042 - created and ran a regression test - checked that existing content types (JSON, text, etc.) continue to print correctly fixes #12042
This commit is contained in:
@@ -97,6 +97,15 @@ pub const Request = struct {
|
||||
ignore_insecure: bool = false,
|
||||
body: []const u8 = "",
|
||||
|
||||
fn isPrintableBody(content_type: []const u8) bool {
|
||||
if (content_type.len == 0) return false;
|
||||
|
||||
return bun.strings.hasPrefixComptime(content_type, "text/") or
|
||||
bun.strings.hasPrefixComptime(content_type, "application/json") or
|
||||
bun.strings.containsComptime(content_type, "json") or
|
||||
bun.strings.hasPrefixComptime(content_type, "application/x-www-form-urlencoded");
|
||||
}
|
||||
|
||||
pub fn format(self: @This(), comptime _: []const u8, _: fmt.FormatOptions, writer: anytype) !void {
|
||||
const request = self.request;
|
||||
if (Output.enable_ansi_colors_stderr) {
|
||||
@@ -132,7 +141,7 @@ pub const Request = struct {
|
||||
}
|
||||
}
|
||||
|
||||
if (self.body.len > 0 and (content_type.len > 0 and bun.strings.hasPrefixComptime(content_type, "application/json") or bun.strings.hasPrefixComptime(content_type, "text/") or bun.strings.containsComptime(content_type, "json"))) {
|
||||
if (self.body.len > 0 and isPrintableBody(content_type)) {
|
||||
_ = try writer.writeAll(" --data-raw ");
|
||||
try bun.js_printer.writeJSONString(self.body, @TypeOf(writer), writer, .utf8);
|
||||
}
|
||||
|
||||
47
test/regression/issue/12042.test.ts
Normal file
47
test/regression/issue/12042.test.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { bunEnv, bunExe, normalizeBunSnapshot, tempDir } from "harness";
|
||||
|
||||
test("#12042 curl verbose fetch logs form-urlencoded body", async () => {
|
||||
using dir = tempDir("issue-12042", {
|
||||
"form.ts": `
|
||||
const server = Bun.serve({
|
||||
port: 0,
|
||||
fetch() {
|
||||
return new Response(JSON.stringify({ ok: true }), {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.set("grant_type", "client_credentials");
|
||||
params.set("client_id", "abc");
|
||||
params.set("client_secret", "xyz");
|
||||
|
||||
await fetch(String(server.url), {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: params,
|
||||
});
|
||||
|
||||
await server.stop();
|
||||
`,
|
||||
});
|
||||
|
||||
const dirPath = String(dir);
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "form.ts"],
|
||||
env: { ...bunEnv, BUN_CONFIG_VERBOSE_FETCH: "curl" },
|
||||
cwd: dirPath,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr] = await Promise.all([proc.stdout.text(), proc.stderr.text()]);
|
||||
|
||||
const output = stdout + stderr;
|
||||
const normalized = normalizeBunSnapshot(output, dirPath);
|
||||
|
||||
expect(normalized).toContain('--data-raw "grant_type=client_credentials&client_id=abc&client_secret=xyz');
|
||||
});
|
||||
Reference in New Issue
Block a user