Skip to content

HTTP(S) Wait strategy

The HTTP wait strategy will check the result of an HTTP(S) request against the container and allows to set the following conditions:

  • the port to be used. If no port is passed, it will use the lowest exposed port in the image.
  • the path to be used.
  • the HTTP method to be used.
  • the HTTP request body to be sent.
  • the HTTP status code matcher as a function.
  • the HTTP response matcher as a function.
  • the HTTP headers to be used.
  • the HTTP response headers matcher as a function.
  • the TLS config to be used for HTTPS.
  • the startup timeout to be used in seconds, default is 60 seconds.
  • the poll interval to be used in milliseconds, default is 100 milliseconds.
  • the basic auth credentials to be used.

Info

It's important to notice that the HTTP wait strategy will default to the first port exported/published by the image.

Variations on the HTTP wait strategy are supported, including:

Match an HTTP method

ctx := context.Background()
req := testcontainers.ContainerRequest{
    Image:        "nginx:latest",
    ExposedPorts: []string{"80/tcp"},
    WaitingFor:   wait.ForHTTP("/").WithStartupTimeout(10 * time.Second),
}

c, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
    ContainerRequest: req,
    Started:          true,
})
defer func() {
    if err := testcontainers.TerminateContainer(c); err != nil {
        log.Printf("failed to terminate container: %s", err)
    }
}()
if err != nil {
    log.Printf("failed to start container: %s", err)
    return
}

Match an HTTP method with Port

ctx := context.Background()
req := testcontainers.ContainerRequest{
    Image:        "nginx:latest",
    ExposedPorts: []string{"8080/tcp", "80/tcp"},
    WaitingFor:   wait.ForHTTP("/").WithPort("80/tcp"),
}

c, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
    ContainerRequest: req,
    Started:          true,
})
defer func() {
    if err := testcontainers.TerminateContainer(c); err != nil {
        log.Printf("failed to terminate container: %s", err)
    }
}()
if err != nil {
    log.Printf("failed to start container: %s", err)
    return
}

Match an HTTP method with Basic Auth

ctx := context.Background()
req := testcontainers.ContainerRequest{
    Image:        "gogs/gogs:0.11.91",
    ExposedPorts: []string{"3000/tcp"},
    WaitingFor:   wait.ForHTTP("/").WithBasicAuth("username", "password"),
}

gogs, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
    ContainerRequest: req,
    Started:          true,
})
defer func() {
    if err := testcontainers.TerminateContainer(gogs); err != nil {
        log.Printf("failed to terminate container: %s", err)
    }
}()
if err != nil {
    log.Printf("failed to start container: %s", err)
    return
}

Match an HTTPS status code and a response matcher

tlsconfig := &tls.Config{RootCAs: certpool, ServerName: "testcontainer.go.test"}
var i int
dockerReq := testcontainers.ContainerRequest{
    FromDockerfile: testcontainers.FromDockerfile{
        Context: "testdata/http",
    },
    ExposedPorts: []string{"6443/tcp"},
    WaitingFor: wait.NewHTTPStrategy("/ping").WithTLS(true, tlsconfig).
        WithStartupTimeout(time.Second * 10).
        WithResponseMatcher(func(body io.Reader) bool {
            data, _ := io.ReadAll(body)
            return bytes.Equal(data, []byte("pong"))
        }).
        WithStatusCodeMatcher(func(status int) bool {
            i++ // always fail the first try in order to force the polling loop to be re-run
            return i > 1 && status == 200
        }).
        WithMethod(http.MethodPost).WithBody(bytes.NewReader([]byte("ping"))),
}

Match for HTTP response headers

tlsconfig := &tls.Config{RootCAs: certpool, ServerName: "testcontainer.go.test"}
req := testcontainers.ContainerRequest{
    FromDockerfile: testcontainers.FromDockerfile{
        Context: "testdata/http",
    },
    ExposedPorts: []string{"6443/tcp"},
    WaitingFor: wait.ForHTTP("/headers").
        WithTLS(true, tlsconfig).
        WithPort("6443/tcp").
        WithHeaders(map[string]string{"X-request-header": "value"}).
        WithResponseHeadersMatcher(func(headers http.Header) bool {
            return headers.Get("X-response-header") == "value"
        },
        ),
}