diff --git a/core-kotlin/pom.xml b/core-kotlin/pom.xml
index 6fdc7c7c1a..88f54963ed 100644
--- a/core-kotlin/pom.xml
+++ b/core-kotlin/pom.xml
@@ -87,6 +87,26 @@
h2
${h2database.version}
+
+ com.github.kittinunf.fuel
+ fuel
+ ${fuel.version}
+
+
+ com.github.kittinunf.fuel
+ fuel-gson
+ ${fuel.version}
+
+
+ com.github.kittinunf.fuel
+ fuel-rxjava
+ ${fuel.version}
+
+
+ com.github.kittinunf.fuel
+ fuel-coroutines
+ ${fuel.version}
+
@@ -100,6 +120,7 @@
3.10.0
1.4.197
0.10.4
+ 1.15.0
-
\ No newline at end of file
+
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/fuel/Interceptors.kt b/core-kotlin/src/main/kotlin/com/baeldung/fuel/Interceptors.kt
new file mode 100644
index 0000000000..377ef979dc
--- /dev/null
+++ b/core-kotlin/src/main/kotlin/com/baeldung/fuel/Interceptors.kt
@@ -0,0 +1,11 @@
+package com.baeldung.fuel
+
+import com.github.kittinunf.fuel.core.Request
+
+fun tokenInterceptor() = {
+ next: (Request) -> Request ->
+ { req: Request ->
+ req.header(mapOf("Authorization" to "Bearer AbCdEf123456"))
+ next(req)
+ }
+}
\ No newline at end of file
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/fuel/Post.kt b/core-kotlin/src/main/kotlin/com/baeldung/fuel/Post.kt
new file mode 100644
index 0000000000..035dfe7aa0
--- /dev/null
+++ b/core-kotlin/src/main/kotlin/com/baeldung/fuel/Post.kt
@@ -0,0 +1,15 @@
+package com.baeldung.fuel
+
+import com.github.kittinunf.fuel.core.ResponseDeserializable
+import com.google.gson.Gson
+
+data class Post(var userId:Int,
+ var id:Int,
+ var title:String,
+ var body:String){
+
+
+ class Deserializer : ResponseDeserializable> {
+ override fun deserialize(content: String): Array = Gson().fromJson(content, Array::class.java)
+ }
+}
\ No newline at end of file
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/fuel/PostRoutingAPI.kt b/core-kotlin/src/main/kotlin/com/baeldung/fuel/PostRoutingAPI.kt
new file mode 100644
index 0000000000..8238c41e56
--- /dev/null
+++ b/core-kotlin/src/main/kotlin/com/baeldung/fuel/PostRoutingAPI.kt
@@ -0,0 +1,42 @@
+package com.baeldung.fuel
+
+import com.github.kittinunf.fuel.core.Method
+import com.github.kittinunf.fuel.util.FuelRouting
+
+sealed class PostRoutingAPI : FuelRouting {
+
+ override val basePath = "https://jsonplaceholder.typicode.com"
+
+ class posts(val id: String, override val body: String?): PostRoutingAPI()
+
+ class comments(val postId: String, override val body: String?): PostRoutingAPI()
+
+ override val method: Method
+ get() {
+ return when(this) {
+ is PostRoutingAPI.posts -> Method.GET
+ is PostRoutingAPI.comments -> Method.GET
+ }
+ }
+
+ override val path: String
+ get() {
+ return when(this) {
+ is PostRoutingAPI.posts -> "/posts"
+ is PostRoutingAPI.comments -> "/comments"
+ }
+ }
+
+ override val params: List>?
+ get() {
+ return when(this) {
+ is PostRoutingAPI.posts -> listOf("id" to this.id)
+ is PostRoutingAPI.comments -> listOf("postId" to this.postId)
+ }
+ }
+
+ override val headers: Map?
+ get() {
+ return null
+ }
+}
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt
index 17f5a43479..a6687b6e0a 100644
--- a/core-kotlin/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt
+++ b/core-kotlin/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt
@@ -93,6 +93,7 @@ internal class BuilderPatternUnitTest {
Assertions.assertNull(foodOrder.fish)
}
+
@Test
fun whenBuildingFoodOrderApplySettingValues_thenFieldsNotNull() {
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/fuel/FuelHttpUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/fuel/FuelHttpUnitTest.kt
new file mode 100644
index 0000000000..f0f9267618
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/fuel/FuelHttpUnitTest.kt
@@ -0,0 +1,286 @@
+package com.baeldung.fuel
+
+import awaitObjectResult
+import awaitStringResponse
+import com.github.kittinunf.fuel.Fuel
+import com.github.kittinunf.fuel.core.FuelManager
+import com.github.kittinunf.fuel.core.Request
+import com.github.kittinunf.fuel.core.interceptors.cUrlLoggingRequestInterceptor
+import com.github.kittinunf.fuel.gson.responseObject
+import com.github.kittinunf.fuel.httpGet
+import com.github.kittinunf.fuel.rx.rx_object
+import com.google.gson.Gson
+import kotlinx.coroutines.experimental.runBlocking
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Test
+import java.io.File
+import java.util.concurrent.CountDownLatch
+
+internal class FuelHttpUnitTest {
+
+ @Test
+ fun whenMakingAsyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val latch = CountDownLatch(1)
+
+ "http://httpbin.org/get".httpGet().response{
+ request, response, result ->
+
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+
+ latch.countDown()
+ }
+
+ latch.await()
+
+ }
+
+ @Test
+ fun whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val (request, response, result) = "http://httpbin.org/get".httpGet().response()
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+
+ }
+
+ @Test
+ fun whenMakingSyncHttpGetURLEncodedRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val (request, response, result) =
+ "https://jsonplaceholder.typicode.com/posts"
+ .httpGet(listOf("id" to "1")).response()
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+
+ }
+
+ @Test
+ fun whenMakingAsyncHttpPostRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val latch = CountDownLatch(1)
+
+ Fuel.post("http://httpbin.org/post").response{
+ request, response, result ->
+
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+
+ latch.countDown()
+ }
+
+ latch.await()
+
+ }
+
+ @Test
+ fun whenMakingSyncHttpPostRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val (request, response, result) = Fuel.post("http://httpbin.org/post").response()
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+ }
+
+ @Test
+ fun whenMakingSyncHttpPostRequestwithBody_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val (request, response, result) = Fuel.post("https://jsonplaceholder.typicode.com/posts")
+ .body("{ \"title\" : \"foo\",\"body\" : \"bar\",\"id\" : \"1\"}")
+ .response()
+
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(201,response.statusCode)
+ }
+
+ @Test
+ fun givenFuelInstance_whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ FuelManager.instance.basePath = "http://httpbin.org"
+ FuelManager.instance.baseHeaders = mapOf("OS" to "macOS High Sierra")
+
+ FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor())
+ FuelManager.instance.addRequestInterceptor(tokenInterceptor())
+
+
+ val (request, response, result) = "/get"
+ .httpGet().response()
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+ }
+
+ @Test
+ fun givenInterceptors_whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
+
+ FuelManager.instance.basePath = "http://httpbin.org"
+ FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor())
+ FuelManager.instance.addRequestInterceptor(tokenInterceptor())
+
+ val (request, response, result) = "/get"
+ .httpGet().response()
+ val (data, error) = result
+
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+ }
+
+ @Test
+ fun whenDownloadFile_thenCreateFileResponseNotNullAndErrorNullAndStatusCode200() {
+
+ Fuel.download("http://httpbin.org/bytes/32768").destination { response, url ->
+ File.createTempFile("temp", ".tmp")
+ }.response{
+ request, response, result ->
+
+ val (data, error) = result
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+ }
+ }
+
+ @Test
+ fun whenDownloadFilewithProgressHandler_thenCreateFileResponseNotNullAndErrorNullAndStatusCode200() {
+
+ val (request, response, result) = Fuel.download("http://httpbin.org/bytes/327680")
+ .destination { response, url -> File.createTempFile("temp", ".tmp")
+ }.progress { readBytes, totalBytes ->
+ val progress = readBytes.toFloat() / totalBytes.toFloat()
+ }.response ()
+
+ val (data, error) = result
+ Assertions.assertNull(error)
+ Assertions.assertNotNull(data)
+ Assertions.assertEquals(200,response.statusCode)
+
+
+ }
+
+ @Test
+ fun whenMakeGetRequest_thenDeserializePostwithGson() {
+
+ val latch = CountDownLatch(1)
+
+ "https://jsonplaceholder.typicode.com/posts/1".httpGet().responseObject { _,_, result ->
+ val post = result.component1()
+ Assertions.assertEquals(1, post?.userId)
+ latch.countDown()
+ }
+
+ latch.await()
+
+ }
+
+ @Test
+ fun whenMakePOSTRequest_thenSerializePostwithGson() {
+
+ val post = Post(1,1, "Lorem", "Lorem Ipse dolor sit amet")
+
+ val (request, response, result) = Fuel.post("https://jsonplaceholder.typicode.com/posts")
+ .header("Content-Type" to "application/json")
+ .body(Gson().toJson(post).toString())
+ .response()
+
+ Assertions.assertEquals(201,response.statusCode)
+
+ }
+
+ @Test
+ fun whenMakeGETRequestWithRxJava_thenDeserializePostwithGson() {
+
+ val latch = CountDownLatch(1)
+
+
+ "https://jsonplaceholder.typicode.com/posts?id=1"
+ .httpGet().rx_object(Post.Deserializer()).subscribe{
+ res, throwable ->
+
+ val post = res.component1()
+ Assertions.assertEquals(1, post?.get(0)?.userId)
+ latch.countDown()
+ }
+
+ latch.await()
+
+ }
+
+ @Test
+ fun whenMakeGETRequestUsingCoroutines_thenResponseStatusCode200() {
+
+ runBlocking {
+ val (request, response, result) = Fuel.get("http://httpbin.org/get").awaitStringResponse()
+
+ result.fold({ data ->
+ Assertions.assertEquals(200, response.statusCode)
+
+ }, { error -> })
+ }
+
+ }
+
+ @Test
+ fun whenMakeGETRequestUsingCoroutines_thenDeserializeResponse() {
+
+
+ runBlocking {
+ Fuel.get("https://jsonplaceholder.typicode.com/posts?id=1").awaitObjectResult(Post.Deserializer())
+ .fold({ data ->
+ Assertions.assertEquals(1, data.get(0).userId)
+ }, { error -> })
+ }
+
+ }
+
+ @Test
+ fun whenMakeGETPostRequestUsingRoutingAPI_thenDeserializeResponse() {
+
+ val latch = CountDownLatch(1)
+
+ Fuel.request(PostRoutingAPI.posts("1",null))
+ .responseObject(Post.Deserializer()) {
+ request, response, result ->
+ Assertions.assertEquals(1, result.component1()?.get(0)?.userId)
+ latch.countDown()
+ }
+
+ latch.await()
+ }
+
+ @Test
+ fun whenMakeGETCommentRequestUsingRoutingAPI_thenResponseStausCode200() {
+
+ val latch = CountDownLatch(1)
+
+ Fuel.request(PostRoutingAPI.comments("1",null))
+ .responseString { request, response, result ->
+ Assertions.assertEquals(200, response.statusCode)
+ latch.countDown()
+ }
+
+ latch.await()
+ }
+
+
+}
\ No newline at end of file