My html page

Make HTTP Requests in Kotlin

These days making HTTP requests in any language is a staple of many common workflows and features. This post will go through a few of the methods in which you can make such requests in Kotlin using some of the great open source libraries available.

JDK 11+ HTTP Client API

If you are using the latest JDK release, you can make use of the new built-in HttpClient API which is now modern and fully feature complete. It supports HTTP 2.0 (header compression, server push, multiplexing etc), WebSockets and can be fully asynchronous — which integrates brilliantly with Kotlin coroutines.

In short, you create a new HttpClient and pass HttpRequest objects in (the below example is synchronous). Note that you could easily create some helper/extension functions to make this code much neater:

val client = HttpClient.newBuilder().build(); val request = HttpRequest.newBuilder() .uri(URI.create("https://something.com")) .build(); val response = client.send(request, BodyHandlers.ofString()); println(response.body()) 

The API also has support for performing completely asynchronous requests (using non-blocking IO). In this case a CompletableFuture is returned instead of the raw HttpResponse . If you are using coroutines, you can use the CompletionStage.await() extension function defined within the JDK integration library to suspend the current coroutine until the response is available. No need to deal with chaining together callbacks!

suspend fun getData(): String  // above code to construct client + request val response = client.sendAsync(request, BodyHandlers.ofString()); return response.await().body() // suspend and return String not a Future > // in some other coroutine (suspend block) val someData = getData() process(someData) // just as if you wrote it synchronously 

Fuel

Probably the most commonly used library for this requirement, Fuel is fully featured and stable for any such use case. The default settings used are also good so it requires very little/if any configuration to get up and running.

The base of the library sits on extension functions of String — which in this case represent URL . This makes the interface very fluent any easy to read.

Fuel also makes use of the Result library — written by the same creator — to bundle up error conditions and responses. This does mean another dependency to add, but it makes error handling a bit easier. The recommended method is done through a when expression:

val future = "http://httpbin.org/get".httpGet().responseString  request, response, result -> when (result)  is Result.Failure ->  val ex = result.getException() > is Result.Success ->  val data = result.get() > > > future.join() 

The underlying requests are performed on a dedicated thread pool making the library capable of both blocking and asynchronous requests.

You can also perform synchronous requests if you want. If you specify a callback the call is async , if you don’t it’s blocking .

val (request, response, result) = "http://httpbin.org/get".httpGet().responseString() // result is Result 

Take a look at the docs to find examples of how to use authentication, POST etc requests, parameters support, and timeouts etc. The API is configured in a fluent manner:

"http://httpbin.org/get".httpGet().timeout(timeout).timeoutRead(timeoutRead).responseString  request, response, result -> > 

Ktor Client

Another approach is to make use of the newer Ktor library. Although the main focus has been on the server-side area, it also includes another package to perform non-blocking requests in a similar fashion. As Ktor is based around Kotlin coroutines, this perhaps makes most sense if you are more familiar/are already using them in your project.

Ktor includes multiple client engines which can handle requests. Make sure to pick the correct one depending on your use case, as some don’t support Android, HTTP 2 or Websockets. The main being Apache , but CIO (Coroutine IO) and Jetty handlers are also available. Configuration is done through a fluent, builder-like API very similar to that used in the Ktor server packages.

val client = HttpClient(CIO)  install(Logging) install(ContentNegotiation)  jackson() > > val htmlContent = client.getString>("https://en.wikipedia.org/wiki/Main_Page") 

Note that in this case, get is a suspending function so you would have to call it within a coroutine. Using runBlocking or async are the most suitable candidates and means that, unlike Fuel , you have complete control over which thread pool is used for the requests.

fun parallelRequests() = runBlocking  val client = HttpClient(CIO) // Start two requests asynchronously. val req1: DeferredString> = async  client.get("https://127.0.0.1:8080/a").body() > val req2: DeferredString> = async  client.get("https://127.0.0.1:8080/b").body() > // Get the request contents without blocking threads, but suspending the function until both // requests are done. val res1 = req1.await() // Suspension point. val res2 = req2.await() // Suspension point. > 

The Apache engine is based on Apache HTTPComponents and supports the widest variety of config options. It is also the only engine to support redirects and HTTP/2. It will bring in apache as a dependency though. The CIO engine is more basic but has no extra dependencies.

