Skip to content

Commit

Permalink
[fuel-core] Integate Stetho (kittinunf#571)
Browse files Browse the repository at this point in the history
* Integate Stetho

* Added DefaultHook for no-op
  • Loading branch information
iNoles authored and SleeplessByte committed Jan 14, 2019
1 parent 8b5553a commit a2c22d3
Show file tree
Hide file tree
Showing 18 changed files with 171 additions and 6 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ allprojects {
}
}

val androidModules = listOf("fuel-android", "fuel-livedata")
val androidModules = listOf("fuel-android", "fuel-livedata", "fuel-stetho")
val androidSampleModules = listOf("sample")

subprojects {
Expand Down
10 changes: 10 additions & 0 deletions buildSrc/src/main/kotlin/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,13 @@ object Release {
const val plugin = "com.jfrog.bintray"
}
}

object Stetho {
const val version = "1.5.0"
const val plugin = "com.facebook.stetho:stetho:$version"

object StethoUrlConnection {
const val version = "1.5.0"
const val plugin = "com.facebook.stetho:stetho-urlconnection:$version"
}
}
1 change: 1 addition & 0 deletions fuel-stetho/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
6 changes: 6 additions & 0 deletions fuel-stetho/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dependencies {
api(project(":fuel"))
implementation(Kotlin.stdlib)
implementation(Stetho.plugin)
implementation(Stetho.StethoUrlConnection.plugin)
}
21 changes: 21 additions & 0 deletions fuel-stetho/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
2 changes: 2 additions & 0 deletions fuel-stetho/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.kittinunf.fuel.stetho" />
28 changes: 28 additions & 0 deletions fuel-stetho/src/main/java/com/kittinunf/fuel/stetho/StethoHook.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.github.kittinunf.fuel.stetho

import com.facebook.stetho.urlconnection.ByteArrayRequestEntity
import com.facebook.stetho.urlconnection.StethoURLConnectionManager
import com.github.kittinunf.fuel.core.Request
import com.github.kittinunf.fuel.core.Client
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection

class StethoHook(val friendlyName: String = "StethoFuelConnectionManager") : Client.Hook {
val stetho = StethoURLConnectionManager(friendlyName)

override fun preConnect(connection: HttpURLConnection, request: Request) {
stetho.preConnect(connection, ByteArrayRequestEntity(request.body.toByteArray()))
}

override fun interpretResponseStream(inputStream: InputStream): InputStream =
stetho.interpretResponseStream(inputStream)

override fun postConnect() {
stetho.postConnect()
}

override fun httpExchangeFailed(exception: IOException) {
stetho.httpExchangeFailed(exception)
}
}
3 changes: 3 additions & 0 deletions fuel-stetho/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">fuel-stetho</string>
</resources>
11 changes: 11 additions & 0 deletions fuel/src/main/kotlin/com/github/kittinunf/fuel/core/Client.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
package com.github.kittinunf.fuel.core

import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection

interface Client {
fun executeRequest(request: Request): Response
suspend fun awaitRequest(request: Request): Response = executeRequest(request)

interface Hook {
fun preConnect(connection: HttpURLConnection, request: Request)
fun interpretResponseStream(inputStream: InputStream): InputStream
fun postConnect()
fun httpExchangeFailed(exception: IOException)
}
}
21 changes: 21 additions & 0 deletions fuel/src/main/kotlin/com/github/kittinunf/fuel/core/DefaultHook.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.github.kittinunf.fuel.core

import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection

