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
3
4
5
6
7
// Adapter injected
Client()                        // No base endpoint, whole URL must be passed each request
Client("http://host:1234/base") // Requests' paths will be appended to supplied base URL

// Adapter provided explicitly
Client(adapter)
Client(adapter, "http://host:1234/base")

Using client settings

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// All client settings parameters are optionals and provide default values
Client("http://host:1234/base", ClientSettings(
    contentType = "application/json",
    useCookies = true,
    headers = mapOf("X-Api-Key" to listOf("cafebabe")), // Headers to use in all requests
    user = "user",                                      // HTTP Basic auth user
    password = "password",                              // HTTP Basic auth password
    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
val request = Request(
    method = GET,
    path = "/",
    body = mapOf("body" to "payload"),
    headers = mapOf("X-Header" to listOf("value")),
    contentType = Json.contentType
)

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
val body = mapOf("key" to "value")

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

Shortcut including body and content type

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

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

Use Cookies Example

Check the details at the full test.

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

// Set the cookie in the client
client.cookies["sampleCookie"] = 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
assert(client.cookies[cookieName]?.value == cookieValue + "_changed")

Multipart Requests Example

Refer to the full test for more details.

Send form fields

1
2
val parts = mapOf("name" to Part("name", "value"))
val response = client.send(Request(POST, "/multipart", parts = parts))

Send and attached file

1
2
3
val stream = URL("classpath:assets/index.html").openStream()
val parts = mapOf("file" to Part("file", stream, "index.html"))
val response = client.send(Request(POST, "/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
// 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 = ServerSettings(
    bindPort = 0,
    protocol = HTTPS, // You can also use HTTP2
    sslSettings = sslSettings
)

val server = serve(serverSettings, serverAdapter) {
    get("/hello") {
        // We can access the certificate used by the client from the request
        val subjectDn = request.certificate?.subjectDN?.name
        response.headers["cert"] = subjectDn
        ok("Hello World!")
    }
}

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

// Create a HTTP client and make a HTTPS request
val client = Client(AhcAdapter(), "https://localhost:${server.runtimePort}", clientSettings)
client.get("/hello").apply {
    logger.debug { body }
    // Assure the certificate received (and returned) by the server is correct
    assert(headers.require("cert").first().startsWith("CN=hexagonkt.com"))
    assert(body == "Hello World!")
}

Comments