Skip to content

Instantly share code, notes, and snippets.

@dstd
Last active July 6, 2016 15:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dstd/2cbd18dccead81a470240837f55f6f2a to your computer and use it in GitHub Desktop.
Save dstd/2cbd18dccead81a470240837f55f6f2a to your computer and use it in GitHub Desktop.
@file:Suppress("UNUSED_PARAMETER", "NOTHING_TO_INLINE") // it's a stub for ConnectionInspector so just suppress the warnings
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
class ConnectionInspector(friendlyName: String?) {
inline fun preConnect(connection: HttpURLConnection, requestEntity: ByteArray?) = Unit
inline fun postConnect() = Unit
inline fun interpretResponseStream(responseStream: InputStream?): InputStream? = responseStream
inline fun httpExchangeFailed(ex: IOException) = Unit
companion object {
private var sharedInstance = ConnectionInspector(null)
fun createInstance(): ConnectionInspector = sharedInstance
}
}
import com.facebook.stetho.urlconnection.ByteArrayRequestEntity
import com.facebook.stetho.urlconnection.StethoURLConnectionManager
import com.facebook.stetho.Stetho
import <package>.<App-class>
import java.net.HttpURLConnection
class ConnectionInspector(friendlyName: String?): StethoURLConnectionManager(friendlyName) {
fun preConnect(connection: HttpURLConnection, requestBytes: ByteArray?) {
if (requestBytes != null)
super.preConnect(connection, ByteArrayRequestEntity(requestBytes))
else
super.preConnect(connection, null)
}
companion object {
private var stethoInitialized = false
fun createInstance(): ConnectionInspector {
if (!stethoInitialized) {
synchronized(stethoInitialized) {
if (!stethoInitialized) {
Stetho.initializeWithDefaults(<App-instance>);
stethoInitialized = true
}
}
}
return ConnectionInspector(null)
}
}
}
package com.github.kittinunf.fuel.toolbox
import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.core.*
import java.io.BufferedOutputStream
import java.io.IOException
import java.net.HttpURLConnection
import java.net.URLConnection
import java.util.zip.GZIPInputStream
import javax.net.ssl.HttpsURLConnection
class HttpClient : Client {
override fun executeRequest(request: Request): Response {
val response = Response()
response.url = request.url
val connectionInspector = ConnectionInspector.createInstance()
val connection = establishConnection(request) as HttpURLConnection
try {
connection.apply {
val timeout = Fuel.testConfiguration.timeout?.let { if (it == -1) Int.MAX_VALUE else it } ?: request.timeoutInMillisecond
val timeoutRead = Fuel.testConfiguration.timeoutRead?.let { if (it == -1) Int.MAX_VALUE else it } ?: request.timeoutReadInMillisecond
connectTimeout = timeout
readTimeout = timeoutRead
doInput = true
useCaches = false
requestMethod = request.httpMethod.value
connectionInspector.preConnect(connection, request.httpBody)
setDoOutput(connection, request.httpMethod)
for ((key, value) in request.httpHeaders) {
setRequestProperty(key, value)
}
setBodyIfAny(connection, request.httpBody)
}
return response.apply {
connectionInspector.postConnect()
httpResponseHeaders = connection.headerFields ?: emptyMap()
httpContentLength = connection.contentLength.toLong()
val contentEncoding = connection.contentEncoding ?: ""
val dataStreamOriginal = if (connection.errorStream != null) {
connection.errorStream
} else {
try {
connection.inputStream
} catch(exception: IOException) {
null
}
}
val dataStream = connectionInspector.interpretResponseStream(dataStreamOriginal)
if (dataStream != null) {
data = if (contentEncoding.compareTo("gzip", true) == 0) {
GZIPInputStream(dataStream).readBytes()
} else {
dataStream.readBytes()
}
}
//try - catch just in case both methods throw
try {
httpStatusCode = connection.responseCode
httpResponseMessage = connection.responseMessage
} catch(exception: IOException) {
throw exception
}
}
} catch(exception: Exception) {
if (exception is IOException)
connectionInspector.httpExchangeFailed(exception)
throw FuelError().apply {
this.exception = exception
this.errorData = response.data
this.response = response
}
} finally {
connection.disconnect()
}
}
private fun establishConnection(request: Request): URLConnection {
return if (request.url.protocol.equals("https")) {
val conn = request.url.openConnection() as HttpsURLConnection
conn.apply {
sslSocketFactory = request.socketFactory
hostnameVerifier = request.hostnameVerifier
}
} else {
request.url.openConnection() as HttpURLConnection
}
}
private fun setBodyIfAny(connection: HttpURLConnection, bytes: ByteArray) {
if (bytes.size != 0) {
val outStream = BufferedOutputStream(connection.outputStream)
outStream.write(bytes)
outStream.close()
}
}
private fun setDoOutput(connection: HttpURLConnection, method: Method) {
when (method) {
Method.GET, Method.DELETE, Method.HEAD -> connection.doOutput = false
Method.POST, Method.PUT, Method.PATCH -> connection.doOutput = true
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment