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

Automatically marshal JS-object HTTP request bodies when content-type is application/json #878

Closed
na-- opened this issue Dec 18, 2018 · 3 comments
Labels
enhancement evaluation needed proposal needs to be validated or tested before fully implementing it in k6 new-http issues that would require (or benefit from) a new HTTP API ux

Comments

@na--
Copy link
Member

na-- commented Dec 18, 2018

If we have this example k6 script:

import http from "k6/http";

export default function () {
    let data = {
        arr: [1, 2, 3, "a"],
        str: "test",
        obj: { a: "b", c: 4 },
    };
    let resp = http.post("https://httpbin.org/post", data, { headers: { "content-type": "application/json" } });
    console.log(resp.json().data);
}

Most people will expect it to print something like {"arr":[1,2,3,"a"],"str":"test","obj":{"a":"b","c":4}}, or to print a warning, or even fail with an error.

Instead, k6 will silently do a stupid thing and actually assume that the content-type is application/x-www-form-urlencoded, and thus try to urlencode the supplied object. Even that may have been fine, if there was a standard in for URL-encoding nested objects. But as far as I can see, there isn't an RFC for this, and and only PHP supports string keys in maps anyway. In the above example, k6 will actually print arr=%5B1+2+3+a%5D&obj=map%5Ba%3Ab+c%3A4%5D&str=test. Basically converts JS arrays and objects to strings and then just tacks them on, which is pretty much useless to everyone. To get the expected result, users have to manually pass JSON.stringify(data) instead of simply data.

So my suggestion is to specifically check if a request's body isn't a string or a binary payload and if its content-type is application/json and just automatically marshal the request body to JSON.

@na--
Copy link
Member Author

na-- commented Dec 18, 2018

A somewhat connected issue: #747

@na--
Copy link
Member Author

na-- commented Mar 15, 2021

Ah, sorry @codebien, looks like I'd forgotten to remove the good first issue tag when I added the evaluation needed one... 😞 The latter tag suggest that this issue needs further consideration before we implement it in k6.

I'd also forgotten to mention why I added the evaluation needed tag... In this case, the need for further evaluation arose after a discussion in #989 on whether it's a good idea to automagically manipulate the request body based on a header. So far, the rough consensus is "probably no", because:

  • it's very easy to JSON.stringify() bodies that require it
  • we want to reduce the amount of "magic" k6 does implicitly
  • when testing things like REST APIs that use JSON for every request, it's better UX to wrap the k6/http module and automatically do both things - encode the body as JSON and emit the content-type: application/json header for every request; this is one of the purposes of @sniku's httpx JS library hosted on jslib.k6.io (WIP PR for docs at Documentation for jslib.k6.io k6-docs#230)

So, yeah, we're probably not going to merge #1903, sorry. We'll probably merge something like #1754 in k6 v0.32.0, so we have a sane default for nested objects and close #1713, though maybe not that specific fix PR. And longer term, we plan to add a new k6 HTTP API that would allow for separate HTTP clients and essentially extend and support what we're trying to do with httpx natively, but that's a long ways off.

@na-- na-- added the new-http issues that would require (or benefit from) a new HTTP API label Oct 18, 2021
@imiric
Copy link
Contributor

imiric commented Mar 28, 2023

Given the last comment by @na--, the team consensus is that we want to avoid automagic behavior, so we will not be changing this in the current HTTP API.

We probably won't implement this exactly in the new API (initial design document) either, but will consider a different approach that avoids using JSON.stringify(). For example, we might want to have a json property that serializes the data and adds the Content-Type: application/json header, as inspired by the request Node library. We'll discuss the details as we flesh out the design of the new API.

@imiric imiric closed this as completed Mar 28, 2023
@imiric imiric closed this as not planned Won't fix, can't repro, duplicate, stale Mar 28, 2023
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 new-http issues that would require (or benefit from) a new HTTP API ux
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants