-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Add ability to compress request body #989
Conversation
This adds `compression` param to all http methods with only current possible value `gzip` that will compress the body set the correct `Content-Encoding` and `Content-Length` and will send the request with the compressed body.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just don't forget to update release notes 🙂
I am even going to update the docs :P |
Codecov Report
@@ Coverage Diff @@
## master grafana/k6#989 +/- ##
==========================================
- Coverage 72.12% 72.09% -0.03%
==========================================
Files 131 131
Lines 9621 9636 +15
==========================================
+ Hits 6939 6947 +8
- Misses 2268 2272 +4
- Partials 414 417 +3
Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## master grafana/k6#989 +/- ##
==========================================
+ Coverage 72.12% 72.28% +0.16%
==========================================
Files 131 132 +1
Lines 9621 9699 +78
==========================================
+ Hits 6939 7011 +72
- Misses 2268 2273 +5
- Partials 414 415 +1
Continue to review full report at Codecov.
|
Moving the discussion about just using the It seems fine to me if we should throw errors when users try to specify unsupported A somewhat connected issue would be the |
I'm against using user specified headers as an implicit signal that we should do additional processing of the body contents (if you specify |
Well... I'm not totally convinced that we need separate options. I get that it might be a bit strange to modify k6's behavior by setting the headers map of a request object, but if the alternative is having multiple different and separate settings that magically modify the headers for every little thing? This will only exacerbate the config mess we're currently in... Even ignoring that, how do we handle things if those settings and the user-specified header values conflict? Do we silently overwrite them or do we throw an error? Or what if the user specified a Regarding And for super-advanced users that want to manually compress their request bodies or mess around with other internals, we could add a single boolean Also, we kind of already read the HTTP headers, to get any import http from "k6/http";
export let options = {
iterations: 2,
};
export default function () {
// Set cookies
if (__ITER === 0) {
let resp1 = http.get("https://httpbingo.org/cookies/set?key=value1");
console.log(resp1.body);
}
// Check cookies
let resp2 = http.get("https://httpbingo.org/cookies");
console.log(resp2.body);
// Check custom cookies...
let resp3 = http.get("https://httpbingo.org/cookies", {
headers: { "Cookie": "key=value2;anotherkey=anothervalue" }
});
console.log(resp3.body);
} And similarly, we probably need to validate any |
Us reading the headers is not a problem, us doing "magical" interactions with them is.
The bug above is strange ... I guess it has something to do with the way cookies are used and cookiejars and such. As an additional question how do you think #970 should be implemented ? because I have always thought it will be through params supposedly or do you propose they add the headers themself |
Sorry, I'm not sure I understand what you mean by "headers take precedence". Let's try with examples.... Here's this script, what should happen? http.get("https://httpbin.org/anything", {
compression: "gzip",
headers: {
"Content-Encoding": "br",
}
}); Here's a similar script, with http.post("https://httpbin.org/anything", {foo: "bar", "baz": "zaz"}, {
contentType: "application/json",
headers: {
"Content-Type": "multipart/form-data; boundary=--myBoundary",
}
}); If "headers take precedence" means we do nothing, since the user explicitly set the header, then this seems like a poor UX to me, since the user also explicitly set our parameter. Or are those errors, warnings, or do we silently overwrite the headers? And how would you deal with more complicated cases, like setting that custom multipart boundary with params? Like this: http.post("https://httpbin.org/anything", {foo: "bar", "baz": "zaz"}, {
contentType: "multipart/form-data; boundary=--myBoundary",
}); or by separate parameters, using an object? Or multiple encodings? In a header it's simply |
Regarding #970 - in the same way I'm not suggesting we make users implement brotly/gzip/zstd compression themselves, or NTLM/digest/basic authentication, I'm also not suggesting that they should implement the |
p.s. While writing this I decided that this discussion should probably be moved outside of this PR as this is getting out of scope By "precedence" I mean - we do nothing if they've setted a header that our param would've set. I think it means that they have mistaken something and we either error out (seem excessive but maybe the better option) or print a warning (probably going to get noisy). first example - we don't encode anything send the header as it is and print a warning/error out without doing anything. Will their server get uncompressed body when they expected compressed one -yes . Is that bad - yes. Do we have to read minds in this situation - I don't think so. second example - what does contentType does ? and leave it to what the Header is. third example - they are not doing it correctly ... it is not our fault the HTTP spec for multipart/form-data requires a lot of hard to write by hand text ...
All my arguments have been about: lets not overwrite what the user has said or change things without it being extremely obvious that this is what the user wants is, because I HATE MAGIC (not magic the gathering, that one is great). Everything that does something without it being obvious is potential issue.
And the thing while writing this that I found out is that there doesn't appear to be cases where k6 reads headers and than change them- it just change them to not make users set them but we require them to set other things in order for things like auth/multipart/formdata and so on to work, without the user setting the. We obviously will need to continue to set some headers on behalf of the user as thing such as Cookies and Content-Length and Agent and so on are hard to do. But IMO we should always leave what they have set. Otherwise there is no way to check how an API behaves if you send it crappy headers/data. To that end we should probably add another params flag such as |
I think it might be a little too late to move the discussion to the issue, since a lot of the context is already here...
They haven't though -
You've kind of answered yourself below in your post. Say that we "ignore" (i.e. not use for configuration but warn/error/? if there's mismatch?) the user-specified The current
This is mostly reasonable, and yes - slightly "magical" ✨ 😄 . If I was starting from scratch, maybe I would have had a much more explicit system, like how you're forced to build a multipart request in Go. But, given that k6 is a load testing tool, this small amount of magic is probably justified and results in better UX, especially if it actually worked better. It currently has a lot of shortcomings, and it breaks in some corner cases:
All of that can be easily fixed if we check for custom But instead of making the two options ( I feel your dislike for magic, I usually don't like it as well, but mostly the "magic at a distance" phenomenon. In this case, k6 reading the
|
After sleeping on this and thinking about it some more, I've mostly come around to your opinion, @mstoykov and @robingustafsson 😄, at least with regards to this specific feature ( Because we're already using some "magic" to determine the request I also propose that instead of a That will be a totally separate PR of course, and if you agree, I can add an issue about it. |
- Move compression to httpext - support deflate and gzip - support combination of the two
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly LGTM now, besides that minor nitpick about more informative error messages and having this code not use the new constants.
…from ParseRequest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This would restore the behavior pre-#989, so that any content-length header values manually specified by users would be overwritten by k6. Only, this time it won't be done silently, a warning would be shown every time there was a mismatch. The HAR converter is also modified to not include the content-length header in the generated sources. While that header isn't going to be a problem if its values matches the actual body content length, some HAR files are broken and include the header without any body data, and other times users may modify the body but forget the header. So, since k6 would automatically send it, we shouldn't include it in the script.
This would restore the behavior pre-#989, so that any content-length header values manually specified by users would be overwritten by k6. Only, this time it won't be done silently, a warning would be shown every time there was a mismatch. The HAR converter is also modified to not include the content-length header in the generated sources. While that header isn't going to be a problem if its values matches the actual body content length, some HAR files are broken and include the header without any body data, and other times users may modify the body but forget the header. So, since k6 would automatically send it, we shouldn't include it in the script.
This adds
compression
param to all http methods that will compress the bodyset the correct
Content-Encoding
andContent-Length
and will send the requestwith the compressed body. The currently supported algorithms are 'gzip' and 'deflate'.
Combinations of the two separated by a comma(",") are also supported.
This fixes #988