From 1cb99194eb20a0bcff458e41581c8055a5fa39df Mon Sep 17 00:00:00 2001 From: sohan Date: Sat, 21 Feb 2026 17:14:51 +0600 Subject: [PATCH] http: warn when http.get/head receive extra arguments Display a warning when http.get() or http.head() are called with more than the expected (url, params) arguments. Users commonly pass a body argument (e.g. http.get(url, body, params)) not realizing that GET and HEAD do not support request bodies. The extra arguments are silently ignored, which can lead to confusing behavior. Fixes #2823 Co-Authored-By: Claude Opus 4.6 --- js/modules/k6/http/http.go | 30 +++++++++-- js/modules/k6/http/request_test.go | 81 ++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 4 deletions(-) diff --git a/js/modules/k6/http/http.go b/js/modules/k6/http/http.go index 5fcfc2ae1e..ae72a97202 100644 --- a/js/modules/k6/http/http.go +++ b/js/modules/k6/http/http.go @@ -69,14 +69,36 @@ func (r *RootModule) NewModuleInstance(vu modules.VU) modules.Instance { // wrappers (facades) that convert the old k6 idiosyncratic APIs to the new // proper Client ones that accept Request objects and don't suck mustExport("get", func(url sobek.Value, args ...sobek.Value) (*Response, error) { - // http.get(url, params) doesn't have a body argument, so we add undefined - // as the third argument to http.request(method, url, body, params) + // http.get(url, params) only accepts a URL and an optional params argument. + // It does not accept a body argument like http.post or http.put. + // Warn the user if they pass more arguments than expected, as they likely + // intended to pass a body (e.g. http.get(url, body, params)), which is + // not supported by HTTP GET. + if len(args) > 1 { + state := mi.vu.State() + if state != nil { + state.Logger.Warnf( + "http.get only accepts a url and an optional params argument. %.0f extra argument(s) will be ignored.", + float64(len(args)-1), + ) + } + } args = append([]sobek.Value{sobek.Undefined()}, args...) return mi.defaultClient.Request(http.MethodGet, url, args...) }) mustExport("head", func(url sobek.Value, args ...sobek.Value) (*Response, error) { - // http.head(url, params) doesn't have a body argument, so we add undefined - // as the third argument to http.request(method, url, body, params) + // http.head(url, params) only accepts a URL and an optional params argument. + // It does not accept a body argument like http.post or http.put. + // Warn the user if they pass more arguments than expected. + if len(args) > 1 { + state := mi.vu.State() + if state != nil { + state.Logger.Warnf( + "http.head only accepts a url and an optional params argument. %.0f extra argument(s) will be ignored.", + float64(len(args)-1), + ) + } + } args = append([]sobek.Value{sobek.Undefined()}, args...) return mi.defaultClient.Request(http.MethodHead, url, args...) }) diff --git a/js/modules/k6/http/request_test.go b/js/modules/k6/http/request_test.go index db99ace1be..315284facc 100644 --- a/js/modules/k6/http/request_test.go +++ b/js/modules/k6/http/request_test.go @@ -2401,3 +2401,84 @@ func TestGzipped204Response(t *testing.T) { `)) assert.NoError(t, err) } + +func TestExtraArgsWarning(t *testing.T) { + t.Parallel() + ts := newTestCase(t) + tb := ts.tb + rt := ts.runtime.VU.Runtime() + + sr := tb.Replacer.Replace + + t.Run("http.get", func(t *testing.T) { + t.Run("no warning with 0 args", func(t *testing.T) { + ts.hook.Drain() // clear previous log entries + _, err := rt.RunString(sr(`http.get("HTTPBIN_URL/get");`)) + require.NoError(t, err) + entries := testutils.FilterEntries(ts.hook.Drain(), logrus.WarnLevel, "http.get only accepts") + assert.Empty(t, entries) + }) + + t.Run("no warning with 1 arg", func(t *testing.T) { + ts.hook.Drain() + _, err := rt.RunString(sr(`http.get("HTTPBIN_URL/get", null);`)) + require.NoError(t, err) + entries := testutils.FilterEntries(ts.hook.Drain(), logrus.WarnLevel, "http.get only accepts") + assert.Empty(t, entries) + }) + + t.Run("warning with 2 args", func(t *testing.T) { + ts.hook.Drain() + _, err := rt.RunString(sr(`http.get("HTTPBIN_URL/get", null, null);`)) + require.NoError(t, err) + entries := testutils.FilterEntries(ts.hook.Drain(), logrus.WarnLevel, "http.get only accepts") + require.Len(t, entries, 1) + assert.Contains(t, entries[0].Message, "1 extra argument(s) will be ignored") + }) + + t.Run("warning with 3 args", func(t *testing.T) { + ts.hook.Drain() + _, err := rt.RunString(sr(`http.get("HTTPBIN_URL/get", null, null, null);`)) + require.NoError(t, err) + entries := testutils.FilterEntries(ts.hook.Drain(), logrus.WarnLevel, "http.get only accepts") + require.Len(t, entries, 1) + assert.Contains(t, entries[0].Message, "2 extra argument(s) will be ignored") + }) + }) + + t.Run("http.head", func(t *testing.T) { + t.Run("no warning with 0 args", func(t *testing.T) { + ts.hook.Drain() + _, err := rt.RunString(sr(`http.head("HTTPBIN_URL/get");`)) + require.NoError(t, err) + entries := testutils.FilterEntries(ts.hook.Drain(), logrus.WarnLevel, "http.head only accepts") + assert.Empty(t, entries) + }) + + t.Run("no warning with 1 arg", func(t *testing.T) { + ts.hook.Drain() + _, err := rt.RunString(sr(`http.head("HTTPBIN_URL/get", null);`)) + require.NoError(t, err) + entries := testutils.FilterEntries(ts.hook.Drain(), logrus.WarnLevel, "http.head only accepts") + assert.Empty(t, entries) + }) + + t.Run("warning with 2 args", func(t *testing.T) { + ts.hook.Drain() + _, err := rt.RunString(sr(`http.head("HTTPBIN_URL/get", null, null);`)) + require.NoError(t, err) + entries := testutils.FilterEntries(ts.hook.Drain(), logrus.WarnLevel, "http.head only accepts") + require.Len(t, entries, 1) + assert.Contains(t, entries[0].Message, "1 extra argument(s) will be ignored") + }) + + t.Run("warning with 3 args", func(t *testing.T) { + ts.hook.Drain() + _, err := rt.RunString(sr(`http.head("HTTPBIN_URL/get", null, null, null);`)) + require.NoError(t, err) + entries := testutils.FilterEntries(ts.hook.Drain(), logrus.WarnLevel, "http.head only accepts") + require.Len(t, entries, 1) + assert.Contains(t, entries[0].Message, "2 extra argument(s) will be ignored") + }) + }) +}