使用 @FormUrlEncoded 未设置 Content-Type 的 OkHTTP 改造
Retrofit with OkHTTP not set Content-Type with @FormUrlEncoded
我正在尝试通过 x-www-form-urlencoded
在 Android 上使用 Retrofit 2 实现身份验证,但遇到了一个问题,即 Header Content-Type
未设置为 @FormUrlEncoded
注释,以及我试图手动设置它,但是当我用 Cotent-Type
之类的错字设置它时,它工作正常,我可以在 headers 中看到它。
改造版本:2.4.0
所以我的问题是:为什么 @FormUrlEncoded
不设置内容类型以及 @Header
注释或者什么可以将其从 headers.
中删除
我的要求:
@FormUrlEncoded
@POST("account/login")
Single<LoginResponse> login(@Field("memberId") String memberId,
@Field("pin") String pin);
OkHTTP/Retrofit 带有拦截器的提供者:
@Singleton
@Provides
Retrofit provideRetrofit(final OkHttpClient client, final Moshi moshi) {
return new Retrofit.Builder()
.baseUrl(Configuration.BASE_URL)
.client(client)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
@Provides
OkHttpClient provideOkHttpClient(@AppContext final Context context) {
final OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.followRedirects(true)
.followSslRedirects(true)
.addInterceptor(createLanguageInterceptor(context));
if (BuildConfig.DEBUG) {
builder.addInterceptor(new LoggingInterceptor());
}
return builder.build();
}
Interceptor createLanguageInterceptor(@AppContext final Context context) {
Locale current = context.getResources().getConfiguration().locale;
return chain -> {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("Accept-Language", current.getLanguage());
Request request = builder.build();
Response response = chain.proceed(request);
return response;
};
}
作为解决方法,我实现了以下拦截器:
Interceptor createHeaderTransformationInterceptor() {
return chain -> {
final Request request = chain.request();
String dataType = request.header("Data-Type");
final Request resultRequest = dataType == null
? request
: chain.request().newBuilder()
.removeHeader("Data-Type")
.addHeader("Content-Type", dataType)
.build();
return chain.proceed(resultRequest);
};
}
它可以很好地使用以下注释:
@Headers({"Data-Type: application/x-www-form-urlencoded"})
更新: 我的拦截器没有看到的原因是在存储内容类型的地方。在拦截器中看到 header 的正确方法 :
if (requestBody.contentType() != null) {
logger.log("Content-Type: " + requestBody.contentType());
}
if (requestBody.contentLength() != -1) {
logger.log("Content-Length: " + requestBody.contentLength());
}
通过此请求
@FormUrlEncoded
@POST("account/login")
Single<LoginResponse> login(@Field("memberId") String memberId,
@Field("pin") String pin);
方法@POST
和@FormUrlEncoded
自动添加
Content-Type: application/x-www-form-urlencoded
在 header 您可以通过
登录
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor.setLevel(HttpLoggingInterceptor.Level.BODY))
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES)
.readTimeout(2, TimeUnit.MINUTES)
.build();
它以详细模式打印所有日志
我正在尝试通过 x-www-form-urlencoded
在 Android 上使用 Retrofit 2 实现身份验证,但遇到了一个问题,即 Header Content-Type
未设置为 @FormUrlEncoded
注释,以及我试图手动设置它,但是当我用 Cotent-Type
之类的错字设置它时,它工作正常,我可以在 headers 中看到它。
改造版本:2.4.0
所以我的问题是:为什么 @FormUrlEncoded
不设置内容类型以及 @Header
注释或者什么可以将其从 headers.
我的要求:
@FormUrlEncoded
@POST("account/login")
Single<LoginResponse> login(@Field("memberId") String memberId,
@Field("pin") String pin);
OkHTTP/Retrofit 带有拦截器的提供者:
@Singleton
@Provides
Retrofit provideRetrofit(final OkHttpClient client, final Moshi moshi) {
return new Retrofit.Builder()
.baseUrl(Configuration.BASE_URL)
.client(client)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
@Provides
OkHttpClient provideOkHttpClient(@AppContext final Context context) {
final OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.followRedirects(true)
.followSslRedirects(true)
.addInterceptor(createLanguageInterceptor(context));
if (BuildConfig.DEBUG) {
builder.addInterceptor(new LoggingInterceptor());
}
return builder.build();
}
Interceptor createLanguageInterceptor(@AppContext final Context context) {
Locale current = context.getResources().getConfiguration().locale;
return chain -> {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("Accept-Language", current.getLanguage());
Request request = builder.build();
Response response = chain.proceed(request);
return response;
};
}
作为解决方法,我实现了以下拦截器:
Interceptor createHeaderTransformationInterceptor() {
return chain -> {
final Request request = chain.request();
String dataType = request.header("Data-Type");
final Request resultRequest = dataType == null
? request
: chain.request().newBuilder()
.removeHeader("Data-Type")
.addHeader("Content-Type", dataType)
.build();
return chain.proceed(resultRequest);
};
}
它可以很好地使用以下注释:
@Headers({"Data-Type: application/x-www-form-urlencoded"})
更新: 我的拦截器没有看到的原因是在存储内容类型的地方。在拦截器中看到 header 的正确方法 :
if (requestBody.contentType() != null) {
logger.log("Content-Type: " + requestBody.contentType());
}
if (requestBody.contentLength() != -1) {
logger.log("Content-Length: " + requestBody.contentLength());
}
通过此请求
@FormUrlEncoded
@POST("account/login")
Single<LoginResponse> login(@Field("memberId") String memberId,
@Field("pin") String pin);
方法@POST
和@FormUrlEncoded
自动添加
Content-Type: application/x-www-form-urlencoded
在 header 您可以通过
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor.setLevel(HttpLoggingInterceptor.Level.BODY))
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES)
.readTimeout(2, TimeUnit.MINUTES)
.build();
它以详细模式打印所有日志