• 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());
        }
    }
    
  • 相关阅读:
    我已经迷失在事件环(eventloop)中了【Nodejs篇】
    canvas练手项目(二)——各种操作基础
    canvas练手项目(三)——Canvas中的Text文本
    canvas练手项目(一)——选取图片
    迭代器,生成器(generator)和Promise的“微妙”关系
    通过HTTP的HEADER完成各种骚操作
    这份Koa的简易Router手敲指南请收下
    KOA的简易模板引擎实现方式
    扒一扒PROMISE的原理,大家不要怕!
    参考KOA,5步手写一款粗糙的web框架
  • 原文地址:https://www.cnblogs.com/seliote/p/15001612.html
Copyright © 2020-2023  润新知