internal class DefaultHook : Client.Hook {
override fun preConnect(connection: HttpURLConnection, request: Request) {
// no-op
}

override fun interpretResponseStream(inputStream: InputStream): InputStream = inputStream

override fun postConnect() {
// no-op
}

override fun httpExchangeFailed(exception: IOException) {
// no-op
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.kittinunf.fuel.core

import com.github.kittinunf.fuel.core.Client.Hook
import com.github.kittinunf.fuel.core.RequestFactory.PathStringConvertible
import com.github.kittinunf.fuel.core.RequestFactory.RequestConvertible
import com.github.kittinunf.fuel.core.interceptors.ParameterEncoder
Expand Down Expand Up @@ -27,12 +28,13 @@ typealias FoldableResponseInterceptor = (ResponseTransformer) -> ResponseTransfo

class FuelManager : RequestFactory, RequestFactory.Convenience {

var client: Client by readWriteLazy { HttpClient(proxy) }
var client: Client by readWriteLazy { HttpClient(proxy, hook = hook) }
var proxy: Proxy? = null
var basePath: String? = null
var timeoutInMillisecond: Int = 15_000
var timeoutReadInMillisecond: Int = timeoutInMillisecond
var progressBufferSize: Int = DEFAULT_BUFFER_SIZE
var hook: Hook = DefaultHook()

var baseHeaders: Map<String, String>? = null
var baseParams: Parameters = emptyList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import kotlin.math.max

internal class HttpClient(
class HttpClient(
private val proxy: Proxy? = null,
var useHttpCache: Boolean = true,
var decodeContent: Boolean = true
var decodeContent: Boolean = true,
var hook: Client.Hook
) : Client {
override fun executeRequest(request: Request): Response {
return try {
Expand Down Expand Up @@ -115,6 +116,7 @@ internal class HttpClient(
setRequestProperty("X-HTTP-Method-Override", Method.PATCH.value)
}

hook.preConnect(connection, request)
setDoOutput(connection, request.method)
setBodyIfDoOutput(connection, request)
}
Expand All @@ -124,6 +126,8 @@ internal class HttpClient(
private fun retrieveResponse(request: Request, connection: HttpURLConnection): Response {
ensureRequestActive(request, connection)

hook.postConnect()

val headers = Headers.from(connection.headerFields)
val transferEncoding = headers[Headers.TRANSFER_ENCODING].flatMap { it.split(',') }.map { it.trim() }
val contentEncoding = headers[Headers.CONTENT_ENCODING].lastOrNull()
Expand Down Expand Up @@ -196,13 +200,16 @@ internal class HttpClient(
private fun dataStream(connection: HttpURLConnection): InputStream? {
return try {
try {
BufferedInputStream(connection.inputStream)
val inputStream = hook.interpretResponseStream(connection.inputStream)
BufferedInputStream(inputStream)
} catch (_: IOException) {
// The InputStream SHOULD be closed, but just in case the backing implementation is faulty, this ensures
// the InputStream ís actually always closed.
try { connection.inputStream?.close() } catch (_: IOException) {}

connection.errorStream?.let { BufferedInputStream(it) }
connection.errorStream?.let {
BufferedInputStream(hook.interpretResponseStream(it))
}
} finally {
// We want the stream to live. Closing the stream is handled by Deserialize
}
Expand All @@ -211,6 +218,8 @@ internal class HttpClient(
// ErrorStream ís actually always closed.
try { connection.errorStream?.close() } catch (_: IOException) {}

hook.httpExchangeFailed(exception)

ByteArrayInputStream(exception.message?.toByteArray() ?: ByteArray(0))
} finally {
// We want the stream to live. Closing the stream is handled by Deserialize
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.github.kittinunf.fuel.toolbox

import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.core.Client
import com.github.kittinunf.fuel.core.Headers
import com.github.kittinunf.fuel.core.Method
import com.github.kittinunf.fuel.core.Request
import com.github.kittinunf.fuel.test.MockHttpTestCase
import com.github.kittinunf.fuel.test.MockReflected
import org.hamcrest.CoreMatchers.equalTo
Expand All @@ -14,9 +16,28 @@ import org.hamcrest.MatcherAssert.assertThat
import org.junit.Test
import org.mockserver.matchers.Times
import org.mockserver.model.Header.header
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection

class HttpClientTest : MockHttpTestCase() {

class TestHook : Client.Hook {
override fun preConnect(connection: HttpURLConnection, request: Request) {
// no-op
}

override fun interpretResponseStream(inputStream: InputStream): InputStream = inputStream

override fun postConnect() {
// no-op
}

override fun httpExchangeFailed(exception: IOException) {
// no-op
}
}

@Test
fun httpClientIsTheDefaultClient() {
val request = Fuel.request(Method.GET, mock.path("default-client"))
Expand Down Expand Up @@ -151,4 +172,16 @@ class HttpClientTest : MockHttpTestCase() {
assertThat("Expected data, actual error $error2", data2, notNullValue())
assertThat(data2, equalTo("fresh"))
}

@Test
fun changeClientHook() {

val request = Fuel.request(Method.GET, mock.path("change-hook")).apply {
val httpClient = executionOptions.client as HttpClient
httpClient.hook = TestHook()
}

val client = request.executionOptions.client as HttpClient
assertThat(client.hook, instanceOf(TestHook::class.java))
}
}
3 changes: 3 additions & 0 deletions sample/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ dependencies {
implementation(AndroidX.appCompat)
implementation(KotlinX.Coroutines.android)
implementation(RxJava.Android.dependency)
implementation(Stetho.plugin)
implementation(Stetho.StethoUrlConnection.plugin)

api(project(":fuel-rxjava"))
api(project(":fuel-android"))
api(project(":fuel-livedata"))
api(project(":fuel-gson"))
api(project(":fuel-coroutines"))
api(project(":fuel-stetho"))

androidTestImplementation(AndroidX.annotation)
androidTestImplementation(AndroidX.Test.junit)
Expand Down
1 change: 1 addition & 0 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<application
android:name=".SampleApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down
2 changes: 2 additions & 0 deletions sample/src/main/kotlin/com/example/fuel/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.github.kittinunf.fuel.httpPost
import com.github.kittinunf.fuel.httpPut
import com.github.kittinunf.fuel.livedata.liveDataObject
import com.github.kittinunf.fuel.rx.rxObject
import com.github.kittinunf.fuel.stetho.StethoHook
import com.github.kittinunf.result.Result
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
Expand Down Expand Up @@ -47,6 +48,7 @@ class MainActivity : AppCompatActivity() {
basePath = "http://httpbin.org"
baseHeaders = mapOf("Device" to "Android")
baseParams = listOf("key" to "value")
hook = StethoHook("Fuel Sample App")
// addResponseInterceptor { loggingResponseInterceptor() }
}

Expand Down
11 changes: 11 additions & 0 deletions sample/src/main/kotlin/com/example/fuel/SampleApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.fuel

import android.app.Application
import com.facebook.stetho.Stetho

class SampleApplication : Application() {
override fun onCreate() {
super.onCreate()
Stetho.initializeWithDefaults(this)
}
}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ include(":fuel-kotlinx-serialization")
include(":fuel-moshi")
include(":fuel-test")
include(":fuel-json")
include(":fuel-stetho")

val includeSample: String by settings
if (includeSample == "true") {
Expand Down

0 comments on commit a2c22d3

Please sign in to comment.