Multipart form requests - add headers and batch requests

Is it possible to add a header to a multipart form request (where I’m uploading a file)? My upload is failing because a bespoke request header is missing.

Also, is it possible to have a multipart request sent as one of the requests in a batch?

Yes, you can set custom headers like how you usually set them in single or batch requests. Here’s an example for both of your questions:

import http from "k6/http";

export default function () {
    let payload = {
        someFile: http.file("some file data, maybe via open()", "test.txt"),
        someNonFileData: "whatever",
    };
    let params = {
        headers: {
            "my-special-header": "foo",
        },
        timeout: 2000,
    };

    let postResponse = http.post("https://httpbin.test.loadimpact.com/post", payload, params);
    console.log(postResponse.body);
    let batchResponses = http.batch([
        ["POST", "https://httpbin.test.loadimpact.com/post", payload, params],
        ["POST", "https://httpbin.test.loadimpact.com/post", payload, { headers: { "some-other-header": "bar" } }],
        ["GET", "https://httpbin.test.loadimpact.com/anything", null, params],
    ]);
    console.log(batchResponses[1].body);
}

This would output something like this:

{
  "args": {}, 
  "data": "", 
  "files": {
    "someFile": "some file data, maybe via open()"
  }, 
  "form": {
    "someNonFileData": "whatever"
  }, 
  "headers": {
    "Content-Length": "408", 
    "Content-Type": "multipart/form-data; boundary=551edbbd317cbea6471a55ab1a71e09b4a674629b90c9e8ec792c477b2d7", 
    "Host": "httpbin.test.loadimpact.com", 
    "My-Special-Header": "foo", 
    "User-Agent": "k6/0.26.0 (https://k6.io/)", 
  }, 
  "json": null, 
  "url": "https://httpbin.test.loadimpact.com/post"
} 
{
  "args": {}, 
  "data": "", 
  "files": {
    "someFile": "some file data, maybe via open()"
  }, 
  "form": {
    "someNonFileData": "whatever"
  }, 
  "headers": {
    "Content-Length": "408", 
    "Content-Type": "multipart/form-data; boundary=f514b810aaeb5969fce380049a85f26cfa89ecd699733d337af6a5dad759", 
    "Host": "httpbin.test.loadimpact.com", 
    "Some-Other-Header": "bar", 
    "User-Agent": "k6/0.26.0 (https://k6.io/)", 
  }, 
  "json": null, 
  "url": "https://httpbin.test.loadimpact.com/post"
} 

1 Like

Hello!
I have related question here. I need to pass request body in a form like this:

------WebKitFormBoundarygBo5S1n4XIhu707h
Content-Disposition: form-data; name="image"; filename="image.png"
Content-Type: image/png

‰PNG

IHDR;.....some file data…

In order to achieve that I’m tring to send request like this:

let binImage = open("./flag.png", "b");

        let headers = {
            "Authorization": "bearer " + user.token,
            "clientid": "webapp"
        }

        var data = {
            file: http.file(binImage, "flag.png", "image/png")
        };

        let res = http.post(URL, data, {headers: headers});

But as a result this kind of request is being sent:

–e6c19b95ce0975c1e8f83876bb81c534f1c89030ce54289cfac66657201c
Content-Disposition: form-data; name=“file”; filename=“flag.png”
Content-Type: image/png

�PNG

IHDR…some file data

This causes me MulterError: Unexpected field error. My guess is that name field values in Content-Disposition differs from each other. I need name=“image”, but I get name=“file”. How can I pass the right value here and avoid such error?

Thank you

@AlexJioev, just change the key in data :smile: Something like this:

var data = {
    // notice the "image" here instead of "file"
    image: http.file(binImage, "image.png", "image/png") 
};

let res = http.post(URL, data, {headers: headers});
2 Likes

OMG, that’s so obvious, and I spent like 1 hour trying to figure this out :grinning: :man_facepalming:
Thank you! :slight_smile:

I have a related question has well. If I have multiple urls that are the same with slightly different headers, how do I differentiate them in the batch requests. Take these for example

response = http.post(

      "http://10.1.11.2:8000",

      '{"size":0,"query":{"bool":{"must":[],"must_not":[],"filter":[]}},"aggregations":{"1__cfgroup":{"terms":{"field":"measure_name","size":10000,"order":{"_term":"asc"}},"aggregations":{}}}}',

      {

        headers: {

          Host: "10.1.11.2:8000",

          Connection: "keep-alive",

          "User-Agent":

            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147 Safari/537.36",

          "content-type": "application/json",

          Accept: "*/*",

          Origin: "http://chart.com",

          Referer: "http://chart.com",

          "Accept-Encoding": "gzip, deflate",

          "Accept-Language": "en-US,en;q=0.9",

          "Content-Type": "application/json",

        },

      }

    );

response = http.post(

      "http://10.1.11.2:8000",

      '{"size":0,"query":{"bool":{"must":[],"must_not":[],"filter":[]}},"aggregations":{"1__cfgroup":{"terms":{"field":"compliance_year","size":10000,"order":{"_term":"desc"}},"aggregations":{}}}}',

      {

        headers: {

          Host: "10.1.11.2:8000",

          Connection: "keep-alive",

          "User-Agent":

            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147 Safari/537.36",

          "content-type": "application/json",

          Accept: "*/*",

          Origin: "http://chart.com",

          Referer: "http://chart.com/",

          "Accept-Encoding": "gzip, deflate",

          "Accept-Language": "en-US,en;q=0.9",

          "Content-Type": "application/json",

        },

      }

    );

what would I add to a batch request like this to differentiate these urls.
export default function () {

    group(' elasticsearch', function () {

      group(':9200', function () {

         let responses = http.batch([
            ['POST', 'http://10.1.11.2:8000'],
            ['POST', 'http://10.1.11.2:8000'],

@ralex7, I’m not sure I understand your question fully, but you can assign unique tags for every individual HTTP request in the http.batch() call, as shown in the examples here: https://k6.io/docs/javascript-api/k6-http/batch-requests#example-with-request-as-an-array

Would there be a way to use the ‘{“size”:0,“query”:{“bool”:{“must”:[],“must_not”:[],“filter”:[]}},“aggregations”:{“1__cfgroup”:{“terms”:{“field”:“measure_name”,“size”:10000,“order”:{"_term":“asc”}},“aggregations”:{}}}}’, in my tags because that is the only difference in the urls.

The tags are a string to string map, technically you can put anything you want in there, though I’d advise you not to put the a JSON query inside one, but rather something shorter that summarizes it…

So if I have multiple of the same URL that only differs in the JSON query there is no way to put that in the batch requests?