【问题标题】:How can I avoid request parameter names getting encoded when making a form-urlencoded Get request in Retrofit?在 Retrofit 中发出 form-urlencoded Get 请求时,如何避免请求参数名称被编码?
【发布时间】:2018-07-01 15:40:50
【问题描述】:

我目前正在开发使用 Retrofit 和 OkHttpClient 从服务器获取/发送数据的 android 应用程序。 这在调用我自己的服务器时很棒,但在尝试调用 google map api 时遇到 404 错误。

以下表示有错误的响应。 Response{protocol=h2, code=404, message=, url=@987654321@}

这显然是因为 '/' 和 '?'被编码为“%2F”和“%3F”。 解决方案可能是阻止那些特殊字符的 urlencode,但无法实现。

我尝试的是通过拦截器向 OkHttpClient 添加自定义标头“Content-Type:application/x-www-form-urlencoded; charset=utf-8”,但这不起作用。

我们将不胜感激。

问候。

private Retrofit createRetrofit(OkHttpClient client, String _baseUrl) { return new Retrofit.Builder() .baseUrl(_baseUrl) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(client) .build(); } private Retrofit createGoogleRetrofit() { return createRetrofit(createGoogleClient(), baseUrl); } public DenningService getGoogleService() { _baseUrl = "https://maps.googleapis.com/"; final Retrofit retrofit = createGoogleRetrofit(); return retrofit.create(DenningService.class); } public interface DenningService { @GET("{url}") @Headers("Content-Type:application/x-www-form-urlencoded; charset=utf-8") Single getEncodedRequest(@Path("url") String url); } private void sendRequest(final CompositeCompletion completion, final ErrorHandler errorHandler) { mCompositeDisposable.add(mSingle. subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(new Function() { @Override public JsonElement apply(JsonElement jsonElement) throws Exception { return jsonElement; } }) .subscribeWith(new DisposableSingleObserver() { @Override public void onSuccess(JsonElement jsonElement) { completion.parseResponse(jsonElement); } @Override public void onError(Throwable e) { if (e instanceof HttpException && ((HttpException) e).code() == 410) { errorHandler.handleError("Session expired. Please log in again."); } else { errorHandler.handleError(e.getMessage()); } e.printStackTrace(); } }) ); } public void sendGoogleGet(String url, final CompositeCompletion completion) { mSingle = getGoogleService().getEncodedRequest(url); sendRequest(completion, new ErrorHandler() { @Override public void handleError(String error) { ErrorUtils.showError(context, error); } }); }

【问题讨论】:

  • 你能发布你的改造服务接口吗?
  • 好的。抱歉回复晚了。
  • 我更新了问题

标签: android retrofit urlencode okhttp3


【解决方案1】:

问题在于您的 Retrofit 服务接口的定义以及您传递给它的值。

public interface DenningService {
    @GET("{url}")
    @Headers("Content-Type:application/x-www-form-urlencoded; charset=utf-8")
    Single getEncodedRequest(@Path("url") String url);
}

根据您发布的内容,我将假设 url 的值为:

maps/api/geocode/json?key=defesdvmdkeidm&latlng=11.586215,104.893197

它应该是这样的:

public interface DenningService {
    @FormUrlEncoded
    @GET("/maps/api/geocode/json")
    Single getEncodedRequest(@Field("key") String key,
                             @Field("latlng") String latlng);
}

然后你会这样称呼它:

mSingle = getGoogleService().getEncodedRequest(key, latlng);

当然,您必须弄清楚如何将keylatlng 参数从当前的url 字符串中分离出来。

编辑

你是否真的想要你的请求是application/x-www-form-urlencoded,或者你只是想看看它是否解决了你的问题,这对我来说并不明显。如果您确实想要它,那么您的界面将如下所示:

public interface DenningService {
    @GET("/maps/api/geocode/json")
    Single getEncodedRequest(@Query("key") String key,
                             @Query("latlng") String latlng);
}

【讨论】:

  • 谢谢 Ben,我都会尝试一下
猜你喜欢
  • 2017-06-27
  • 2017-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多