<p>I have deployed two services to a Kubernetes Cluster on GCP:</p>

<p>One is a Spring Cloud Api Gateway implementation:</p>

<pre><code>apiVersion: v1
kind: Service
metadata:
  name: api-gateway
spec:
  ports:
  - name: main
    port: 80
    targetPort: 8080
    protocol: TCP
  selector:
    app: api-gateway
    tier: web
  type: NodePort
</code></pre>

<p>The other one is a backend chat service implementation which exposes a WebSocket at <code>/ws/</code> path.</p>

<pre><code>apiVersion: v1
kind: Service
metadata:
 name: chat-api
spec:
  ports:
  - name: main
    port: 80
    targetPort: 8080
    protocol: TCP
  selector:
    app: chat
    tier: web
  type: NodePort
</code></pre>

<p>The API Gateway is exposed to internet through a <a href="https://github.com/heptio/contour" rel="nofollow noreferrer">Contour Ingress Controller</a>:</p>

<pre><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: api-gateway-ingress
  annotations:
    kubernetes.io/tls-acme: "true"
    certmanager.k8s.io/cluster-issuer: "letsencrypt-prod"
    ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  tls:
  - secretName: api-gateway-tls
    hosts:
    - api.mydomain.com.br
  rules:
  - host: api.mydomain.com.br
    http:
      paths:
      - backend:
          serviceName: api-gateway
          servicePort: 80
</code></pre>

<p>The gateway routes incoming calls to <code>/chat/</code> path to the chat service on <code>/ws/</code>:</p>

<pre><code>@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
            .route(r -&gt; r.path("/chat/**")
                    .filters(f -&gt; f.rewritePath("/chat/(?&lt;segment&gt;.*)", "/ws/(?&lt;segment&gt;.*)"))
                    .uri("ws://chat-api"))
            .build();
}
</code></pre>

<p>When I try to connect to the WebSocket through the gateway I get a 403 error:</p>

<p><code>error: Unexpected server response: 403</code></p>

<p>I even tried to connect using http, https, ws and wss but the error remains.</p>

<p>Anyone has a clue?</p>

<p>I had the same issue using Ingress resource with Contour 0.5.0 but I managed to solve it by
upgrading Contour to v0.6.0-beta.3 with IngressRoute  (be aware, though, that it's a beta version).</p>

<p>You can add an IngressRoute resource (crd) like this (remove your previous ingress resource): </p>

<pre><code>#ingressroute.yaml
apiVersion: contour.heptio.com/v1beta1
kind: IngressRoute
metadata:
  name: api-gateway-ingress
  namespace: default
spec:
  virtualhost:
    fqdn: api.mydomain.com.br
    tls:
      secretName: api-gateway-tls
  routes:
    - match: /
      services:
        - name: api-gateway
          port: 80
    - match: /chat
      enableWebsockets: true # Setting this to true enables websocket for all paths that match /chat
      services:
        - name: api-gateway
          port: 80
</code></pre>

<p>Then apply it</p>

<p>Websockets  will be authorized only on the <code>/chat</code> path.</p>

<p>See <a href="https://github.com/heptio/contour/blob/master/docs/ingressroute.md#websocket-support" rel="nofollow noreferrer">here</a> for more detail about Contour IngressRoute.</p>