Much like you would expect from any HTTP library, you can configure cookies, authentication, timeouts etc as needed.

Native URL

If you don’t want to use a dedicated library, don’t want to do any custom configuration, then Kotlin includes a nice extension method on the URL class to perform GET requests via opening a stream . Note that this is a blocking operation.

val response = try  URL("http://google.co.uk") .openStream() .bufferedReader() .use  it.readText() > 

Источник

Kotlin HTTP GET/POST request

Kotlin HTTP GET/POST request tutorial shows how to send a GET and a POST request in Kotlin. We use HttpClient and Fuel library.

HTTP

The is an application protocol for distributed, collaborative, hypermedia information systems. HTTP is the foundation of data communication for the World Wide Web.

In the examples, we use httpbin.org , which is a freely available HTTP request and response service, and the webcode.me , which is a tiny HTML page for testing.

HTTP GET

The HTTP GET method requests a representation of the specified resource. Requests using GET should only retrieve data.

HTTP POST

The HTTP POST method sends data to the server. It is often used when uploading a file or when submitting a completed web form.

Kotlin GET request with HttpClient

HttpClient is a tool for generating http requests in Java.

package com.zetcode import java.net.URI import java.net.http.HttpClient import java.net.http.HttpRequest import java.net.http.HttpResponse fun main() < val client = HttpClient.newBuilder().build(); val request = HttpRequest.newBuilder() .uri(URI.create("http://webcode.me")) .build(); val response = client.send(request, HttpResponse.BodyHandlers.ofString()); println(response.body()) >

We create a GET request to the webcode.me webpage.

val client = HttpClient.newBuilder().build();
val request = HttpRequest.newBuilder() .uri(URI.create("http://webcode.me")) .build();

We build a synchronous request to the webpage. The default method is GET.

val response = client.send(request, HttpResponse.BodyHandlers.ofString()); println(response.body())

We send the request, retrieve the content of the response, and print it to the console.

        

Today is a beautiful day. We go swimming and fishing.

Hello there. How are you?

GET query parameters with HttpClient

The following example appends some query parameters to the URL.

package com.zetcode import java.net.URI import java.net.URLEncoder import java.net.http.HttpClient import java.net.http.HttpRequest import java.net.http.HttpResponse fun String.utf8(): String = URLEncoder.encode(this, "UTF-8") fun main() < val params = mapOf("name" to "John Doe", "occupation" to "gardener") val urlParams = params.map <(k, v) ->"$=$"> .joinToString("&") val client = HttpClient.newBuilder().build(); val request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/get?$")) .build(); val response = client.send(request, HttpResponse.BodyHandlers.ofString()); println(response.body()) >

We create a GET request to the httpbin.org/get with some URL parameters.

fun String.utf8(): String = URLEncoder.encode(this, "UTF-8")

This is a string extension method for encoding URL paramaters.

val params = mapOf("name" to "John Doe", "occupation" to "gardener") val urlParams = params.map <(k, v) ->"$=$"> .joinToString("&")

We have a map of values. We endcode them for the URL path with the custom extension method.

val request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/get?$")) .build();

We append the parameters to the URL.

< "args": < "name": "John Doe", "occupation": "gardener" >, "headers": < "Host": "httpbin.org", "User-Agent": "Java-http-client/14.0.1", "X-Amzn-Trace-Id": "Root=1-6000269f-2389dad80db13d002a8a9003" >, . "url": "https://httpbin.org/get?name=John+Doe&occupation=gardener" >

Kotlin POST JSON data request with HttpClient

The following example sends a POST request with HttpClient. The data is sent in JSON format.

For this example, we need the jackson-module-kotlin dependency.

package com.zetcode import com.fasterxml.jackson.databind.ObjectMapper import java.net.URI import java.net.http.HttpClient import java.net.http.HttpRequest import java.net.http.HttpResponse fun main() < val values = mapOf("name" to "John Doe", "occupation" to "gardener") val objectMapper = ObjectMapper() val requestBody: String = objectMapper .writeValueAsString(values) val client = HttpClient.newBuilder().build(); val request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/post")) .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build() val response = client.send(request, HttpResponse.BodyHandlers.ofString()); println(response.body()) >

We generate a POST request to the httpbin.org/post webpage. The post data are taken from a map and transformed into a string with Jackson’s ObjectMapper.

