@@ -24,8 +24,10 @@ import (
2424 "math"
2525 "net"
2626 "net/http"
27+ "net/url"
2728 "time"
2829
30+ "github.com/gorilla/websocket"
2931 . "github.com/onsi/ginkgo/v2"
3032 . "github.com/onsi/gomega"
3133 "k8s.io/apimachinery/pkg/types"
@@ -906,4 +908,137 @@ spec:
906908 })
907909 })
908910 })
911+
912+ Context ("Test ApisixRoute WebSocket Support" , func () {
913+ It ("basic websocket functionality" , func () {
914+ const websocketServerResources = `
915+ apiVersion: v1
916+ kind: Pod
917+ metadata:
918+ name: websocket-server
919+ labels:
920+ app: websocket-server
921+ spec:
922+ containers:
923+ - name: websocket-server
924+ image: jmalloc/echo-server:latest
925+ ports:
926+ - containerPort: 8080
927+ ---
928+ apiVersion: v1
929+ kind: Service
930+ metadata:
931+ name: websocket-server-service
932+ spec:
933+ selector:
934+ app: websocket-server
935+ ports:
936+ - name: ws
937+ port: 8080
938+ protocol: TCP
939+ targetPort: 8080
940+ `
941+ const apisixRouteSpec = `
942+ apiVersion: apisix.apache.org/v2
943+ kind: ApisixRoute
944+ metadata:
945+ name: websocket-route
946+ spec:
947+ ingressClassName: apisix
948+ http:
949+ - name: rule1
950+ match:
951+ hosts:
952+ - httpbin.org
953+ paths:
954+ - /echo
955+ websocket: true
956+ backends:
957+ - serviceName: websocket-server-service
958+ servicePort: 8080
959+ `
960+
961+ const apisixRouteSpec2 = `
962+ apiVersion: apisix.apache.org/v2
963+ kind: ApisixRoute
964+ metadata:
965+ name: websocket-route
966+ spec:
967+ ingressClassName: apisix
968+ http:
969+ - name: rule1
970+ match:
971+ hosts:
972+ - httpbin.org
973+ paths:
974+ - /echo
975+ backends:
976+ - serviceName: websocket-server-service
977+ servicePort: 8080
978+ `
979+
980+ By ("create WebSocket server resources" )
981+ err := s .CreateResourceFromString (websocketServerResources )
982+ Expect (err ).ShouldNot (HaveOccurred (), "creating WebSocket server resources" )
983+
984+ By ("create ApisixRoute without WebSocker" )
985+ var apisixRouteWithoutWS apiv2.ApisixRoute
986+ applier .MustApplyAPIv2 (
987+ types.NamespacedName {Namespace : s .Namespace (), Name : "websocket-route" },
988+ & apisixRouteWithoutWS ,
989+ apisixRouteSpec2 ,
990+ )
991+ time .Sleep (8 * time .Second )
992+
993+ By ("verify WebSocket connection fails without WebSocket enabled" )
994+ u := url.URL {
995+ Scheme : "ws" ,
996+ Host : s .ApisixHTTPEndpoint (),
997+ Path : "/echo" ,
998+ }
999+ headers := http.Header {"Host" : []string {"httpbin.org" }}
1000+ _ , resp , _ := websocket .DefaultDialer .Dial (u .String (), headers )
1001+ // should receive 200 instead of 101
1002+ Expect (resp .StatusCode ).Should (Equal (http .StatusOK ))
1003+
1004+ By ("apply ApisixRoute for WebSocket" )
1005+ var apisixRoute apiv2.ApisixRoute
1006+ applier .MustApplyAPIv2 (
1007+ types.NamespacedName {Namespace : s .Namespace (), Name : "websocket-route" },
1008+ & apisixRoute ,
1009+ apisixRouteSpec ,
1010+ )
1011+ By ("wait for WebSocket server to be ready" )
1012+ time .Sleep (10 * time .Second )
1013+ By ("verify WebSocket connection" )
1014+ u = url.URL {
1015+ Scheme : "ws" ,
1016+ Host : s .ApisixHTTPEndpoint (),
1017+ Path : "/echo" ,
1018+ }
1019+ headers = http.Header {"Host" : []string {"httpbin.org" }}
1020+
1021+ conn , resp , err := websocket .DefaultDialer .Dial (u .String (), headers )
1022+ Expect (err ).ShouldNot (HaveOccurred (), "WebSocket handshake" )
1023+ Expect (resp .StatusCode ).Should (Equal (http .StatusSwitchingProtocols ))
1024+
1025+ defer func () {
1026+ _ = conn .Close ()
1027+ }()
1028+
1029+ By ("send and receive message through WebSocket" )
1030+ testMessage := "hello, this is APISIX"
1031+ err = conn .WriteMessage (websocket .TextMessage , []byte (testMessage ))
1032+ Expect (err ).ShouldNot (HaveOccurred (), "writing WebSocket message" )
1033+
1034+ // The echo server sends an identification message first
1035+ _ , _ , err = conn .ReadMessage ()
1036+ Expect (err ).ShouldNot (HaveOccurred (), "reading identification message" )
1037+
1038+ // Then our echo
1039+ _ , msg , err := conn .ReadMessage ()
1040+ Expect (err ).ShouldNot (HaveOccurred (), "reading echo message" )
1041+ Expect (string (msg )).To (Equal (testMessage ), "message content verification" )
1042+ })
1043+ })
9091044})
0 commit comments