如何避免在 Retrofit 中发出表单编码的 Get 请求时对请求参数名称进行编码?



我目前正在开发Android应用程序,该应用程序使用Retrofit和OkHttpClient从服务器获取/发送数据。 这在调用我自己的服务器时很棒,而在尝试调用谷歌地图 API 时遇到 404 错误。

下面表示有错误的响应。 Response{protocol=h2, code=404, message=, url=https://maps.googleapis.com/maps%2Fapi%2Fgeocode%2Fjson%3Fkey=defesdvmdkeidm&latlng=11.586215,104.893197}

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

我尝试的是添加自定义标题"内容类型:应用程序/x-www-form-urlencoded;charset=utf-8"通过拦截器到OkHttpClient,但这不起作用。

最好的详细回复将不胜感激。

问候。


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);
}
});
}

The problem is in the definition of your Retrofit service interface and the values you pass to it.

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);
}

最新更新