I have created a Websocket API using AWS's websocket API gateway. After creating the api i got the endpoint like
wss://x5g9h3p2rq.execute-api.eu-central-1.amazonaws.com/dev
I could use this directly and invoke the $connect
lambda without any issue
Now I wanted this to serve via cloudfront.
I already have a distribution which has Alternate domain name like app.blablabla.cloud
and it serves multiple REST APIs (Origin Type: API Gateway) for different services. I wanted to do the same for the websocket API as well
I created a new custom origin for the distribution
x5g9h3p2rq.execute-api.eu-central-1.amazonaws.com
After that I created a behaviour and attached this origin
/dev/my-socket/*
Cookies - All
, Query strings - All
and Headers - Include the following headers - Sec-WebSocket-Key, Sec-WebSocket-Version, Sec-WebSocket-Protocol, Sec-WebSocket-Accept, Sec-WebSocket-Extensions
Now i tried to invoke a wss initial call from postman with the url
wss://app.blablabla.cloud/dev/my-socket/?param1=1¶m2=test
but i get Status Code: 403 Forbidden
(I'm expecting a 101 Switching Protocols
) and also request headers are
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: TVMDG46dqkDM4a7DoM20ZB==
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Host: app.blablabla.cloud
so it looks like cloudfront is hit just can't get it through. the api gateway dashboard also showed something like
I don't understand where the issue is. Help is much appreciated. Thanks in advance!
EDIT.
Later tried with cloudfront functions here and think it is a better approach
the issue was API Gateway’s WebSocket API does not support a path parameter in the connection URL. By design (or say it a design oversight), the connection URL path is fixed to the root path / (stage would be prepended when execute-api endpoint is used).
as mentioned in this medium article.
In simple terms trying to connect wss://x5g9h3p2rq.execute-api.eu-central-1.amazonaws.com/dev/my-socket/?param1=1¶m2=test
will give the same 403 Forbidden . Only wss://x5g9h3p2rq.execute-api.eu-central-1.amazonaws.com/dev/?param1=1¶m2=test
or wss://x5g9h3p2rq.execute-api.eu-central-1.amazonaws.com/dev?param1=1¶m2=test
works.
i.e when i try to connect wss://app.blablabla.cloud/dev/my-socket/?param1=1¶m2=test
it must be trying to connect to wss://x5g9h3p2rq.execute-api.eu-central-1.amazonaws.com/dev/my-socket/?param1=1¶m2=test
So approach 1
/dev
and bring the precedence down so that the rest of the dev/stuff/*
are not affected.wss://app.blablabla.cloud/dev?param1=1¶m2=test
But this is not scalable. What if we need another socket API. we cannot use the same /dev
for everything.
This leads to better approach 2
Using Lambda@Edge
/dev/my-socket/*
.uri
from /dev/my-socket/
to /dev
'use strict';
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
request.uri = request.uri.replace(/\/[^\/]+\/$/, '');
return callback(null, request);
};
wss://app.blablabla.cloud/dev/my-socket/?param1=1¶m2=test
and it will strip the my-socket
and forward to the correct origin.