Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/provider/adc/translator/apisixroute.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func (t *Translator) buildRoute(ar *apiv2.ApisixRoute, service *adc.Service, rul
route.ID = id.GenID(route.Name)
route.Desc = "Created by apisix-ingress-controller, DO NOT modify it manually"
route.Labels = label.GenLabel(ar)
route.EnableWebsocket = ptr.To(true)
route.EnableWebsocket = ptr.To(rule.Websocket)
route.FilterFunc = rule.Match.FilterFunc
route.Hosts = rule.Match.Hosts
route.Methods = rule.Match.Methods
Expand Down
135 changes: 135 additions & 0 deletions test/e2e/crds/v2/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ import (
"io"
"net"
"net/http"
"net/url"
"time"

"github.com/gorilla/websocket"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -757,4 +759,137 @@ spec:
})
})
})

Context("Test ApisixRoute WebSocket Support", func() {
It("basic websocket functionality", func() {
const websocketServerResources = `
apiVersion: v1
kind: Pod
metadata:
name: websocket-server
labels:
app: websocket-server
spec:
containers:
- name: websocket-server
image: jmalloc/echo-server:latest
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: websocket-server-service
spec:
selector:
app: websocket-server
ports:
- name: ws
port: 8080
protocol: TCP
targetPort: 8080
`
const apisixRouteSpec = `
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: websocket-route
spec:
ingressClassName: apisix
http:
- name: rule1
match:
hosts:
- httpbin.org
paths:
- /echo
websocket: true
backends:
- serviceName: websocket-server-service
servicePort: 8080
`

const apisixRouteSpec2 = `
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: websocket-route
spec:
ingressClassName: apisix
http:
- name: rule1
match:
hosts:
- httpbin.org
paths:
- /echo
backends:
- serviceName: websocket-server-service
servicePort: 8080
`

By("create WebSocket server resources")
err := s.CreateResourceFromString(websocketServerResources)
Expect(err).ShouldNot(HaveOccurred(), "creating WebSocket server resources")

By("create ApisixRoute without WebSocker")
var apisixRouteWithoutWS apiv2.ApisixRoute
applier.MustApplyAPIv2(
types.NamespacedName{Namespace: s.Namespace(), Name: "websocket-route"},
&apisixRouteWithoutWS,
apisixRouteSpec2,
)
time.Sleep(8 * time.Second)

By("verify WebSocket connection fails without WebSocket enabled")
u := url.URL{
Scheme: "ws",
Host: s.ApisixHTTPEndpoint(),
Path: "/echo",
}
headers := http.Header{"Host": []string{"httpbin.org"}}
_, resp, _ := websocket.DefaultDialer.Dial(u.String(), headers)
// should receive 200 instead of 101
Expect(resp.StatusCode).Should(Equal(http.StatusOK))

By("apply ApisixRoute for WebSocket")
var apisixRoute apiv2.ApisixRoute
applier.MustApplyAPIv2(
types.NamespacedName{Namespace: s.Namespace(), Name: "websocket-route"},
&apisixRoute,
apisixRouteSpec,
)
By("wait for WebSocket server to be ready")
time.Sleep(10 * time.Second)
By("verify WebSocket connection")
u = url.URL{
Scheme: "ws",
Host: s.ApisixHTTPEndpoint(),
Path: "/echo",
}
headers = http.Header{"Host": []string{"httpbin.org"}}

conn, resp, err := websocket.DefaultDialer.Dial(u.String(), headers)
Expect(err).ShouldNot(HaveOccurred(), "WebSocket handshake")
Expect(resp.StatusCode).Should(Equal(http.StatusSwitchingProtocols))

defer func() {
_ = conn.Close()
}()

By("send and receive message through WebSocket")
testMessage := "hello, this is APISIX"
err = conn.WriteMessage(websocket.TextMessage, []byte(testMessage))
Expect(err).ShouldNot(HaveOccurred(), "writing WebSocket message")

// The echo server sends an identification message first
_, _, err = conn.ReadMessage()
Expect(err).ShouldNot(HaveOccurred(), "reading identification message")

// Then our echo
_, msg, err := conn.ReadMessage()
Expect(err).ShouldNot(HaveOccurred(), "reading echo message")
Expect(string(msg)).To(Equal(testMessage), "message content verification")
})
})
})
4 changes: 4 additions & 0 deletions test/e2e/scaffold/scaffold.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ func (s *Scaffold) NewAPISIXClient() *httpexpect.Expect {
})
}

func (s *Scaffold) ApisixHTTPEndpoint() string {
return s.apisixHttpTunnel.Endpoint()
}

// GetAPISIXHTTPSEndpoint get apisix https endpoint from tunnel map
func (s *Scaffold) GetAPISIXHTTPSEndpoint() string {
return s.apisixHttpsTunnel.Endpoint()
Expand Down
Loading