如何在 Retrofit 中避免 URL 编码?

How to avoid URL encoding in Retrofit?

我正在对我的网络层进行改造我遇到了一个奇怪的问题我有参数,它的值看起来像这样

store://0TxIGQMQbObzvU4Apia0V0&callback=

编码后变成这样

store://0TxIGQMQbObzvU4Apia0V0%26callback%3D

并且出于某种原因服务器不喜欢这种编码,我得到 "HTTP 400 Bad Request"。

如果我在没有编码的情况下点击它运行正常,所以我想知道有什么方法可以禁用 endoing。

我试过其他类似的方法

@Query(value "env" encoded = false) String env

但运气不好。

这是我的网络接口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);
        }
    }
}

编辑:

我还注意到问题只是“&”的编码值,因为如果我替换它的值(即 %26)它工作正常

我认为问题是您将 callback 参数作为 env 参数的一部分。尝试将 @Query("callback") boolean callback 添加到您的改造界面(并仅使用 store://0TxIGQMQbObzvU4Apia0V0 来表示 env

来自 Github issue 1199 的更好解决方案,我们可以使用自定义拦截器是解决此问题的一种方法。这个解决方案对我有用。

根据你的情况,我想在 url.

中用 = 替换 %26
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);
    }
});

请使用encoded = true

@Query(值="email",编码=真)

@HTTP(方法="DELETE",路径=ApiConstant.DELETE_CONTACT_INFO,hasBody=true)

Observable deleteContactInfo( @Query(value = "email", encoded = true) String email);

URL是:

https://api.themoviedb.org/3/discover/movie?api_key={"PUTAPIKEYHERE!!!}&with_genres=28

我得到:

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
}