Skip to main content

HTTP plugin

This document will help you learn about NBomber.HTTP plugin in more detail.

Overview#

NBomber.Http provides a simple API to define HTTP steps, calculate response size, apply assertions.

Installation#

Add HTTP package into your project.

dotnet add package NBomber.Http

Create HTTP load test

Program.fs
open System
open System.Net.Http
open FSharp.Control.Tasks.NonAffine
open NBomber.Contracts
open NBomber.FSharp
open NBomber.Plugins.Network.Ping
open NBomber.Plugins.Http.FSharp
[<EntryPoint>]
let main argv =
// it's optional Ping plugin that brings additional reporting data
let pingConfig = PingPluginConfig.CreateDefault "nbomber.com"
let pingPlugin = new PingPlugin(pingConfig)
let httpFactory = HttpClientFactory.create()
let step = Step.create("simple step", clientFactory = httpFactory, execute = fun context ->
Http.createRequest "GET" "https://nbomber.com"
|> Http.withHeader "Accept" "text/html"
|> Http.withBody(new StringContent("{ some JSON }"))
|> Http.withCheck(fun response -> task {
return if response.IsSuccessStatusCode then Response.ok()
else Response.fail()
})
|> Http.send context
)
Scenario.create "nbomber-web-site" [step]
|> Scenario.withLoadSimulations [InjectPerSec(rate = 100, during = seconds 30)]
|> NBomberRunner.registerScenario
|> NBomberRunner.withWorkerPlugins [pingPlugin]
|> NBomberRunner.run
|> ignore
0 // return an integer exit code

HTTP API#

NBomber.Http provides HTTP API that can be used to create/send request and check response. It supports HTTP protocol specific concepts like HEADERS, BODY, VERSION.

HTTP Request#

NBomber.Http provides a convenient way to define HTTP request and then send it.

let httpFactory = HttpClientFactory.create();
let step1 = Step.create("step 1", clientFactory = httpFactory, execute = fun context ->
Http.createRequest "GET" "https://nbomber.com"
|> Http.send context
)
let step2 = Step.create("step 2", clientFactory = httpFactory, execute = fun context -> task {
let step1Response = context.GetPreviousStepResponse<HttpResponseMessage>()
let headers = step1Response.Headers
let! body = step1Response.Content.ReadAsStringAsync()
return! Http.createRequest "GET" "https://nbomber.com"
|> Http.send context
})

HTTP Version#

By default, NBomber.Http sets HTTP Version 1.1 but you can override this.

Http.withVersion "2.0"

HTTP Headers#

By default, NBomber.Http sets no headers but you can override this.

Http.withHeader "Accept" "application/json"

HTTP Body#

// here we set string content
Http.withBody(new StringContent json)
// here we set binary data
Http.withBody(new ByteArrayContent bytes)

HTTP Check Response#

By default, NBomber.Http is using this check for every response but you can override it.

Http.withCheck(fun response -> task {
if response.IsSuccessStatusCode then
return Response.ok(response, statusCode = int response.StatusCode)
else
return Response.fail(statusCode = int response.StatusCode)
})

HTTP ClientFactory#

NBomber.Http provides HttpClientFactory abstraction that can be used to init a base HttpClient that will be used within your test.

note

NBomberHttpClientFactory creates only one instance of HttpClient and uses it for all steps. You can override it if you need it.

let httpFactory = HttpClientFactory.create();
let step1 = Step.create("step 1", clientFactory = httpFactory, execute = fun context ->
Http.createRequest "GET" "https://nbomber.com"
|> Http.send context
)

HTTP Client Timeout#

By default, NBomber.Http uses HttpClient with default timeout for 100 seconds. A Domain Name System (DNS) query may take up to 15 seconds to return or time out. You can adjust and set a cutom timeout.

note

Also, pay attention that NBomber Step has a default timeout for 1 second.

let myHttpClient = new HttpClient()
myHttpClient.Timeout <- seconds 5
let httpFactory = HttpClientFactory.create("my_http_factory", myHttpClient)

Tracing#

There may be situations when you need to trace your requests and responses. The NBomber.Http has built-in functionality for tracing every request/response. In order to start tracing you need to set minimum logging level to Verbose.

NBomberRunner.withLoggerConfig(fun () ->
LoggerConfiguration().MinimumLevel.Verbose()
)

Also, you can enable tracing via the infrastructure config file.

infra-config.json
{
"Serilog": {
"MinimumLevel": "Verbose"
}
}

JSON parsing#

To work with the JSON format, you can use any library you prefer. Here is a list of popular libraries:

Here is an example with using Newtonsoft.Json, but you can use any other.

Http.createRequest "GET" url
|> Http.withCheck(fun response -> task {
let! jsonBody = response.Content.ReadAsStringAsync()
// parse JSON
let posts =
jsonBody
|> JsonConvert.DeserializeObject<PostResponse[]>
|> Option.ofObj
match posts with
| Some ps when ps.Length > 0 -> return Response.ok()
| -> return Response.fail()
})

Best practices#

  • To test HTTP use LoadSimulation.InjectPerSec since usually web server is an open system. You can read more here.
  • For debugging or tracing you can use LoadSimulation.KeepConstant with copies = 1 since for this simulation NBomber will use a single thread which is easier to debug.
  • Use Ping plugin to get more info about networking.
  • Convert your integration tests to load tests