Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/Force HTTP1 functionality #2222

Merged
merged 21 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion js/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"net"
"net/http"
"net/http/cookiejar"
"os"
"runtime/debug"
"strconv"
"strings"
Expand Down Expand Up @@ -210,7 +211,12 @@ func (r *Runner) newVU(idLocal, idGlobal uint64, samplesOut chan<- stats.SampleC
MaxIdleConns: int(r.Bundle.Options.Batch.Int64),
MaxIdleConnsPerHost: int(r.Bundle.Options.BatchPerHost.Int64),
}
_ = http2.ConfigureTransport(transport)

if forceHTTP1() {
transport.TLSNextProto = make(map[string]func(string, *tls.Conn) http.RoundTripper) // send over h1 protocol
} else {
_ = http2.ConfigureTransport(transport) // send over h2 protocol
}

cookieJar, err := cookiejar.New(nil)
if err != nil {
Expand Down Expand Up @@ -262,6 +268,23 @@ func (r *Runner) newVU(idLocal, idGlobal uint64, samplesOut chan<- stats.SampleC
return vu, nil
}

// forceHTTP1 checks if force http1 env variable has been set in order to force requests to be sent over h1
// TODO: This feature is temporary until #936 is resolved
func forceHTTP1() bool {
godebug := os.Getenv("GODEBUG")
if godebug == "" {
return false
}
variables := strings.SplitAfter(godebug, ",")

for _, v := range variables {
if strings.Trim(v, ",") == "http2client=0" {
return true
}
}
return false
}

// Setup runs the setup function if there is one and sets the setupData to the returned value
func (r *Runner) Setup(ctx context.Context, out chan<- stats.SampleContainer) error {
setupCtx, setupCancel := context.WithTimeout(ctx, r.getTimeoutFor(consts.SetupFn))
Expand Down
82 changes: 82 additions & 0 deletions js/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2074,6 +2074,88 @@ func TestMinIterationDurationIsCancellable(t *testing.T) {
}
}

// nolint:paralleltest
func TestForceHTTP1Feature(t *testing.T) {
cases := map[string]struct {
godebug string
expectedForceH1Result bool
protocol string
}{
"Force H1 Enabled. Checking for H1": {
godebug: "http2client=0,gctrace=1",
expectedForceH1Result: true,
protocol: "HTTP/1.1",
},
"Force H1 Disabled. Checking for H2": {
godebug: "test=0",
expectedForceH1Result: false,
protocol: "HTTP/2.0",
},
}

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
err := os.Setenv("GODEBUG", tc.godebug)
require.NoError(t, err)
defer func() {
err = os.Unsetenv("GODEBUG")
require.NoError(t, err)
}()
assert.Equal(t, tc.expectedForceH1Result, forceHTTP1())

tb := httpmultibin.NewHTTPMultiBin(t)

data := fmt.Sprintf(`var k6 = require("k6");
var check = k6.check;
var fail = k6.fail;
var http = require("k6/http");;
exports.default = function() {
var res = http.get("HTTP2BIN_URL");
if (
!check(res, {
'checking to see if status was 200': (res) => res.status === 200,
'checking to see protocol': (res) => res.proto === '%s'
})
) {
fail('test failed')
}
}`, tc.protocol)

r1, err := getSimpleRunner(t, "/script.js", tb.Replacer.Replace(data))
require.NoError(t, err)

err = r1.SetOptions(lib.Options{
sjordhani22 marked this conversation as resolved.
Show resolved Hide resolved
Hosts: tb.Dialer.Hosts,
// We disable TLS verify so that we don't get a TLS handshake error since
// the certificates on the endpoint are not certified by a certificate authority
InsecureSkipTLSVerify: null.BoolFrom(true),
})

require.NoError(t, err)

registry := metrics.NewRegistry()
builtinMetrics := metrics.RegisterBuiltinMetrics(registry)
r2, err := NewFromArchive(testutils.NewLogger(t), r1.MakeArchive(), lib.RuntimeOptions{}, builtinMetrics, registry)
require.NoError(t, err)

runners := map[string]*Runner{"Source": r1, "Archive": r2}
for name, r := range runners {
r := r
t.Run(name, func(t *testing.T) {
initVU, err := r.NewVU(1, 1, make(chan stats.SampleContainer, 100))
require.NoError(t, err)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
vu := initVU.Activate(&lib.VUActivationParams{RunContext: ctx})
err = vu.RunOnce()
require.NoError(t, err)
})
}
})
}
}

func TestExecutionInfo(t *testing.T) {
t.Parallel()

Expand Down
2 changes: 1 addition & 1 deletion lib/netext/httpext/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ import (
"net/url"
"testing"

"github.com/sirupsen/logrus"
"go.k6.io/k6/lib"
"go.k6.io/k6/stats"
"github.com/sirupsen/logrus"
)

func BenchmarkMeasureAndEmitMetrics(b *testing.B) {
Expand Down