k6 icon indicating copy to clipboard operation
k6 copied to clipboard

Option to set default HTTP configuration globally

Open na-- opened this issue 7 years ago • 7 comments
trafficstars

Currently users can specify the userAgent that would be used by k6 by default when it makes HTTP requests. I'd be useful if we can generalize that and allow users to specify the default value of any header they want globally. Use cases that I can think of:

  • custom headers that should be in every request (people have asked for this on slack)
  • Accept-Encoding and Accept-Language headers are pretty much the same for all requests, if you want your test to look like a browser. It might also make some sense to manually set the Connection header as well.
  • connected to the previous point, it would help with making the HAR converter produce much more readable scripts
  • we can optionally gently deprecate the --user-agent flag, suggesting instead the usage of --header User-Agent="my-custom-useragent-value", to avoid CLI interface clutter

na-- avatar Sep 11 '18 12:09 na--

It seems worth it to also allow other request options (https://docs.k6.io/docs/params-k6http) to be specified globally. It'd be especially useful to be able add cookies or to change the global default timeout...

na-- avatar Nov 23 '18 09:11 na--

I agree that it would be useful to be able to set defaults for all (or most) request options. Now I don't think that all of these would also need a cli option. For most it would be enough to be able to specify them in the script.

marklagendijk avatar Feb 21 '19 07:02 marklagendijk

Being able to set a global timeout would definitely be a good addition.

simskij avatar Sep 28 '20 12:09 simskij

https://github.com/loadimpact/k6/issues/1865 is a request to be able to specify the Content-Type header globally, which I'll close in favor of this issue.

In general, it's not certain if we'll implement this issue at all. It's more likely we'll go for a whole new version of the HTTP API where you are able to create multiple HTTP clients, each with different default properties (headers, connection reuse and proxy settings, timeouts, etc.). We've delayed even writing an issue for that new and better HTTP API for probably close to 2 years now, due to the many other things that have had higher priority... :disappointed: So I can't give any ETAs, but it will happen eventually, we're slowly running out of more important things... :sweat_smile:

It will probably be done as an xk6 (https://github.com/k6io/xk6) extension initially, and adopted in the k6 core when it's good enough and stable. If someone wants to take an early stab at it, here is some more info on how extensions are made: https://k6.io/blog/extending-k6-with-xk6

Until then, it's worth pointing out that we already have a pure JavaScript wrapper around k6/http that does some of the things described in this issue, hosted on https://jslib.k6.io/: https://jslib.k6.io/httpx/0.0.3/index.js

We haven't documented it well yet, and it's still a very early prototype, but the code is short enough to be understandable... You can create something like an HTTP client and set headers and tags that are applied to every HTTP request. We also always accept PRs at https://github.com/k6io/jslib.k6.io/ and https://k6.io/docs/ with improvements :sweat_smile:

na-- avatar Feb 19 '21 12:02 na--

I encountered the same problem during the implementation of the "functional.js" library for k6.

It's handy to be able to specify default headers, baseURL, tags and other parameters. I implemented a httpx wrapper around the built-in http library to accomplish this. While I have not documented all the functionality, I think the code is self-explanatory, so anyone who finds this issue can consider using it.

import { test } from 'https://jslib.k6.io/functional/0.0.1/index.js';
import { Httpx } from 'https://jslib.k6.io/httpx/0.0.3/index.js';

import { randomIntBetween, randomItem } from "https://jslib.k6.io/k6-utils/1.0.0/index.js";

export let options = {
  thresholds: {
    'http_req_duration{name:PublicCrocs}': ['p(90)<200'],
    checks: [{threshold: 'rate == 1.00', abortOnFail: true}],
  },
};

const USERNAME = `user${randomIntBetween(1, 100000)}@example.com`;  // Set your own email;
const PASSWORD = 'superCroc2019';

let session = new Httpx({
    baseURL: 'https://test-api.k6.io', 
    headers: {
        'User-Agent': "My custom user agent",
        "Content-Type": 'application/x-www-form-urlencoded' // or 'MyDefaultContentType'
    },
    timeout: 20000 // 20s timeout.
});

export default function testSuite() {

  test(`Create a test user ${USERNAME}`, (t) => {

    let resp = session.post(`/user/register/`, {
      first_name: 'Crocodile',
      last_name: 'Owner',
      username: USERNAME,
      password: PASSWORD,
    });

    t.expect(resp.status).as("status").toEqual(201)
      .and(resp).toHaveValidJson();
  })

  &&

  test(`Authenticate the new user ${USERNAME}`, (t) => {

    let resp = session.post(`/auth/token/login/`, {
      username: USERNAME,
      password: PASSWORD
    });

    t.expect(resp.status).as("Auth status").toBeBetween(200, 204)
      .and(resp).toHaveValidJson()
      .and(resp.json('access')).as("auth token").toBeTruthy();

    let authToken = resp.json('access');
    // set the authorization header on the session for the subsequent requests.
    session.addHeader('Authorization', `Bearer ${authToken}`);

  })

  &&

  test('04. Create a new crocodile', (t) => {
    let payload = {
      name: `Croc Name`,
      sex: randomItem(["M", "F"]),
      date_of_birth: '2019-01-01',
    };

    let resp = session.post(`/my/crocodiles/`, payload);

    t.expect(resp.status).as("Croc creation status").toEqual(201)
      .and(resp).toHaveValidJson();
  })

}

Note, I'm defining an http client called session outside of the default function. All requests that use session, get default parameters defined in the constructor. Session parameters can also be updated in the default function. See line

session.addHeader('Authorization', `Bearer ${authToken}`);

which adds a new default header to the existing session. Subsequent requests will get this header by default.

Note: both the functional.js and httpx.js libraries are in active development, so you may want to check https://jslib.k6.io/ to see if there are newer releases.

sniku avatar Feb 19 '21 13:02 sniku

Where are we with this?

testn avatar Jun 01 '22 09:06 testn

custom headers that should be in every request

Some tests interact with different systems (domains), requiring distinct headers.

Perhaps, it is useful to also allow configuring "global" headers for each specific (sub)domains.

ppcano avatar Apr 15 '24 08:04 ppcano