Retrofit Get請求中帶有特殊字元(^)報400錯誤
轉眼又是一個月,回首已經過兩年,唉。
修改了密碼之後登陸app,發現無法登陸直接報錯,趕緊檢視程式碼log:
09-05 12:50:29.909 13653-13653/com.yiche.autoreport W/System.err: retrofit2.adapter.rxjava.HttpException: HTTP 400
at retrofit2.adapter.rxjava.OperatorMapResponseToBodyOrError$1.onNext(OperatorMapResponseToBodyOrError.java:43)
at retrofit2.adapter.rxjava.OperatorMapResponseToBodyOrError$1.onNext(OperatorMapResponseToBodyOrError.java:38)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:162)
at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80)
at rx.Subscriber.setProducer(Subscriber.java:211)
at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76)
at rx.Subscriber.setProducer(Subscriber.java:205)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:141)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:127)
at rx.Observable$2.call(Observable.java:233)
at rx.Observable$2.call(Observable.java:225)
at rx.Observable.unsafeSubscribe(Observable.java:8644)
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:154)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
沒看太明白!
然後觀察HttpLoggingInterceptor列印的請求log發現url引數如下:
║ --> GET https://xxxxxx/index/login?username=xxx&password=ssd123$%^ http/1.1
引數中未編碼的password為ssd123$%^,”^”字元竟然沒有進行url編碼,我記得retrofit預設會自動對不符合規則的引數value進行編碼。
檢視文件可知:
Retrofit中類似@Query,@QueryMap,@QueryName等都會自動進行編碼,
註解定義如下:
@Documented
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface QueryMap {
boolean encoded() default false;
}
public abstract boolean encoded
Specifies whether the parameter name and value are already URL encoded.
Default:
false
false表示特殊字元已進行url 編碼。
看到這裡解決辦法已經有了,就是encoded = true,然後自己編碼,我設定encoded = true,之後檢視log,不符合規則的請求引數還是會進行編碼。
/**
* 登入
*/
@GET( BASE_URL + "index/login" )
Observable< LoginResult > requestLogin( @QueryMap(encoded = true) Map< String, String > params );
final Map< String, String > paramsMap = new ParamsProvider.Builder().
append( "username", account ).
append( "password",URLEncoded(password) ).
build();
這裡有個疑問是為什麼自動編碼時沒有對“^”字元進行編碼,很奇怪。