Retrofit2:在OkHttp Interceptor中修改请求体

Lal*_*ukh 23 android retrofit okhttp

我在Android应用程序中使用Retrofit 2(2.0.0-beta3)和OkHttp客户端,到目前为止一切都很顺利.但目前我正面临着OkHttp Interceptor的问题.我正在与之通信的服务器正在请求主体中访问令牌,因此当我需要添加更新的身份验证令牌时,当我拦截添加身份验证令牌的身份验证或身份验证器的身份验证方法时,我需要为此目的修改请求体.但看起来我只能在标题中添加数据,但不能在正在进行的请求中添加数据.我到目前为止编写的代码如下:

client.interceptors().add(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (UserPreferences.ACCESS_TOKEN != null) {
                    // need to add this access token in request body as encoded form field instead of header
                    request = request.newBuilder()
                            .header("access_token", UserPreferences.ACCESS_TOKEN))
                            .method(request.method(), request.body())
                            .build();
                }
                Response response = chain.proceed(request);
                return response;
            }
        });
Run Code Online (Sandbox Code Playgroud)

任何人都可以指出正确的方向,如何修改请求体以添加我的访问令牌(第一次或在令牌刷新后更新)?任何指向正确方向的指针都将受到赞赏.

Fab*_*ian 31

我使用它将post参数添加到现有参数.

 OkHttpClient client = new OkHttpClient.Builder()
                    .protocols(protocols)
                    .addInterceptor(new Interceptor() {
                        @Override
                        public Response intercept(Chain chain) throws IOException {
                            Request request = chain.request();
                            Request.Builder requestBuilder = request.newBuilder();
RequestBody formBody = new FormEncodingBuilder()
            .add("email", "Jurassic@Park.com")
            .add("tel", "90301171XX")
            .build();
                            String postBodyString = Utils.bodyToString(request.body());
                            postBodyString += ((postBodyString.length() > 0) ? "&" : "") +  Utils.bodyToString(formBody);
                            request = requestBuilder
                                    .post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), postBodyString))
                                    .build();
                            return chain.proceed(request);
                        }
                    })
                    .build();

public static String bodyToString(final RequestBody request){
        try {
            final RequestBody copy = request;
            final Buffer buffer = new Buffer();
            if(copy != null)
                copy.writeTo(buffer);
            else
                return "";
            return buffer.readUtf8();
        }
        catch (final IOException e) {
            return "did not work";
        }
    }
Run Code Online (Sandbox Code Playgroud)

OkHttp3:

RequestBody formBody = new FormBody.Builder()
                .add("email", "Jurassic@Park.com")
                .add("tel", "90301171XX")
                .build();
Run Code Online (Sandbox Code Playgroud)


mgr*_*y88 10

我将使用 Dagger 分享我对 @Fabian 答案的 Kotlin 实现。我想origin=app添加到 GET 请求的请求 url 中,并添加到表单编码的 POST 请求的正文中

@Provides
@Singleton
fun providesRequestInterceptor() =
        Interceptor {
            val request = it.request()

            it.proceed(when (request.method()) {
                "GET" -> {
                    val url = request.url()
                    request.newBuilder()
                            .url(url.newBuilder()
                                    .addQueryParameter("origin", "app")
                                    .build())
                            .build()
                }
                "POST" -> {
                    val body = request.body()
                    request.newBuilder()
                            .post(RequestBody.create(body?.contentType(),
                                    body.bodyToString() + "&origin=app"))
                            .build()
                }
                else -> request
            })
        }

fun RequestBody?.bodyToString(): String {
    if (this == null) return ""
    val buffer = okio.Buffer()
    writeTo(buffer)
    return buffer.readUtf8()
}
Run Code Online (Sandbox Code Playgroud)


Deb*_*jan 5

由于这不能写在@Fabian的上一个答案的注释中,因此我将其作为单独的答案发布。该答案同时处理“ application / json”和表单数据。

import android.content.Context;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;

/**
 * Created by debanjan on 16/4/17.
 */

public class TokenInterceptor implements Interceptor {
    private Context context; //This is here because I needed it for some other cause 

    //private static final String TOKEN_IDENTIFIER = "token_id";
    public TokenInterceptor(Context context) {
        this.context = context;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        RequestBody requestBody = request.body();
        String token = "toku";//whatever or however you get it.
        String subtype = requestBody.contentType().subtype();
        if(subtype.contains("json")){
            requestBody = processApplicationJsonRequestBody(requestBody, token);
        }
        else if(subtype.contains("form")){
            requestBody = processFormDataRequestBody(requestBody, token);
        }
        if(requestBody != null) {
            Request.Builder requestBuilder = request.newBuilder();
            request = requestBuilder
                    .post(requestBody)
                    .build();
        }

        return chain.proceed(request);
    }
    private String bodyToString(final RequestBody request){
        try {
            final RequestBody copy = request;
            final Buffer buffer = new Buffer();
            if(copy != null)
                copy.writeTo(buffer);
            else
                return "";
            return buffer.readUtf8();
        }
        catch (final IOException e) {
            return "did not work";
        }
    }
    private RequestBody processApplicationJsonRequestBody(RequestBody requestBody,String token){
        String customReq = bodyToString(requestBody);
        try {
            JSONObject obj = new JSONObject(customReq);
            obj.put("token", token);
            return RequestBody.create(requestBody.contentType(), obj.toString());
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
    private RequestBody processFormDataRequestBody(RequestBody requestBody, String token){
        RequestBody formBody = new FormBody.Builder()
                .add("token", token)
                .build();
        String postBodyString = bodyToString(requestBody);
        postBodyString += ((postBodyString.length() > 0) ? "&" : "") +  bodyToString(formBody);
        return RequestBody.create(requestBody.contentType(), postBodyString);
    }

}
Run Code Online (Sandbox Code Playgroud)