您的位置:

解决方案:okhttp ProtocolException("Malformed close payload length of 1.")

  发布时间:2025-01-23 17:08:22
该内容主要介绍了OkHttp出现ProtocolException('Malformed close payload length of 1.')的原因和解决方案,通过自定义ResponseBody和拦截器来处理异常的关闭载荷,从而避免抛出ProtocolException异常。提供了两种不同的方案,分别通过自定义ResponseBody和响应拦截器来处理异常关闭载荷的情况。

问题原因

okhttp出现ProtocolException("Malformed close payload length of 1.")的原因是在HTTP/2协议中,当收到一个长度为1的异常关闭帧(GOAWAY frame)时,这是无效的帧格式,因为按照协议规范,关闭帧的有效载荷长度应该为8字节。因此,当okhttp在解析HTTP/2协议时遇到这种长度为1的异常关闭帧时,就会抛出ProtocolException异常。

解决方案

在处理OkHttp时,可能会出现ProtocolException("Malformed close payload length of 1.")这个异常。这个异常通常是由于服务端在响应结束时使用了非标准的关闭连接方式,导致OkHttp无法正确处理。要解决这个问题,可以通过自定义OkHttp的ResponseBody来处理。 你可以创建一个ResponseBody的子类,重写close()方法,捕获异常并忽略它,从而绕过这个问题。下面是一个示例代码:


import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.BufferedSource;
import java.io.IOException;

public class CustomResponseBody extends ResponseBody {

    private ResponseBody responseBody;

    public CustomResponseBody(ResponseBody responseBody) {
        this.responseBody = responseBody;
    }

    @Override
    public MediaType contentType() {
        return responseBody.contentType();
    }

    @Override
    public long contentLength() {
        return responseBody.contentLength();
    }

    @Override
    public BufferedSource source() {
        return responseBody.source();
    }

    @Override
    public void close() {
        try {
            responseBody.close();
        } catch (IOException e) {
            // Ignore the exception
        }
    }
}

然后,在发起请求的时候,使用OkHttp的interceptor,在拦截器的response()方法中使用自定义的ResponseBody,示例如下:


import okhttp3.Interceptor;
import okhttp3.Response;
import okhttp3.ResponseBody;
import java.io.IOException;

public class CustomInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Response originalResponse = chain.proceed(chain.request());
        return originalResponse.newBuilder()
                .body(new CustomResponseBody(originalResponse.body()))
                .build();
    }
}

最后,在创建OkHttpClient时,将自定义的拦截器添加到OkHttpClient中即可:


OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(new CustomInterceptor())
        .build();

通过上述方法,我们可以在OkHttp中自定义一个ResponseBody来处理Malformed close payload length of 1异常,从而解决这个问题。

具体例子

在使用 OkHttp 时出现 ProtocolException("Malformed close payload length of 1.") 通常是因为服务器在关闭连接时发送了一个不符合规范的关闭载荷导致的。为了正确处理这个问题,可以通过设置合适的响应拦截器来处理异常的关闭载荷,从而避免抛出 ProtocolException。 首先,创建一个自定义的响应拦截器,用于捕获 ProtocolException 异常,然后进行处理。在拦截器中,可以通过判断异常信息中是否包含特定的错误文本来确定是否是由于不规范的关闭载荷导致的异常:


import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Response;
import okhttp3.ProtocolException;

public class CustomResponseInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        try {
            return chain.proceed(chain.request());
        } catch (ProtocolException e) {
            if (e.getMessage().contains("Malformed close payload length of 1.")) {
                // 进行异常处理,例如重新发送请求或者做其他操作
                // 此处仅为示例,具体处理方式根据实际需求来定
                return new Response.Builder()
                        .request(chain.request())
                        .protocol(chain.connection().protocol())
                        .code(200)
                        .message("OK")
                        .body(ResponseBody.create(null, ""))
                        .build();
            } else {
                throw e;
            }
        }
    }
}

接下来,创建 OkHttpClient 实例时,添加自定义的响应拦截器:


import okhttp3.OkHttpClient;

OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(new CustomResponseInterceptor())
        .build();

现在,当服务器发送异常的关闭载荷时,拦截器会捕获到 ProtocolException,并对该异常进行处理,如返回一个自定义的响应。这样就可以避免抛出 ProtocolException("Malformed close payload length of 1.") 异常了。 请注意,以上代码仅作为示例,实际的异常处理方式应根据具体需求进行调整。