Interceptor拦截器刷新token,遇到okhttp流只能读取一次解决方法

295 阅读1分钟

image.png

可以使用newBuilder()

Response.Builder builder = resp.newBuilder();
Response clone = builder.build();
ResponseBody responseBody = clone.body();

/**
 * @author Aivan
 * @date 2023/4/26
 * @describe 刷新token
 */
public class AutoRegisterLoginInterceptor implements Interceptor {
    private static final Charset UTF8 = Charset.forName("UTF-8");

    @NonNull
    @Override
    public Response intercept(@NonNull Chain chain) throws IOException {
        Request request = chain.request();
        Response response = chain.proceed(request);
        return handleResp(chain,request,response);
    }

    private Response handleResp(Chain chain, Request request, Response resp) {
        Response.Builder builder = resp.newBuilder();
        Response clone = builder.build();
        ResponseBody responseBody = clone.body();

        try {
            if (HttpHeaders.hasBody(clone)) {
                if (responseBody == null) {
                    return resp;
                }

                if (isPlaintext(responseBody.contentType())) {
                    byte[] bytes = IOUtils.toByteArray(responseBody.byteStream());
                    MediaType contentType = responseBody.contentType();
                    String body = new String(bytes, getCharset(contentType));

                    BaseResp tioResp = JsonUtils.fromJson(body, BaseResp.class);
                    if(tioResp.getCode() == TmdRespCode.ForbidOper.NOTLOGIN){
                        resp.close();
                        String token = getToken(chain, request);
                        return chain.proceed(request.newBuilder().header("token",token).build());
                    }

                    responseBody = ResponseBody.create(responseBody.contentType(), bytes);
                    return resp.newBuilder().body(responseBody).build();
                } else {
                    //body: maybe [binary body], omitted!
                }
            }
        } catch (Exception ignored) {
        }

        return resp;
    }


    private String getToken(@NonNull Chain chain, Request request) throws IOException {
        AutoRegisterLoginReq req = new AutoRegisterLoginReq();
        FormBody.Builder formBuilder = new FormBody.Builder();
        formBuilder.add("deviceid", DeviceUtils.getAndroidID()).add("appid", Utils.getApp().getString(R.string.appid));
        Request.Builder builder = new Request.Builder()
                .url(req.url())
                .post(formBuilder.build())
                ;
        Response response = chain.proceed(builder.build());
        if(response != null && response.code() == 200){
            JsonReader jsonReader = new JsonReader(response.body().charStream());
            BaseResp<AutoRegisterLoginResp> baseResp = JsonUtils.fromJson(jsonReader, new TypeToken<BaseResp<AutoRegisterLoginResp>>() {}.getType());
            AutoRegisterLoginResp resp = baseResp.getData();
            if(resp != null){
                HttpPreferences.saveCurrToken(resp.token);
                return resp.token;
            }
        }
        return null;
    }

    private static Charset getCharset(MediaType contentType) {
        Charset charset = contentType != null ? contentType.charset(UTF8) : UTF8;
        if (charset == null) {
            charset = UTF8;
        }
        return charset;
    }

    /**
     * Returns true if the body in question probably contains human readable text. Uses a small sample
     * of code points to detect unicode control characters commonly used in binary file signatures.
     */
    private static boolean isPlaintext(MediaType mediaType) {
        if (mediaType == null) {
            return false;
        }
        if (mediaType.type() != null && mediaType.type().equals("text")) {
            return true;
        }
        String subtype = mediaType.subtype();
        if (subtype != null) {
            subtype = subtype.toLowerCase();
            if (subtype.contains("x-www-form-urlencoded") || subtype.contains("json") || subtype.contains("xml") || subtype.contains("html")) //
            {
                return true;
            }
        }
        return false;
    }
}