Introduction to khttp
khttp is a lightweight and user-friendly HTTP client library for Kotlin that simplifies making HTTP requests. It provides a more intuitive and concise syntax compared to the standard Java HTTP libraries. khttp is built on top of the Apache HttpClient library and allows you to perform various types of HTTP requests easily.
In this article, we will explore how to use khttp to make HTTP requests in Kotlin.
Setting Up khttp in Your Project
Before you can start using khttp in your Kotlin project, you need to add the khttp library as a dependency. If you are using Gradle, add the following line to your build.gradle.kts
file:
implementation("io.github.khttp:khttp:1.0.0")
If you are using Maven, add the following XML snippet to your pom.xml
file:
<dependency>
<groupId>io.github.khttp</groupId>
<artifactId>khttp</artifactId>
<version>1.0.0</version>
</dependency>
After adding the dependency, sync or rebuild your project to include the khttp library.
Making HTTP GET Requests
To make an HTTP GET request using khttp, you simply need to call the get
function and pass the URL of the resource you want to access. The response returned by the get
function contains all the information about the response, including the status code, headers, and content.
Let’s see how to make a simple GET request with khttp:
import khttp.get
fun main() {
val url = "https://jsonplaceholder.typicode.com/posts/1"
val response = get(url)
if (response.statusCode == 200) {
println("Response Body:")
println(response.text)
} else {
println("HTTP request failed with status code: ${response.statusCode}")
}
}
In this example, we import the khttp.get
function, which allows us to make a GET request. We specify the URL “https://jsonplaceholder.typicode.com/posts/1” to retrieve a sample JSON data. The response is then checked for a successful status code (200) before printing the response body.
Making HTTP POST Requests
Making an HTTP POST request with khttp is also straightforward. You can use the post
function and provide the URL and data to be sent in the request body.
Let’s make a POST request to send JSON data to a server:
import khttp.post
fun main() {
val url = "https://jsonplaceholder.typicode.com/posts"
val data = mapOf("title" to "New Post", "body" to "This is the body of the new post.", "userId" to 1)
val response = post(url, json = data)
if (response.statusCode == 201) {
println("Post created successfully!")
println("Response Body:")
println(response.text)
} else {
println("HTTP request failed with status code: ${response.statusCode}")
}
}
In this example, we use the khttp.post
function and specify the URL “https://jsonplaceholder.typicode.com/posts” to create a new post. We provide the JSON data to be sent in the request body using a Map
. The response is then checked for a successful status code (201) before printing the response body.
Handling Errors and Exceptions
It’s essential to handle errors and exceptions properly when making HTTP requests. khttp throws various exceptions, such as khttp.exceptions.HttpException
and khttp.exceptions.ConnectException
, which you should catch and handle accordingly.
Here’s an example of handling exceptions with khttp:
import khttp.get
import khttp.exceptions.HttpException
import khttp.exceptions.ConnectException
fun main() {
val url = "https://jsonplaceholder.typicode.com/posts/1000"
try {
val response = get(url)
println("Response Body:")
println(response.text)
} catch (e: HttpException) {
println("HTTP request failed with status code: ${e.response.statusCode}")
} catch (e: ConnectException) {
println("Failed to connect to the server: ${e.message}")
}
}
In this example, we attempt to make an HTTP GET request to a non-existing resource “https://jsonplaceholder.typicode.com/posts/1000”. The HttpException
will be caught and the status code of the failed response will be printed. If there is a connection error, the ConnectException
will be caught and the error message will be displayed.
Handling Response Data with khttp
In addition to making HTTP requests, khttp provides convenient methods to handle response data. Let’s explore some useful features for handling response data with khttp.
JSON Response Handling
khttp includes built-in support for handling JSON responses. When the server responds with JSON data, khttp can automatically parse the JSON and provide it as a Map<String, Any>
or a List<Any>
for easier access.
Here’s an example of handling a JSON response with khttp:
import khttp.get
fun main() {
val url = "https://jsonplaceholder.typicode.com/posts/1"
val response = get(url)
if (response.statusCode == 200) {
val post = response.jsonObject
println("Title: ${post["title"]}")
println("Body: ${post["body"]}")
} else {
println("HTTP request failed with status code: ${response.statusCode}")
}
}
In this example, we use the response.jsonObject
property to automatically parse the JSON response. We can then access the values using the keys, making it easy to work with JSON data in Kotlin.
Binary Response Handling
khttp also supports handling binary responses, such as downloading files from the server. The response.content
property provides access to the raw binary data as a ByteArray
.
Here’s an example of downloading an image file using khttp:
import khttp.get
import java.io.File
fun main() {
val url = "https://example.com/image.jpg"
val response = get(url)
if (response.statusCode == 200) {
val file = File("downloaded_image.jpg")
file.writeBytes(response.content)
println("Image downloaded successfully.")
} else {
println("HTTP request failed with status code: ${response.statusCode}")
}
}
In this example, we use the response.content
property to access the binary data of the image. We then write the binary data to a local file named “downloaded_image.jpg” using File.writeBytes()
.
Custom Headers and Query Parameters
khttp allows you to set custom headers and query parameters for your HTTP requests. This is useful when working with APIs that require authentication or specific request headers.
Here’s an example of setting custom headers and query parameters with khttp:
import khttp.get
fun main() {
val url = "https://api.example.com/data"
val headers = mapOf("Authorization" to "Bearer your_access_token", "User-Agent" to "MyApp/1.0")
val params = mapOf("page" to "1", "limit" to "10")
val response = get(url, headers = headers, params = params)
if (response.statusCode == 200) {
println("Response Body:")
println(response.text)
} else {
println("HTTP request failed with status code: ${response.statusCode}")
}
}
In this example, we use the headers
parameter to set custom headers, such as an “Authorization” header with an access token. We also use the params
parameter to set query parameters, such as “page” and “limit”. These parameters are automatically appended to the URL.
Conclusion
khttp is a versatile and straightforward HTTP client library for Kotlin that simplifies making HTTP requests and handling responses. By incorporating khttp into your Kotlin projects and utilizing its features for handling JSON, binary data, custom headers, and query parameters, you can efficiently interact with web services and APIs. With the concise and intuitive syntax of khttp, developers can focus on building robust and reliable applications that communicate seamlessly with remote resources.