使用OkHTTP进行的改装未使用@FormUrlEncoded设置Content-Type [英] Retrofit with OkHTTP not set Content-Type with @FormUrlEncoded

查看:1331
本文介绍了使用OkHTTP进行的改装未使用@FormUrlEncoded设置Content-Type的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Android上使用Retrofit 2通过x-www-form-urlencoded实现身份验证,但是遇到一个问题,标题Content-Type没有设置@FormUrlEncoded注释,并且我试图手动设置它,但是当我用Cotent-Type等错字设置它时,它可以正常工作,并且可以在标题中看到它.

I'm trying to implement auth via x-www-form-urlencoded with Retrofit 2 on Android but faced a problem, that Header Content-Type not set with @FormUrlEncoded annotation, as well as I'm trying to set it manually, but when I'm setting it with a typo like Cotent-Type it works correctly and I can see it in headers.

改造版本:2.4.0

Retrofit version: 2.4.0

所以我的问题是:为什么@FormUrlEncoded不能设置内容类型以及@Header注释,或者可以从标头中删除它呢?

So my question: why @FormUrlEncoded not set a content type as well as @Header annotation or what can remove it from headers.

我的请求:

   @FormUrlEncoded
   @POST("account/login")
   Single<LoginResponse> login(@Field("memberId") String memberId,
                                    @Field("pin") String pin);

带有拦截器的Okk/Retrofit提供程序:

OkHTTP/Retrofit provider with interceptors:

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

作为一种解决方法,我实现了以下拦截器:

As a workaround, I've implemented the following interceptor:

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

,并且可以在以下注释中正常工作:

and it works fine with the following annotation:

@Headers({"Data-Type: application/x-www-form-urlencoded"})

UPD: 我的拦截器没有看到它的原因是在存储内容类型的地方.在拦截器中查看该标头的正确方法:

    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通过

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

它以详细模式打印所有日志

it print all log in verbose mode

这篇关于使用OkHTTP进行的改装未使用@FormUrlEncoded设置Content-Type的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