In retrofit I am sending XML in request and in response server will send XML in response. I am using proxy to consume that API. But I am always getting - HTTP FAILED: java.io.IOException: unexpected end of stream on null. I have tried solutions mentioned in stackoverflow but nothing worked. Below code is for retrofit client -
fun getRetrofitClient(context: Context): RestAPI {
if (mRetrofitClient == null) {
val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
val cert: InputStream = context.getResources().openRawResource(R.raw.mycert)
val ca: Certificate
ca = try {
cf.generateCertificate(cert)
} finally {
cert.close()
}
val keyStoreType: String = KeyStore.getDefaultType()
val keyStore: KeyStore = KeyStore.getInstance(keyStoreType)
keyStore.load(null, null)
keyStore.setCertificateEntry("ca", ca)
val proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("xxxx.xx.xx.xx",xxxx ))
val tmfAlgorithm: String = TrustManagerFactory.getDefaultAlgorithm()
val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm)
tmf.init(keyStore)
val sslContext: SSLContext = SSLContext.getInstance("TLSv1.2")
sslContext.init(null, tmf.getTrustManagers(), null)
val spec = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA
)
.build()
val httpClient = OkHttpClient.Builder()
.followRedirects(true)
.followSslRedirects(true)
.connectTimeout(10, TimeUnit.MINUTES)
.readTimeout(10, TimeUnit.MINUTES)
.writeTimeout(10, TimeUnit.MINUTES)
.sslSocketFactory(socketFactory)
.socketFactory(socketFactory)
.hostnameVerifier(getHostnameVerifier())
.retryOnConnectionFailure(true)
.proxy(proxy)
.connectionSpecs(Collections.singletonList(spec))
val retrofit = Retrofit.Builder()
.baseUrl("https://xxx.xx.xx.xx:xxxx/xx/")
.addConverterFactory(SimpleXmlConverterFactory.create())
.client(httpClient.build())
.build()
mRetrofitClient = retrofit.create(RestAPI::class.java!!)
}
return mRetrofitClient!!
}
fun getHostnameVerifier(): HostnameVerifier? {
return object : HostnameVerifier {
override fun verify(hostname: String?, session: SSLSession?): Boolean {
return true
}
}
}
Below code is for Rest API -
interface RestAPI {
@Headers("Content-Type: text/xml","Connection: keep-alive","Transfer-Encoding: chunked","Cache-Control: no-cache","Accept: */*","Host: xxx.xx.xx.xx:xxxx","Accept-Encoding: gzip, deflate, br")
@POST("BillQuery/V1.0")
abstract fun billQuery(@Body input:String): Call<String>
}
I tried volley also, same issue. But it's working fine in Postman. I have added header like postman. Still it doesn't work.
Please help.
unexpected end of stream
can be thrown by okhttp if the Response-Headers cannot be parsed or if the length in the Response-Header Content-Length
doesn't match with the actual length of the response body (see HTTP FAILED: java.io.IOException: unexpected end of stream exception while making https request).
In your case, okhttp wants to send a unencrypted connect to the HTTP-proxy and fails at this step to parse the Reponse-Headers from the proxy-response i guess. The proxy gives okhttp an invalid answer. Could you try with postman to connect to the proxy through HTTP?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With