static boolean isWebsocketUpgrade(HttpHeaders headers) {
        //this contains check does not allocate an iterator, and most requests are not upgrades
        //so we do the contains check first before checking for specific values
        return headers.contains(HttpHeaderNames.UPGRADE) &&
                headers.containsValue(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE, true) &&
                headers.contains(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET, true);
    }
@Test
    public void testIsWebsocketUpgrade() {
        HttpHeaders headers = new DefaultHttpHeaders();
        assertFalse(isWebsocketUpgrade(headers));

        headers.add(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET);
        assertFalse(isWebsocketUpgrade(headers));

        headers.add(HttpHeaderNames.CONNECTION, "Keep-Alive, Upgrade");
        assertTrue(isWebsocketUpgrade(headers));
    }