How to Create an HTTP Request in Kotlin

David Mbochi Njonge Feb 02, 2024
  1. Create a Kotlin Project and Add Dependencies
  2. Use Retrofit to Create an HTTP Request in Kotlin
  3. Use an API of the Java Standard Library to Create an HTTP Request in Kotlin
  4. Use the Fuel API to Create an HTTP Request in Kotlin
  5. Use the OkHttp API to Create an HTTP Request in Kotlin
  6. Conclusion
How to Create an HTTP Request in Kotlin

HTTP is a communication protocol for the web and is responsible for serving web content from a web server to the web browser.

The web content might be static data or dynamic data. Static data means that information displayed on a page does not change, while dynamic data displayed on a web page is always changing.

The data retrieved from a server include structured data, image and video files. Most applications usually work with structured data, which is managed by a database.

A common approach when fetching data from the database to the web client is using restful APIs. The restful APIs are consumed by the application using different libraries through the HTTP protocol and loaded to the web client.

In this tutorial, we will learn the different ways we can use to create an HTTP request that consumes a Restful API. The Restful API returns a list of countries from an application hosted on Heroku.

Create a Kotlin Project and Add Dependencies

Open the IntelliJ development environment and select File > New > Project. On the window that opens, enter the project name as kotlin-http-request, select Kotlin on the Language section, and select Gradle on the Build system section.

Finally, press the Create button to generate the project.

Open the file build.gradle.kts and ensure you have all the dependencies shown in the following code. These dependencies help us add the libraries we can use to create HTTP requests.

dependencies{
    implementation ("com.squareup.retrofit2:retrofit:2.9.0")
    implementation ("com.squareup.retrofit2:converter-gson:2.9.0")
    implementation ("com.github.kittinunf.fuel:fuel:2.3.1")
    implementation ("com.squareup.okhttp3:okhttp:4.10.0")
    testImplementation(kotlin("test"))
}

Use Retrofit to Create an HTTP Request in Kotlin

Retrofit is the most commonly used library when developing applications with either Kotlin or Java.

Under the kotlin folder, create a folder named model. Create a file named Country.kt and copy and paste the following code into the file.

package model

data class Country(var id: Number,
              var countryName: String);

In this code, we have created a data class that we will use to store the country objects fetched from the server. The class has fields id and countryName, which will be mapped with the fields of the objects retrieved from the server.

Under the kotlin folder, create a folder named service. Create a file named CountryService.kt and copy and paste the following code into the file.

package service

import model.Country
import retrofit2.Call
import retrofit2.http.GET

interface CountryService {
    @GET("/country/all")
    fun getAllCountries(): Call<List<Country>>;
}

In this code, we have created a GET request that maps to the relative path /country/all to fetch all countries List<Country> from the server. We always use the @GET annotation when we want to retrieve data from a server.

Note that the getAllCountries() method returns a Call which means that the method makes a request to the server and returns a response.

Create a file named CountryServiceImpl.kt and copy and paste the following code into the file.

package service

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

class CountryServiceImpl {
    fun getCountryServiceFactory(): CountryService{
        val retrofit = Retrofit.Builder()
            .baseUrl("https://countryapp254.herokuapp.com")
            .addConverterFactory(GsonConverterFactory.create())
            .build();

        return retrofit.create(CountryService::class.java);
    }
}

This class does the main work of fetching the data from the server by mapping the relative URL we provided in the getAllCountries() method with the baseUrl() provided to the builder.

The addConverterFactory() helps us to deserialize the Kotlin objects using the Gson library, which is also provided by Retrofit.

Create a Main.kt file under the kotlin folder and copy and paste the following code into the file.

import model.Country
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import service.CountryService
import service.CountryServiceImpl

fun getAllCountriesUsingRetrofit(){
    val countryService: CountryService =
        CountryServiceImpl().getCountryServiceFactory();

    val call: Call<List<Country>> = countryService.getAllCountries();

    call.enqueue(object : Callback<List<Country>> {
        override fun onResponse(call: Call<List<Country>>,
                                response: Response<List<Country>>
        ) {
            response.body()?.forEach(::println)
        }

        override fun onFailure(call: Call<List<Country>>, t: Throwable) {
            t.printStackTrace();
        }

    })
}

fun main(){
    getAllCountriesUsingRetrofit();
}

The above code verifies whether our Retrofit code is working. Invoke the getCountryServiceFactory() which returns a CountryService.

The CountryService instance helps us to call the getAllCountries() method. The method returns a Call that contains a response to our data.

To get the countries retrieved from the server, call the enqueue() method and implement the onResponse() and onFailure() methods of the CallBack.

The enqueue() method executes asynchronously, and since we are creating a console application, we only need to log the response body() to the console. Run this code and ensure the output is as shown below.

[{"id":18,"countryName":"Kenya"},
{"id":20,"countryName":"Tanzania"},
{"id":21,"countryName":"Ethiopia"},
{"id":22,"countryName":"Malawi"},
{"id":23,"countryName":"Country"},
{"id":24,"countryName":"Country"},
{"id":25,"countryName":"Kenya"},
{"id":26,"countryName":"Country"},
{"id":27,"countryName":"USA"},
{"id":28,"countryName":"USA"},
{"id":29,"countryName":"Kenya"},
{"id":30,"countryName":"Kenya"}]

Use an API of the Java Standard Library to Create an HTTP Request in Kotlin

Comment on the previous example in the Main.kt file and copy and paste the following code into the file after it.

import java.net.HttpURLConnection
import java.net.URL

