Skip to content

Commit 90a3af7

Browse files
kdnaktbmoffatt
andauthored
Handle disconnect route of Websocket (#548)
* Handle disconnect route of Websocket * Revert MessageID type change * Revert field type change * revert MessageID to interface{} --------- Co-authored-by: Bryan Moffatt <[email protected]>
1 parent de51f68 commit 90a3af7

5 files changed

+151
-45
lines changed

events/apigw.go

+45-43
Original file line numberDiff line numberDiff line change
@@ -133,63 +133,65 @@ type APIGatewayV2HTTPResponse struct {
133133

134134
// APIGatewayRequestIdentity contains identity information for the request caller.
135135
type APIGatewayRequestIdentity struct {
136-
CognitoIdentityPoolID string `json:"cognitoIdentityPoolId"`
137-
AccountID string `json:"accountId"`
138-
CognitoIdentityID string `json:"cognitoIdentityId"`
139-
Caller string `json:"caller"`
140-
APIKey string `json:"apiKey"`
141-
APIKeyID string `json:"apiKeyId"`
142-
AccessKey string `json:"accessKey"`
136+
CognitoIdentityPoolID string `json:"cognitoIdentityPoolId,omitempty"`
137+
AccountID string `json:"accountId,omitempty"`
138+
CognitoIdentityID string `json:"cognitoIdentityId,omitempty"`
139+
Caller string `json:"caller,omitempty"`
140+
APIKey string `json:"apiKey,omitempty"`
141+
APIKeyID string `json:"apiKeyId,omitempty"`
142+
AccessKey string `json:"accessKey,omitempty"`
143143
SourceIP string `json:"sourceIp"`
144-
CognitoAuthenticationType string `json:"cognitoAuthenticationType"`
145-
CognitoAuthenticationProvider string `json:"cognitoAuthenticationProvider"`
146-
UserArn string `json:"userArn"` //nolint: stylecheck
144+
CognitoAuthenticationType string `json:"cognitoAuthenticationType,omitempty"`
145+
CognitoAuthenticationProvider string `json:"cognitoAuthenticationProvider,omitempty"`
146+
UserArn string `json:"userArn,omitempty"` //nolint: stylecheck
147147
UserAgent string `json:"userAgent"`
148-
User string `json:"user"`
148+
User string `json:"user,omitempty"`
149149
}
150150

151151
// APIGatewayWebsocketProxyRequest contains data coming from the API Gateway proxy
152152
type APIGatewayWebsocketProxyRequest struct {
153-
Resource string `json:"resource"` // The resource path defined in API Gateway
154-
Path string `json:"path"` // The url path for the caller
153+
Resource string `json:"resource,omitempty"` // The resource path defined in API Gateway
154+
Path string `json:"path,omitempty"` // The url path for the caller
155155
HTTPMethod string `json:"httpMethod,omitempty"`
156-
Headers map[string]string `json:"headers"`
157-
MultiValueHeaders map[string][]string `json:"multiValueHeaders"`
158-
QueryStringParameters map[string]string `json:"queryStringParameters"`
159-
MultiValueQueryStringParameters map[string][]string `json:"multiValueQueryStringParameters"`
160-
PathParameters map[string]string `json:"pathParameters"`
161-
StageVariables map[string]string `json:"stageVariables"`
156+
Headers map[string]string `json:"headers,omitempty"`
157+
MultiValueHeaders map[string][]string `json:"multiValueHeaders,omitempty"`
158+
QueryStringParameters map[string]string `json:"queryStringParameters,omitempty"`
159+
MultiValueQueryStringParameters map[string][]string `json:"multiValueQueryStringParameters,omitempty"`
160+
PathParameters map[string]string `json:"pathParameters,omitempty"`
161+
StageVariables map[string]string `json:"stageVariables,omitempty"`
162162
RequestContext APIGatewayWebsocketProxyRequestContext `json:"requestContext"`
163-
Body string `json:"body"`
164-
IsBase64Encoded bool `json:"isBase64Encoded,omitempty"`
163+
Body string `json:"body,omitempty"`
164+
IsBase64Encoded bool `json:"isBase64Encoded"`
165165
}
166166

167167
// APIGatewayWebsocketProxyRequestContext contains the information to identify
168168
// the AWS account and resources invoking the Lambda function. It also includes
169169
// Cognito identity information for the caller.
170170
type APIGatewayWebsocketProxyRequestContext struct {
171-
AccountID string `json:"accountId"`
172-
ResourceID string `json:"resourceId"`
173-
Stage string `json:"stage"`
174-
RequestID string `json:"requestId"`
175-
Identity APIGatewayRequestIdentity `json:"identity"`
176-
ResourcePath string `json:"resourcePath"`
177-
Authorizer interface{} `json:"authorizer"`
178-
HTTPMethod string `json:"httpMethod"`
179-
APIID string `json:"apiId"` // The API Gateway rest API Id
180-
ConnectedAt int64 `json:"connectedAt"`
181-
ConnectionID string `json:"connectionId"`
182-
DomainName string `json:"domainName"`
183-
Error string `json:"error"`
184-
EventType string `json:"eventType"`
185-
ExtendedRequestID string `json:"extendedRequestId"`
186-
IntegrationLatency string `json:"integrationLatency"`
187-
MessageDirection string `json:"messageDirection"`
188-
MessageID interface{} `json:"messageId"`
189-
RequestTime string `json:"requestTime"`
190-
RequestTimeEpoch int64 `json:"requestTimeEpoch"`
191-
RouteKey string `json:"routeKey"`
192-
Status string `json:"status"`
171+
AccountID string `json:"accountId,omitempty"`
172+
ResourceID string `json:"resourceId,omitempty"`
173+
Stage string `json:"stage"`
174+
RequestID string `json:"requestId"`
175+
Identity APIGatewayRequestIdentity `json:"identity"`
176+
ResourcePath string `json:"resourcePath,omitempty"`
177+
Authorizer interface{} `json:"authorizer,omitempty"`
178+
HTTPMethod string `json:"httpMethod,omitempty"`
179+
APIID string `json:"apiId"` // The API Gateway rest API Id
180+
ConnectedAt int64 `json:"connectedAt"`
181+
ConnectionID string `json:"connectionId"`
182+
DomainName string `json:"domainName"`
183+
Error string `json:"error,omitempty"`
184+
EventType string `json:"eventType"`
185+
ExtendedRequestID string `json:"extendedRequestId"`
186+
IntegrationLatency string `json:"integrationLatency,omitempty"`
187+
MessageDirection string `json:"messageDirection"`
188+
MessageID interface{} `json:"messageId,omitempty"`
189+
RequestTime string `json:"requestTime"`
190+
RequestTimeEpoch int64 `json:"requestTimeEpoch"`
191+
RouteKey string `json:"routeKey"`
192+
Status string `json:"status,omitempty"`
193+
DisconnectStatusCode int64 `json:"disconnectStatusCode,omitempty"`
194+
DisconnectReason *string `json:"disconnectReason,omitempty"`
193195
}
194196

195197
// APIGatewayCustomAuthorizerRequestTypeRequestIdentity contains identity information for the request caller including certificate information if using mTLS.

events/apigw_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,52 @@ func TestApiGatewayWebsocketRequestMarshaling(t *testing.T) {
150150
assert.JSONEq(t, string(inputJSON), string(outputJSON))
151151
}
152152

153+
func TestApiGatewayWebsocketRequestSendMessageMarshaling(t *testing.T) {
154+
155+
// read json from file
156+
inputJSON, err := ioutil.ReadFile("./testdata/apigw-websocket-request-send-message.json")
157+
if err != nil {
158+
t.Errorf("could not open test file. details: %v", err)
159+
}
160+
161+
// de-serialize into Go object
162+
var inputEvent APIGatewayWebsocketProxyRequest
163+
if err := json.Unmarshal(inputJSON, &inputEvent); err != nil {
164+
t.Errorf("could not unmarshal event. details: %v", err)
165+
}
166+
167+
// serialize to json
168+
outputJSON, err := json.Marshal(inputEvent)
169+
if err != nil {
170+
t.Errorf("could not marshal event. details: %v", err)
171+
}
172+
173+
assert.JSONEq(t, string(inputJSON), string(outputJSON))
174+
}
175+
176+
func TestApiGatewayWebsocketRequestDisconnectMarshaling(t *testing.T) {
177+
178+
// read json from file
179+
inputJSON, err := ioutil.ReadFile("./testdata/apigw-websocket-request-disconnect.json")
180+
if err != nil {
181+
t.Errorf("could not open test file. details: %v", err)
182+
}
183+
184+
// de-serialize into Go object
185+
var inputEvent APIGatewayWebsocketProxyRequest
186+
if err := json.Unmarshal(inputJSON, &inputEvent); err != nil {
187+
t.Errorf("could not unmarshal event. details: %v", err)
188+
}
189+
190+
// serialize to json
191+
outputJSON, err := json.Marshal(inputEvent)
192+
if err != nil {
193+
t.Errorf("could not marshal event. details: %v", err)
194+
}
195+
196+
assert.JSONEq(t, string(inputJSON), string(outputJSON))
197+
}
198+
153199
func TestApiGatewayWebsocketRequestMalformedJson(t *testing.T) {
154200
test.TestMalformedJson(t, APIGatewayWebsocketProxyRequest{})
155201
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"headers": {
3+
"Host": "dl7ptocha9.execute-api.ap-northeast-1.amazonaws.com",
4+
"x-api-key": "",
5+
"X-Forwarded-For": "",
6+
"x-restapi": ""
7+
},
8+
"multiValueHeaders": {
9+
"Host": [ "dl7ptocha9.execute-api.ap-northeast-1.amazonaws.com" ],
10+
"x-api-key": [ "" ],
11+
"X-Forwarded-For": [ "" ],
12+
"x-restapi": [ "" ]
13+
},
14+
"requestContext": {
15+
"routeKey": "$disconnect",
16+
"disconnectStatusCode": 1001,
17+
"eventType": "DISCONNECT",
18+
"extendedRequestId": "R1koeHsUtjMFbRw=",
19+
"requestTime": "20/Jan/2024:11:55:08 +0000",
20+
"messageDirection": "IN",
21+
"disconnectReason": "",
22+
"stage": "prod",
23+
"connectedAt": 1705751697419,
24+
"requestTimeEpoch": 1705751708326,
25+
"identity": {
26+
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
27+
"sourceIp": "49.105.91.154"
28+
},
29+
"requestId": "R1koeHsUtjMFbRw=",
30+
"domainName": "dl7ptocha9.execute-api.ap-northeast-1.amazonaws.com",
31+
"connectionId": "R1kmxc2VNjMCFIA=",
32+
"apiId": "dl7ptocha9"
33+
},
34+
"isBase64Encoded": false
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"requestContext": {
3+
"routeKey": "$default",
4+
"messageId": "R1knPc2ntjMCFIA=",
5+
"eventType": "MESSAGE",
6+
"extendedRequestId": "R1knPH17NjMFftw=",
7+
"requestTime": "20/Jan/2024:11:55:00 +0000",
8+
"messageDirection": "IN",
9+
"stage": "prod",
10+
"connectedAt": 1705751697419,
11+
"requestTimeEpoch": 1705751700453,
12+
"identity": {
13+
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
14+
"sourceIp": "49.105.91.154"
15+
},
16+
"requestId": "R1knPH17NjMFftw=",
17+
"domainName": "dl7ptocha9.execute-api.ap-northeast-1.amazonaws.com",
18+
"connectionId": "R1kmxc2VNjMCFIA=",
19+
"apiId": "gy415nuibc"
20+
},
21+
"body": "{\r\n\t\"a\": 1\r\n}",
22+
"isBase64Encoded": false
23+
}

events/testdata/apigw-websocket-request.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@
9797
"extendedRequestId": "TWegAcC4EowCHnA=",
9898
"integrationLatency": "123",
9999
"messageDirection": "IN",
100-
"messageId": null,
101100
"requestTime": "07/Jan/2019:09:20:57 +0000",
102101
"requestTimeEpoch": 0,
103102
"routeKey": "$connect",
104103
"status": "*"
105104
},
106-
"body": "{\r\n\t\"a\": 1\r\n}"
105+
"body": "{\r\n\t\"a\": 1\r\n}",
106+
"isBase64Encoded": false
107107
}

0 commit comments

Comments
 (0)