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

Any way to force to use HTTP/1.1 protocol #936

Closed
spaiz opened this issue Mar 3, 2019 · 9 comments
Closed

Any way to force to use HTTP/1.1 protocol #936

spaiz opened this issue Mar 3, 2019 · 9 comments
Labels
enhancement evaluation needed proposal needs to be validated or tested before fully implementing it in k6 help wanted new-http issues that would require (or benefit from) a new HTTP API

Comments

@spaiz
Copy link

spaiz commented Mar 3, 2019

Just looked over the docs and didn't find any way to force the k6 not to switch to HTTP 2

I must do it cause we have a clients that won't use HTTP 2, so when I test I want to test the same protocol.

Tnx.

@na--
Copy link
Member

na-- commented Mar 5, 2019

Unfortunately there's currently no way to force k6 to use HTTP/1.1 if the remote server supports HTTP/2 and the connection is over HTTPS. I think that's mostly a consequence of the way the Go standard library's HTTP client operates - it also doesn't allow us to specify the HTTP version you want to use for a particular request.

That said, I think we can potentially slightly ameliorate this in k6 by adding the option to disable HTTP/2 globally, or at maybe at a per-VU/per-group() basis. Not sure how much refactoring would be needed for the more granular approaches, but the way we can do this is by modifying the http.Transport we use to make HTTP requests in k6. If we don't execute this line:
https://github.com/loadimpact/k6/blob/0b1b25949256544226cbe3641ad8024c06ef3420/js/runner.go#L171
k6 will be unable to make HTTP/2 requests. The trouble comes from the fact that this is executed once, in the beginning of initializing each VU, so it'd be somewhat difficult to get more granular than a global "don't allow any HTTP/2 requests" option...

@na-- na-- added help wanted evaluation needed proposal needs to be validated or tested before fully implementing it in k6 labels Mar 5, 2019
@spaiz
Copy link
Author

spaiz commented Mar 7, 2019

Thanks for the answer.

Disallowing http/2 usage globally should be good enough. Cannot think about situation when I would like to test both protocols in the same benchmark session.

Just found in the go's doc:

Starting with Go 1.6, the http package has transparent support for the
HTTP/2 protocol when using HTTPS. Programs that must disable HTTP/2
can do so by setting Transport.TLSNextProto (for clients) or
Server.TLSNextProto (for servers) to a non-nil, empty
map. Alternatively, the following GODEBUG environment variables are
currently supported:

GODEBUG=http2client=0  # disable HTTP/2 client support
GODEBUG=http2server=0  # disable HTTP/2 server support
GODEBUG=http2debug=1   # enable verbose HTTP/2 debug logs
GODEBUG=http2debug=2   # ... even more verbose, with frame dumps

Before talking about refactoring, will the k6 see honor the GO's env variables? May be it can be a quick win...

@na--
Copy link
Member

na-- commented Mar 7, 2019

A quick test with GODEBUG=http2client=0 and this script:

import http from "k6/http";

export default function () {
    let resp = http.get("https://google.com/");
    console.log(resp.proto);
}

shows that we unfortunately don't honor those environment variables. I think the reason is that line I quoted above: https://github.com/loadimpact/k6/blob/0b1b25949256544226cbe3641ad8024c06ef3420/js/runner.go#L171
We use that code from the golang.org/x/net/http2 package (connected k6 issue) because we define our own http.Transport just above that line: https://github.com/loadimpact/k6/blob/0b1b25949256544226cbe3641ad8024c06ef3420/js/runner.go#L153-L171
We need to define our own http.Transport in order to have customizable TLS settings, and we need to use http2.ConfigureTransport(transport) in order for that transport to support HTTP/2 at all. But it seems that in golang.org/x/net/http2 they don't honor any of the GODEBUG values besides http2debug: https://github.com/golang/net/search?q=GODEBUG&unscoped_q=GODEBUG 😞 So we'll need to handle disabling HTTP/2 in k6, and unfortunately it doesn't look like there's a quick workaround.

@spaiz
Copy link
Author

spaiz commented Mar 10, 2019

Understood. Tnx for help.

Will try for to fork k6 and implement it for my usage... if it will look good will open PR.

@na--
Copy link
Member

na-- commented Jun 12, 2019

A proposal on how something like this (among other things) could be implemented in k6 in a backwards compatible and reasonably performant and user-friendly way: #1045 (comment)

@ajay-sainy
Copy link

@spaiz Did you find any solution? I am also facing same error

ERRO[0004] GoError: Get "https://": stream error: stream ID 1; HTTP_1_1_REQUIRED
at github.com/loadimpact/k6/js/common.Bind.func1 (native)

@mstoykov
Copy link
Contributor

This is now supported since #2222, but is still not documented as can be seen in grafana/k6-docs#664

to use it you need to set the GODEBUG env variable to http2client=0 before running k6. Effectively what didn't work in #936 (comment) now does work.

I will leave this open both for more visibility and because I kind of doubt we will keep this working with the New HTTP API so we will likely need a different way to fix that there.

@automationmaven
Copy link

automationmaven commented Jan 22, 2023

I DO have a workaround for this... It's not great... but it works.
You can proxy through fiddler classic which does not support HTTP 2 and it will downgrade all of the calls. There might be another more elegant way to use a different proxy to do the same. Also, you might be able to keep fiddler stable so that you don't slam fiddler and run it out of memory during the test, just apply a filter that will never capture anything like "~~~~".
If you are running via Powershell, you can set the run to proxy through fiddler like this:

set-item env:HTTPS_PROXY localhost:8888

This will set it to proxy through the default proxy port for Fiddler Classic.

If nothing else, you could use this to ty to confirm whether this is actually the problem you're seeing or not.

Also, check out the documentation for any questions on this. This doesn't just pertain to Android, it's just some of the better documentation on using fiddler as a proxy, and figuring out desktop proxy is easy - just launch fiddler and make sure it's setup correctly - here's the documentation on the tougher case. https://docs.telerik.com/fiddler/configure-fiddler/tasks/configureforandroid

@imiric
Copy link
Contributor

imiric commented Mar 28, 2023

Since this is now fixed by #2222, and we're unlikely to change how this works in the current HTTP API, I'll close this issue.

We're currently working on the new HTTP API (initial design document), and this feature will be addressed differently there. It's planned as part of Phase 1 of the proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement evaluation needed proposal needs to be validated or tested before fully implementing it in k6 help wanted new-http issues that would require (or benefit from) a new HTTP API
Projects
None yet
Development

No branches or pull requests

6 participants