fun getCountriesUsingHttpURLConnection(){
    var url = URL("https://countryapp254.herokuapp.com/country/all");

    with(url.openConnection() as HttpURLConnection){
        inputStream.bufferedReader().use {
            it.lines().forEach(::println)
        }
    }
}

fun main(){
    getCountriesUsingHttpURLConnection();
}

The URLConnection is an API of the Java standard library from the java.net package and can be used in Kotlin to make HTTP requests.

The HttpURLConnection is an instance of URLConnection, and we use it to create an HTPP connection to our server. The with() function makes a single request to the server using the established connection, executes the code inside the function, and returns our result.

The inputStream inside the function reads the data from the established connection using a bufferedReader() and the use() extension function helps us to log the data read from the server to the console. Run this code and ensure the output is as shown below.

[{"id":18,"countryName":"Kenya"},
{"id":20,"countryName":"Tanzania"},
{"id":21,"countryName":"Ethiopia"},
{"id":22,"countryName":"Malawi"},
{"id":23,"countryName":"Country"},
{"id":24,"countryName":"Country"},
{"id":25,"countryName":"Kenya"},
{"id":26,"countryName":"Country"},
{"id":27,"countryName":"USA"},
{"id":28,"countryName":"USA"},
{"id":29,"countryName":"Kenya"},
{"id":30,"countryName":"Kenya"}]

Use the Fuel API to Create an HTTP Request in Kotlin

Comment on the previous example in the Main.kt file and copy and paste the following code into the file after it.

import com.github.kittinunf.fuel.httpGet
import com.github.kittinunf.result.Result

fun getCountriesUsingFuel(){
    val request = "https://countryapp254.herokuapp.com/country/all"
        .httpGet()
        .responseString{ request, response, result ->
            when(result){
                is Result.Failure -> {
                    println(result.getException());
                }

                is Result.Success -> {
                    println(result.get())
                }
            }
        }

    request.join();
}

fun main(){
    getCountriesUsingFuel();
}

The Fuel API is another approach we can use to create HTTP requests in our applications. In this example, we have called the httpGet(), an extension function of the String class, to indicate that we are making a GET request.

The string provides the RESTful API used to fetch data from the server.

The httpGet() method returns a Request which allows us to call the responseString() method to execute the request asynchronously into a Charset.UTF-8 by passing a handler as the argument.

The handler is a lambda function that accepts three parameters of type Request, Response, and Result and returns a Unit which means it does not return any value. Since we are interested in the Result, we invoke Failure and Success which both provide a result when the application failed or succeeded, respectively.

The when() method is the same as switch in Java and helps us make different decisions when the request was successful or failed. Run this code and ensure the output is as shown below.

[{"id":18,"countryName":"Kenya"},
{"id":20,"countryName":"Tanzania"},
{"id":21,"countryName":"Ethiopia"},
{"id":22,"countryName":"Malawi"},
{"id":23,"countryName":"Country"},
{"id":24,"countryName":"Country"},
{"id":25,"countryName":"Kenya"},
{"id":26,"countryName":"Country"},
{"id":27,"countryName":"USA"},
{"id":28,"countryName":"USA"},
{"id":29,"countryName":"Kenya"},
{"id":30,"countryName":"Kenya"}]

Use the OkHttp API to Create an HTTP Request in Kotlin

Comment on the previous example in the Main.kt file and copy and paste the following code into the file after it.

import okhttp3.OkHttpClient
import okhttp3.Request

private val httpClient = OkHttpClient()

fun getCountriesUsingOkHttp() {
    val countriesRequest = Request.Builder()
        .url("https://countryapp254.herokuapp.com/country/all")
        .build();

    httpClient.newCall(countriesRequest).execute().use { countryResponse ->
        if (!countryResponse.isSuccessful) throw RuntimeException("status code $countryResponse");

        println(countryResponse.body!!.string())
    }
}

fun main(){
    getCountriesUsingOkHttp();
}

The OkHttpClient() creates a shared API instance that we can use to make HTTP requests to the server.

The shared instance is created because each client has its thread pools and connections pools, and reusing them is important to save on memory and reduce latency.

The Builder() creates a Request using the provided URL, and to prepare a request to the server, we invoke the newCall() method from the OkHttpClient() instance and pass the Request as the argument of this method.

The newCall() method returns a Call and we invoke its execute() method to get the response of the request from Response.body(). The use() extension function helps us access the response’s data and log it to the console.

Note that the use() function closes the result regardless of whether an exception was thrown or not. Run this code and ensure the output is as shown below.

[{"id":18,"countryName":"Kenya"},
{"id":20,"countryName":"Tanzania"},
{"id":21,"countryName":"Ethiopia"},
{"id":22,"countryName":"Malawi"},
{"id":23,"countryName":"Country"},
{"id":24,"countryName":"Country"},
{"id":25,"countryName":"Kenya"},
{"id":26,"countryName":"Country"},
{"id":27,"countryName":"USA"},
{"id":28,"countryName":"USA"},
{"id":29,"countryName":"Kenya"},
{"id":30,"countryName":"Kenya"}]

Conclusion

In this tutorial, we have learned different ways that we can leverage to create HTTP requests in Kotlin. The approaches we covered include using Retrofit, using an API of the Java standard library, using the Fuel API, and finally covered using the OkHttp API.

Note that these are not the only approaches we can use; there are other approaches that we can use, such as the Volley API. Feel free to use any method that is suitable for your use case.

David Mbochi Njonge avatar David Mbochi Njonge avatar

David is a back end developer with a major in computer science. He loves to solve problems using technology, learning new things, and making new friends. David is currently a technical writer who enjoys making hard concepts easier for other developers to understand and his work has been published on multiple sites.

LinkedIn GitHub