val request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/post")) .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build()

A POST request is generated via the POST method.

[Success: < "args": <>, "data": "", "files": <>, "form": <>, "headers": < "Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2", "Content-Length": "43", "Content-Type": "application/json", "Host": "httpbin.org", "User-Agent": "Java/14.0.1", "X-Amzn-Trace-Id": "Root=1-60004591-5248fddb69a2221616147220" >, "json": < "name": "John Doe", "occupation": "gardener" >, "origin": "188.167.250.74", "url": "https://httpbin.org/post" > ]

Kotlin POST FORM data request with HttpClient

With application/x-www-form-urlencoded the data is sent in the body of the request; the keys and values are encoded in key-value tuples separated by ‘&’, with a ‘=’ between the key and the value.

package com.zetcode import java.net.URI import java.net.URLEncoder import java.net.http.HttpClient import java.net.http.HttpRequest import java.net.http.HttpResponse fun main() < val values = mapOf("name" to "John Doe", "occupation" to "gardener") val client = HttpClient.newBuilder().build(); val request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/post")) .POST(formData(values)) .header("Content-Type", "application/x-www-form-urlencoded") .build() val response = client.send(request, HttpResponse.BodyHandlers.ofString()); println(response.body()) >fun String.utf8(): String = URLEncoder.encode(this, "UTF-8") fun formData(data: Map): HttpRequest.BodyPublisher? < val res = data.map <(k, v) ->"$=$"> .joinToString("&") return HttpRequest.BodyPublishers.ofString(res) >

We generate a POST request with FORM data to httpbin.org/post .

.header("Content-Type", "application/x-www-form-urlencoded")

We set the content type header to application/x-www-form-urlencoded .

fun String.utf8(): String = URLEncoder.encode(this, "UTF-8") fun formData(data: Map): HttpRequest.BodyPublisher? < val res = data.map <(k, v) ->"$=$"> .joinToString("&") return HttpRequest.BodyPublishers.ofString(res) >

With the String.uft8 and formData helper functions, we create a body publisher with url encoded values.

< "args": <>, "data": "", "files": <>, "form": < "name": "John Doe", "occupation": "gardener" >, "headers": < "Content-Length": "33", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "Java-http-client/14.0.1", "X-Amzn-Trace-Id": "Root=1-600030bb-7c7f4d026883523b438f2e63" >, "json": null, . "url": "https://httpbin.org/post" >

Kotlin GET request with Fuel

Fuel is an easy-to-use HTTP networking library for Kotlin.

We need to add the fuel dependency.

package com.zetcode import com.github.kittinunf.fuel.httpGet fun main() < val (_, _, result) = "http://webcode.me".httpGet().responseString() println(result) >

The example sends a simple GET request to webcode.me .

GET query parameters with Fuel

The following example sends some query parameters with the GET request.

package com.zetcode import com.github.kittinunf.fuel.httpGet fun main() < val (_, _, result) = "http://httpbin.org/get" .httpGet(listOf("name" to "John Doe", "occupation" to "gardener")) .responseString() println(result) >

The Fuel library automatically takes care of encoding the parameters in httpGet .

Kotlin POST JSON data request with Fuel

We set a POST request with JSON data. This time we use the Gson library.

We have additional dependencies for the Gson library.

package com.zetcode import com.github.kittinunf.fuel.core.extensions.jsonBody import com.github.kittinunf.fuel.httpPost import com.google.gson.Gson data class User(var name: String, var occupation: String) fun main() < val user = User("John Doe", "gardener") val (_, _, result) = "https://httpbin.org/post".httpPost() .jsonBody(Gson().toJson(user).toString()) .responseString() println(result) >

We serialize the user object into a JSON string with the toJson method. We set a JSON body with the jsonBody method.

Kotlin POST FORM data request with Fuel

In the following example, we send a POST request with FORM data.

package com.zetcode import com.github.kittinunf.fuel.httpPost fun main() < val (_, _, result) = "https://httpbin.org/post" .httpPost(listOf("name" to "John Doe", "occupation" to "gardener")) .responseString() println(result) >

Fuel automatically tranforms the data to application/x-www-form-urlencoded content type in httpPost .

Источник

Читайте также:  CSS позиционирование
Оцените статью