OkHTTP 重写 WebSocket 请求头

问题背景

对方 WebSocket 有问题,握手时返回的响应头含有两个 Connection,一个为 upgrade 另一个为 close,导致协议升级失败,具体报错为 WsListener 587802424 on failure, exception java.net.ProtocolException, exception message Expected 'Connection' header value 'Upgrade' but was 'close', code 101, response Switching Protocols

解决方式

重写响应头,移除 close 值,解决方案是 Okhttp 新增拦截器,移除错误的请求头

package cn.crservice.sbktransfer.lmd;

import cn.crservice.sbktransfer.config.YmlConfig;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;

@Slf4j
@Component
public class WsInit {

    private final YmlConfig.Websocket websocketConfig;
    private WebSocket webSocket;

    @Autowired
    public WsInit(YmlConfig ymlConfig) {
        this.websocketConfig = ymlConfig.getWebsocket();
    }

    /**
     * 初始化当前 WebSocket 连接
     */
    @PostConstruct
    public void init() {
        log.info("Initialization websocket");
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                // 对方 WebSocket 存在双 Connection,且最后一个为 close,导致握手失败,定义拦截器进行移除
                .addInterceptor(chain -> {
                    Request request = chain.request();
                    Response response = chain.proceed(request);
                    List<String> headers = response.headers("Connection");
                    // 重写 Connection 响应头
                    if (headers.size() == 2 && headers.contains("upgrade") && headers.contains("close")) {
                        return response.newBuilder().header("Connection", "upgrade").build();
                    }
                    return response;
                })
                .pingInterval(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        Request request = new Request.Builder().url(websocketConfig.getUrl().getLmd()).build();
        webSocket = okHttpClient.newWebSocket(request, new WsListener());
    }
}
原文地址:https://www.cnblogs.com/seliote/p/15001612.html