Skip to content

HTTP Client

HTTP Client Creation Example

This example shows how to create HTTP Client instances. Check the full test for more information.

Without setting parameters

1
2
HttpClient(adapter)
HttpClient(adapter, URL("http://host:1234/base"))

Using client settings

1
2
3
4
5
6
7
8
9
// All client settings parameters are optionals and provide default values
HttpClient(adapter, HttpClientSettings(
    baseUrl = URL("http://host:1234/base"),
    contentType = ContentType(JSON),
    useCookies = true,
    headers = HttpFields(Header("x-api-Key", "cafebabe")), // Headers used in all requests
    insecure = false,               // If true, the client doesn't check server certificates
    sslSettings = SslSettings()     // Key stores settings (check TLS section for details)
))

Send Requests Example

This example shows send HTTP requests to a server. Here you can check the full test.

Generic request

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
val request = HttpClientRequest(
    method = GET,
    path = "/",
    body = mapOf("body" to "payload").serialize(),
    headers = HttpFields(Header("x-header", "value")),
    queryParameters = HttpFields(QueryParameter("qp", "qpValue")),
    contentType = ContentType(JSON)
)

val response = client.send(request)

Shortcut without body sending

1
2
3
4
5
6
7
8
val responseGet = client.get("/")
val responseHead = client.head("/")
val responsePost = client.post("/")
val responsePut = client.put("/")
val responseDelete = client.delete("/")
val responseTrace = client.trace("/")
val responseOptions = client.options("/")
val responsePatch = client.patch("/")

Shortcut with payload sending

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
val body = mapOf("key" to "value")
val serializedBody = body.serialize()

val responseGet = client.get("/", body = serializedBody)
val responsePost = client.post("/", serializedBody)
val responsePut = client.put("/", serializedBody)
val responseDelete = client.delete("/", serializedBody)
val responseTrace = client.trace("/", serializedBody)
val responseOptions = client.options("/", serializedBody)
val responsePatch = client.patch("/", serializedBody)

Shortcut including body and content type

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
val body = mapOf("key" to "value")
val serializedBody = body.serialize(YAML)

val responseGet = client.get("/", body = serializedBody, contentType = ContentType(YAML))
val responsePost = client.post("/", serializedBody, contentType = ContentType(YAML))
val responsePut = client.put("/", serializedBody, contentType = ContentType(YAML))
val responseDelete = client.delete("/", serializedBody, contentType = ContentType(YAML))
val responseTrace = client.trace("/", serializedBody, contentType = ContentType(YAML))
val responseOptions = client.options("/", serializedBody, contentType = ContentType(YAML))
val responsePatch = client.patch("/", serializedBody, contentType = ContentType(YAML))

Use Cookies Example

Check the details at the full test.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
val cookieName = "sampleCookie"
val cookieValue = "sampleCookieValue"

// Set the cookie in the client
client.cookies = client.cookies + HttpCookie(cookieName, cookieValue)

// Assert that it is received in the server and change its value afterwards
client.post("/assertHasCookie?cookieName=$cookieName")
client.post("/addCookie?cookieName=$cookieName&cookieValue=${cookieValue}_changed")

// Verify that the client cookie is updated
assertEquals(cookieValue + "_changed", client.cookiesMap()[cookieName]?.value)

// The cookie is persisted along calls
client.post("/assertHasCookie?cookieName=$cookieName")
assertEquals(cookieValue + "_changed", client.cookiesMap()[cookieName]?.value)

Multipart Requests Example

Refer to the full test for more details.

Send form fields

1
2
val parts = listOf(HttpPart("name", "value"))
val response = client.send(HttpClientRequest(POST, path = "/multipart", parts = parts))

Send and attached file

1
2
3
val stream = URL("classpath:assets/index.html").readBytes()
val parts = listOf(HttpPart("file", stream, "index.html"))
val response = client.send(HttpClientRequest(POST, path = "/file", parts = parts))

Mutual TLS Example

This example shows how make requests using mutual TLS between the client and the server. You can check the full test for more details.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// Key store files
val identity = "hexagonkt.p12"
val trust = "trust.p12"

// Default passwords are file name reversed
val keyStorePassword = identity.reversed()
val trustStorePassword = trust.reversed()

// Key stores can be set as URIs to classpath resources (the triple slash is needed)
val keyStore = URL("classpath:ssl/$identity")
val trustStore = URL("classpath:ssl/$trust")

val sslSettings = SslSettings(
    keyStore = keyStore,
    keyStorePassword = keyStorePassword,
    trustStore = trustStore,
    trustStorePassword = trustStorePassword,
    clientAuth = true // Requires a valid certificate from the client (mutual TLS)
)

val serverSettings = HttpServerSettings(
    bindPort = 0,
    protocol = HTTPS, // You can also use HTTP2
    sslSettings = sslSettings
)

val server = HttpServer(serverAdapter(), serverSettings) {
    get("/hello") {
        // We can access the certificate used by the client from the request
        val subjectDn = request.certificate()?.subjectX500Principal?.name ?: ""
        val h = response.headers + Header("cert", subjectDn)
        ok("Hello World!", headers = h)
    }
}
server.start()

// We'll use the same certificate for the client (in a real scenario it would be different)
val clientSettings = HttpClientSettings(sslSettings = sslSettings)

// Create an HTTP client and make an HTTPS request
val contextPath = URL("https://localhost:${server.runtimePort}")
val client = HttpClient(clientAdapter(), contextPath, clientSettings)
client.start()
client.get("/hello").apply {
    // Assure the certificate received (and returned) by the server is correct
    assert(headers.require("cert").startsWith("CN=hexagonkt.com"))
    assertEquals("Hello World!", body)
}