Kotlin Retrofit ignore https certifcate - kotlin

Kotlin Retrofit ignore https certifcate.
I tried this Android ignore self signed certificate and converted to Kotlin. Its not working.
How can i ignore https (SSL) certificate.
My OkHttp is
import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
object OwnRetrofitClient {
private val authInterceptor = Interceptor { chain ->
val newUrl = chain.request().url
.newBuilder()
.build()
val newRequest = chain.request()
.newBuilder()
.addHeader("Authorization", "bearer " + AppPreferences.token)
.url(newUrl)
.build()
chain.proceed(newRequest)
}
private val client =
OkHttpClient().newBuilder()
.addInterceptor(authInterceptor)
.connectTimeout(120, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS)
.writeTimeout(90, TimeUnit.SECONDS)
.build()
private fun retrofit(baseUrl: String = "https:some.com/api") =
Retrofit.Builder()
.client(client)
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build()
fun apiService(): ApiService {
return retrofit().create(ApiService::class.java)
}
}```

The example you refer to, uses java built-in HttpsUrlConnection. In okhttp, you need to add the X509TrustManager, the HostnameVerifier and the SSLSocketFactory to OkHttpClient.Builder (see https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/ssl-socket-factory/)

Related

Kotlin Ktor client 403 forbidden cloudflare

So im trying to request a side with proxies that is protected with cloudflare. The problem is i get 403 forbidden cloduflare error but only when im using proxies without it works. But the proxies are not the problem i tried them with python(requests module) and in my browser there i dont get blocked. My code
suspend fun scrape() {
val client = HttpClient {
followRedirects = true
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
})
}
engine {
proxy =
ProxyBuilder.http("http://ProxyIP:proxyPort")
}
defaultRequest {
val credentials = Base64.getEncoder().encodeToString("ProxyUser:ProxyPassword".toByteArray())
header(HttpHeaders.ProxyAuthorization, "Basic $credentials")
}
}
val response = client.get("http://example.com")
val body = response.bodyAsText()
println(body)
println(response.status.hashCode())
Fixxed it
suspend fun scrape() {
val client = HttpClient(Apache) {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
})
}
engine {
followRedirects = false
customizeClient {
setProxy(HttpHost("hostname", port))
val credentialsProvider = BasicCredentialsProvider()
credentialsProvider .setCredentials(
AuthScope("hostname", port),
UsernamePasswordCredentials("username", "password")
)
setDefaultCredentialsProvider(credentialsProvider )
}
}
}
val response =
client.get("http://example.com") {
}
val body = response.bodyAsText()
println(body)
println(response.status.hashCode())
}
There is a problem with making a request through a proxy server using the CIO engine. I've created an issue to address this problem. As a workaround, please use the OkHttp engine instead of CIO.
Here is how you can use a proxy with the Basic authentication:
import io.ktor.client.*
import io.ktor.client.engine.okhttp.*
import io.ktor.client.request.*
import kotlinx.coroutines.runBlocking
import okhttp3.Authenticator
import okhttp3.Credentials
import okhttp3.OkHttpClient
import java.net.Proxy
fun main(): Unit = runBlocking {
val proxyAuthenticator = Authenticator { _, response ->
response.request.newBuilder()
.header("Proxy-Authorization", Credentials.basic("<username>", "<password>"))
.build()
}
val client = HttpClient(OkHttp) {
engine {
preconfigured = OkHttpClient.Builder()
.proxy(Proxy(Proxy.Type.HTTP, java.net.InetSocketAddress("127.0.0.1", 3128)))
.proxyAuthenticator(proxyAuthenticator)
.build()
}
}
val response = client.get("http://eu.kith.com/products.json")
println(response.status)
}

Okhttp interceptor not working showing 401(Unauthenticated) response

OKHTTP Interceptor not working It gives me 401 Response(Unauthenticated/UnAuthorized)
Here is my Interceptor Class
InterceptorClass
class NetworkInterceptor(context: Context) : Interceptor {
private val applicationContext = context.applicationContext
private val sharedPreferenceData = SharedPreferenceData(applicationContext)
override fun intercept(chain: Interceptor.Chain): Response {
if (!isConnectionAvailable()) {
throw NoConnectionException("Error! Connecting to the network")
} else {
val requestBuilder = chain.request().newBuilder()
val token = sharedPreferenceData.getString("token", "")
requestBuilder.addHeader("Authorization", "Bearer $token")
Log.e("Token", "intercept: $token")
return chain.proceed(requestBuilder.build())
}
}
#Suppress("DEPRECATION")
fun isConnectionAvailable(): Boolean {
val cm =
applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
cm.activeNetworkInfo.also {
return it != null && it.isConnected
}
}
}
Here is the network instance class
object NetworkInstance {
fun getApi(context: Context): DataApi {
val gsonBuilder = GsonBuilder()
gsonBuilder.setLenient()
val gson = gsonBuilder.create()
val logging = HttpLoggingInterceptor()
logging.setLevel(HttpLoggingInterceptor.Level.BODY)
val client = OkHttpClient
.Builder()
.addInterceptor(logging)
.addInterceptor(NetworkInterceptor(context))
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.addInterceptor(logging)
.build()
val retrofit = Retrofit
.Builder()
.client(client)
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
return retrofit.create(DataApi::class.java)
}
}
The issue was because of my Stupidity. I have added BASE_URL inside build.gradle which generates a Static Final variable inside BuildCondig.java which can't be altered. While Adding header BASE_URL can't be changed.

okhttp3:okhttp:4.4.0: Can't set timeout for GET method: Val cannot be reassigned

Kotlin project
in build.gradle
implementation 'com.squareup.okhttp3:okhttp:4.4.0'
By default timeout is 10 sec. I want to change to 30 sec.
I try this:
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
val requestToc = Request.Builder()
.url(loginURL)
.get()
.build()
val httpClient = OkHttpClient()
httpClient.connectTimeoutMillis = 30000; // error here
val loginResponse: Response = httpClient.newCall(requestToc).execute()
But I get compile error:
Val cannot be reassigned
This also not working:
val requestTocan = Request.Builder()
.connectTimeout(30, TimeUnit.SECONDS) // error here
.url(loginTocanRequestURL)
.get()
.build()
I get error:
Unresolved reference: connectTimeout
val httpClient = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.build()
val httpClient = OkHttpClient()
httpClient.connectTimeoutMillis = 30000; // error here
To resolve val cannot be assigned issue just change val to var since val cannot be assigned a value.
And try doing this:
try {
val builder = OkHttpClient.Builder()
builder.connectTimeout(30, TimeUnit.SECONDS)
builder.readTimeout(30, TimeUnit.SECONDS)
builder.build()
} catch (e: Exception) {
throw RuntimeException(e)
}
I found solution:
private const val CONNECTION_TIMEOUT_SEC = 30L
val requestToc = Request.Builder()
.url(loginTocanRequestURL)
.get()
.build()
val loginTocResponse = OkHttpClient().newBuilder()
.connectTimeout(CONNECTION_TIMEOUT_SEC, TimeUnit.SECONDS)
.readTimeout(CONNECTION_TIMEOUT_SEC, TimeUnit.SECONDS)
.build().newCall(requestToc).execute()

How to add Api_KEY into interceptor using okhttp

I have this service where I want to put the token as an interception in the okhttp instead of passing as a parameter with #Header("MY_API_KEY")
This is my code regarding the service
/**
* Provides the [PHService]
*/
fun provideService(): PHService {
val logger = HttpLoggingInterceptor()
logger.level = HttpLoggingInterceptor.Level.BASIC
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(BuildConfig.API_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(PHService::class.java)
}
How can I add an interceptor for header authorization in here?
add like this
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", "MY_API_KEY"); // <-- this is the important line
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
httpClient.connectTimeout(30, TimeUnit.SECONDS);
httpClient.readTimeout(30, TimeUnit.SECONDS);
httpClient.addNetworkInterceptor(logging);
OkHttpClient client = httpClient.build();
in kotlin its like
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
val httpClient = OkHttpClient.Builder()
httpClient.addInterceptor { chain ->
val original = chain.request()
// Request customization: add request headers
val requestBuilder = original.newBuilder()
.header("Authorization", "MY_API_KEY") // <-- this is the important line
val request = requestBuilder.build()
chain.proceed(request)
}
httpClient.connectTimeout(30, TimeUnit.SECONDS)
httpClient.readTimeout(30, TimeUnit.SECONDS)
httpClient.addNetworkInterceptor(logging)
val okHttpClient=httpClient.build()
In case you wish to add an api_key and an app_id in your requests as a query parameter using retrofit and OkHttp interceptors in kotlin. You can follow the following steps. This is useful so you dont have to pass the keys in every request in each query:
const val E_BASE_URL = "https://api.example.com"
const val API_ID = "YourApiID"
const val API_KEY = "YourApiKey"
//Here you add your url interceptor
//"app_id" and "app_key" might be different, depending on your API
val api_interceptor = Interceptor {
val originalRequest = it.request()
val newHttpUrl = originalRequest.url.newBuilder()
.addQueryParameter("app_id", API_ID)
.addQueryParameter("app_key", API_KEY)
.build()
val newRequest = originalRequest.newBuilder()
.url(newHttpUrl)
.build()
it.proceed(newRequest)
}
//Add the logger interceptor optional:
val logger = HttpLoggingInterceptor().apply { setLevel(HttpLoggingInterceptor.Level.BASIC) }
//Build your OkHttpClient - here you add the api_interceptor and logger
val clientHTTP = OkHttpClient().newBuilder()
.addNetworkInterceptor(logger) //optional
.addNetworkInterceptor(api_interceptor)
.build()
//Build your json converter - in this example MOSHI
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
//FINALLY build your retrofit
val retrofitE = Retrofit.Builder()
.client(clientHTTP)
.baseUrl(E_BASE_URL)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
//You can now declare your interfaces with your REST methods as usual, for example GET which will return your object
interface RecipesService {
#GET("search")
suspend fun getRecipes(
#Query("q") recipe: String,
): RecipeResponse
}
//Finally you create your object (Singleton in Java) which generates your service via lazy delegate
object RecipesAPI {
val retrofitService: RecipesService by lazy {
retrofitE.create(RecipesService::class.java)
}
}
For this example, you need to import following dependencies in the latest version:
com.squareup.retrofit2:retrofit
com.squareup.moshi:moshi-kotlin
com.squareup.retrofit2:converter-moshi
com.squareup.okhttp3:logging-interceptor

Retrofit does not cache my response

I have tried through almost every videos, articles and stackoverflow answer but I am not being able to cache the response in Retrofit.
I have retrofit setup is like this :
private val gson = GsonBuilder()
.setLenient()
.create()!!
private val CACHE_CONTROL = "Cache-Control"
private var cacheSize: Long = 10 * 1024 * 1024 // 10 MB
private var cache = Cache(File(applicationContext.cacheDir, "http-cache"), cacheSize)
private val offlineCacheInterceptor = Interceptor { chain ->
var request = chain.request()
Log.i("datatest", "Internet is availiable : ${isOnline(applicationContext)}")
if (!isOnline(applicationContext)) {
val cacheControl = CacheControl.Builder()
.maxStale(7, TimeUnit.DAYS)
.build()
request = request.newBuilder()
.cacheControl(cacheControl)
.build()
}
chain.proceed(request)
}
private val networkInterceptor = Interceptor { chain ->
val response = chain.proceed(chain.request())
val cacheControl = CacheControl.Builder()
.maxAge(2, TimeUnit.MINUTES)
.build()
response.newBuilder()
.header(CACHE_CONTROL, cacheControl.toString())
.build()
}
private val httpClient = OkHttpClient.Builder()
.addInterceptor(offlineCacheInterceptor)
.addNetworkInterceptor(networkInterceptor)
.cache(cache)
.build()
private val retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
But when I try to call the retrofit APIs with my phone in Airplane mode
I get the following error :
Unable to resolve host "my_url": No address associated with hostname
What am I doing wrong in the cache setup?
I think there is a stupid mistake I have done but haven't seen by myself.