Reputation: 1146
I'm using retrofit for my network layer I'm facing a strange issue I've the parameter and it's value look like this
store://0TxIGQMQbObzvU4Apia0V0&callback=
and after encoding it changes to this
store://0TxIGQMQbObzvU4Apia0V0%26callback%3D
and for some reason server is not liking this encoding and I'm getting "HTTP 400 Bad Request".
If I hit without encoding it runs fine so I was wondering is there is any way i can disable the endoing.
I've tried other ways like this
@Query(value "env" encoded = false) String env
but no luck.
This is my network interface class
public interface NetworkService
{
@GET("v1/public/yql")
Observable<SeriesEntity> getOnGoingSeries(@Query("q") String query,
@Query("format") String format,
@Query("diagnostics") boolean flag,
@Query("env") String env);
class Factory {
public static NetworkService create()
{
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
clientBuilder.addInterceptor(loggingInterceptor);
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://query.yahooapis.com")
.client(clientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
return retrofit.create(NetworkService.class);
}
}
}
Edit :
I also notice that the issue is only the encoded value of '&' because if i replace it value (whic is %26) it works fine
Upvotes: 15
Views: 14067
Reputation: 8674
My problem was that I had a query param that was getting encoded. The only solution that worked for me was adding an interceptor that decodes the URL as shown below:
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import java.nio.charset.StandardCharsets
import javax.inject.Singleton
@Singleton
internal object UrlDecoderInterceptor: Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val original: Request = chain.request()
var url: String = original.url.toString()
url = java.net.URLDecoder.decode(url, StandardCharsets.UTF_8.name())
val requestBuilder: Request.Builder = original.newBuilder().url(url)
val request: Request = requestBuilder.build()
return chain.proceed(request)
}
}
You can use this interceptor while creating the okhttp object as shown below:
val interceptClient = okHttpClient.newBuilder()
.addInterceptor(UrlDecoderInterceptor)
.build()
And creating a retrofit builder with this okhttp instance:
Retrofit.Builder().client(interceptClient)
.baseUrl("https://example.net")
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
Works like a charm.
Upvotes: 1
Reputation: 179
The URL is:
https://api.themoviedb.org/3/discover/movie?api_key={"PUTAPIKEYHERE!!!}&with_genres=28
I was getting:
https://api.themoviedb.org/3/discover/movie?api_key={"PUTAPIKEYHERE!!!}&with_genres%3D=28
fun getClient(codeForActionOrComedy:Int): MovieDbInterfaceToGetMovies {
val requestToApiInterceptor=Interceptor { chain ->
val url =chain.request()
.url()
.newBuilder()
// ALONE_API is just the "PUTAPIKEYHERE!!!"
.addQueryParameter("api_key","PUTAPIKEYHERE!!!")
//codeForActionOrComedy is an Int
.addQueryParameter("with_genres","$codeForActionOrComedy")
.build()
val request =chain.request()
.newBuilder()
.url(url.toString().replace("%3D","="))
.build()
return@Interceptor chain.proceed(request)
}
val okHttpClient= OkHttpClient.Builder()
.addInterceptor(requestToApiInterceptor)
.connectTimeout(60, TimeUnit.SECONDS)
.build()
val httpUrl = Retrofit.Builder()
.client(okHttpClient)
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(MovieDbInterfaceToGetMovies::class.java)
return httpUrl
}
Upvotes: 0
Reputation: 247
Please Use encoded = true
@Query(value = "email", encoded = true)
@HTTP(method = "DELETE", path = ApiConstant.DELETE_CONTACT_INFO, hasBody = true)
Observable deleteContactInfo( @Query(value = "email", encoded = true) String email);
Upvotes: 22
Reputation: 348
better solution from Github issue 1199 , we can have custom interceptor is one way to solve this issue. and this solution work for me.
from your case i want to replace %26 with = in url.
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String string = request.url().toString();
string = string.replace("%26", "=");
Request newRequest = new Request.Builder()
.url(string)
.build();
return chain.proceed(newRequest);
}
});
Upvotes: 3
Reputation: 10350
the issue I believe is that you're including callback
param as part of env
one. Try adding @Query("callback") boolean callback
to your retrofit interface (and using just store://0TxIGQMQbObzvU4Apia0V0
for env
)
Upvotes: 2