I'm using Retrofit to do a basic POST request, and I'm providing a basic @Body for the request.
@POST("/rest/v1/auth/login")
LoginResponse login(@Body LoginRequest loginRequest);
When I'm building the interface for Retrofit I'm providing my own custom OkHttpClient, and all that I'm doing to it is adding my own custom authentication:
@Provides
@Singleton
public Client providesClient() {
OkHttpClient httpClient = new OkHttpClient();
httpClient.setAuthenticator(new OkAuthenticator() {
@Override
public Credential authenticate(Proxy proxy, URL url, List<Challenge> challenges) throws IOException {
return getCredential();
}
@Override
public Credential authenticateProxy(Proxy proxy, URL url, List<Challenge> challenges) throws IOException {
return getCredential();
}
});
return new OkClient(httpClient);
}
This works great when I'm sending requests directly with OKHttp, and other GET requests with retrofit but when I use retrofit to do a POST request I get the following error:
Caused by: java.net.HttpRetryException: Cannot retry streamed HTTP body
at com.squareup.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:324)
at com.squareup.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:508)
at com.squareup.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:136)
at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:94)
at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:49)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:357)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:282)
at $Proxy3.login(Native Method)
at com.audax.paths.job.LoginJob.onRunInBackground(LoginJob.java:41)
at com.audax.library.job.AXJob.onRun(AXJob.java:25)
at com.path.android.jobqueue.BaseJob.safeRun(BaseJob.java:108)
at com.path.android.jobqueue.JobHolder.safeRun(JobHolder.java:60)
at com.path.android.jobqueue.executor.JobConsumerExecutor$JobConsumer.run(JobConsumerExecutor.java:172)
at java.lang.Thread.run(Thread.java:841)
I've played around with it. If I remove the authentication, and point to a server that doesn't require the authentication, then it works fine.
Not sure how to get around this. Any help would be wonderful.
Your best bet is to provide your credentials to Retrofit via a RequestInterceptor instead of OkHttp's OkAuthenticator
. That interface works best when the request can be retried, but in your case we've already thrown out the post body by the time we find out that's necessary.
You can continue to use OkAuthenticator's Credential class which can encode your username and password in the required format. The header name you want is Authorization
.