├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── CommonChat
├── CommonChat.csproj
└── Constants.cs
├── LICENSE
├── OnConnect
├── Function.cs
└── OnConnect.csproj
├── OnDisconnect
├── Function.cs
└── OnDisconnect.csproj
├── README.md
├── SendMessage
├── Function.cs
└── SendMessage.csproj
├── aws-lambda-tools-defaults.json
├── netcore-simple-websockets-chat-app.sln
└── template.yaml
/.gitignore:
--------------------------------------------------------------------------------
1 | ######################################
2 | # Visual Studio per-user settings data
3 | ######################################
4 | *.suo
5 | *.user
6 |
7 | ####################
8 | # Build/Test folders
9 | ####################
10 | **/.vs/
11 | **/bin/
12 | **/obj/
13 | **/TestResults/
14 | **/Temp/
15 | **/NuGet.exe
16 | **/buildlogs/
17 | **/Deployment/
18 | **/packages
19 | **/launchSettings.json
20 |
21 | **/node_modules/
22 | **/TestGenerations/
23 |
24 | **/.vscode
25 | **/.idea
26 | *.userprefs
27 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check [existing open](https://github.com/aws-samples/simple-websockets-chat-app/issues), or [recently closed](https://github.com/aws-samples/simple-websockets-chat-app/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *master* branch.
27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 3. Ensure local tests pass.
35 | 4. Commit to your fork using clear commit messages.
36 | 5. Send us a pull request, answering any default questions in the pull request interface.
37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
38 |
39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
41 |
42 |
43 | ## Finding contributions to work on
44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-samples/simple-websockets-chat-app/labels/help%20wanted) issues is a great place to start.
45 |
46 |
47 | ## Code of Conduct
48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50 | opensource-codeofconduct@amazon.com with any additional questions or comments.
51 |
52 |
53 | ## Security issue notifications
54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
55 |
56 |
57 | ## Licensing
58 |
59 | See the [LICENSE](https://github.com/aws-samples/simple-websockets-chat-app/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
60 |
61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
--------------------------------------------------------------------------------
/CommonChat/CommonChat.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CommonChat/Constants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace CommonChat
4 | {
5 | public class Constants
6 | {
7 | public static readonly string TABLE_NAME = System.Environment.GetEnvironmentVariable("TABLE_NAME");
8 |
9 | public const string ConnectionIdField = "connectionId";
10 | }
11 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
--------------------------------------------------------------------------------
/OnConnect/Function.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | using Amazon.Lambda.Core;
7 | using Amazon.Lambda.APIGatewayEvents;
8 |
9 | using Amazon.DynamoDBv2;
10 | using Amazon.DynamoDBv2.Model;
11 |
12 | using CommonChat;
13 | using Newtonsoft.Json.Linq;
14 |
15 | // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
16 | [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
17 |
18 |
19 | namespace OnConnect
20 | {
21 | public class Function
22 | {
23 | IAmazonDynamoDB _ddbClient = new AmazonDynamoDBClient();
24 |
25 | public async Task FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
26 | {
27 | try
28 | {
29 | // Using JObject instead of APIGatewayProxyRequest till APIGatewayProxyRequest gets updated with DomainName and ConnectionId
30 | var connectionId = request.RequestContext.ConnectionId;
31 | context.Logger.LogLine($"ConnectionId: {connectionId}");
32 |
33 | var ddbRequest = new PutItemRequest
34 | {
35 | TableName = Constants.TABLE_NAME,
36 | Item = new Dictionary
37 | {
38 | {Constants.ConnectionIdField, new AttributeValue{ S = connectionId}}
39 | }
40 | };
41 |
42 | await _ddbClient.PutItemAsync(ddbRequest);
43 |
44 | return new APIGatewayProxyResponse
45 | {
46 | StatusCode = 200,
47 | Body = "Connected."
48 | };
49 | }
50 | catch (Exception e)
51 | {
52 | context.Logger.LogLine("Error connecting: " + e.Message);
53 | context.Logger.LogLine(e.StackTrace);
54 | return new APIGatewayProxyResponse
55 | {
56 | StatusCode = 500,
57 | Body = $"Failed to connect: {e.Message}"
58 | };
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/OnConnect/OnConnect.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 | true
6 | Lambda
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/OnDisconnect/Function.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | using Amazon.Lambda.Core;
7 | using Amazon.Lambda.APIGatewayEvents;
8 |
9 | using Amazon.DynamoDBv2;
10 | using Amazon.DynamoDBv2.Model;
11 |
12 | using CommonChat;
13 | using Newtonsoft.Json.Linq;
14 |
15 | // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
16 | [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
17 |
18 | namespace OnDisconnect
19 | {
20 | public class Function
21 | {
22 | IAmazonDynamoDB _ddbClient = new AmazonDynamoDBClient();
23 |
24 | public async Task FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
25 | {
26 | try
27 | {
28 | // Using JObject instead of APIGatewayProxyRequest till APIGatewayProxyRequest gets updated with DomainName and ConnectionId
29 | var connectionId = request.RequestContext.ConnectionId;
30 | context.Logger.LogLine($"ConnectionId: {connectionId}");
31 |
32 | var ddbRequest = new DeleteItemRequest
33 | {
34 | TableName = Constants.TABLE_NAME,
35 | Key = new Dictionary
36 | {
37 | {Constants.ConnectionIdField, new AttributeValue {S = connectionId}}
38 | }
39 | };
40 |
41 | await _ddbClient.DeleteItemAsync(ddbRequest);
42 |
43 | return new APIGatewayProxyResponse
44 | {
45 | StatusCode = 200,
46 | Body = "Disconnected."
47 | };
48 | }
49 | catch (Exception e)
50 | {
51 | context.Logger.LogLine("Error disconnecting: " + e.Message);
52 | context.Logger.LogLine(e.StackTrace);
53 | return new APIGatewayProxyResponse
54 | {
55 | StatusCode = 500,
56 | Body = $"Failed to disconnect: {e.Message}"
57 | };
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/OnDisconnect/OnDisconnect.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 | true
6 | Lambda
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # .NET Core Port of simple-websockets-chat-app
2 |
3 | This is a .NET Core port of the [simple-websockets-chat-app](https://github.com/aws-samples/simple-websockets-chat-app) sample for AWS Lambda. For more information [Announcing WebSocket APIs in Amazon API Gateway](https://aws.amazon.com/blogs/compute/announcing-websocket-apis-in-amazon-api-gateway/) blog post.
4 |
5 | ## Deploy
6 |
7 | To deploy this sample use the the [AWS Lambda .NET Core Global Tool](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/).
8 |
9 | To install the global tool execute the command. Be sure at least version 3.1.0 of the tool is installed.
10 |
11 | ```
12 | dotnet tool install -g Amazon.Lambda.Tools
13 | ```
14 |
15 | Then to deploy execute the following command in the root directory of this repository.
16 | ```
17 | dotnet lambda deploy-serverless --region --s3-bucket
18 | ```
19 |
--------------------------------------------------------------------------------
/SendMessage/Function.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | using Amazon.Lambda.Core;
10 | using Amazon.Lambda.APIGatewayEvents;
11 |
12 | using Amazon.DynamoDBv2;
13 | using Amazon.DynamoDBv2.Model;
14 | using Amazon.ApiGatewayManagementApi;
15 | using Amazon.ApiGatewayManagementApi.Model;
16 | using Amazon.Runtime;
17 | using CommonChat;
18 | using Newtonsoft.Json;
19 | using Newtonsoft.Json.Linq;
20 |
21 | // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
22 | [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
23 |
24 | namespace SendMessage
25 | {
26 | public class Function
27 | {
28 | IAmazonDynamoDB _ddbClient = new AmazonDynamoDBClient();
29 |
30 | public async Task FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
31 | {
32 | try
33 | {
34 | // Using JObject instead of APIGatewayProxyRequest till APIGatewayProxyRequest gets updated with DomainName and ConnectionId
35 | var domainName = request.RequestContext.DomainName;
36 | var stage = request.RequestContext.Stage;
37 | var endpoint = $"https://{domainName}/{stage}";
38 | context.Logger.LogLine($"API Gateway management endpoint: {endpoint}");
39 |
40 | var message = JsonConvert.DeserializeObject(request.Body);
41 | var data = message["data"]?.ToString();
42 |
43 | var stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(data));
44 |
45 | var scanRequest = new ScanRequest
46 | {
47 | TableName = Constants.TABLE_NAME,
48 | ProjectionExpression = Constants.ConnectionIdField
49 | };
50 |
51 | var scanResponse = await _ddbClient.ScanAsync(scanRequest);
52 |
53 | var apiClient = new AmazonApiGatewayManagementApiClient(new AmazonApiGatewayManagementApiConfig
54 | {
55 | ServiceURL = endpoint
56 | });
57 |
58 | var count = 0;
59 | foreach (var item in scanResponse.Items)
60 | {
61 | var connectionId = item[Constants.ConnectionIdField].S;
62 |
63 |
64 | var postConnectionRequest = new PostToConnectionRequest
65 | {
66 | ConnectionId = connectionId,
67 | Data = stream
68 | };
69 |
70 | try
71 | {
72 | context.Logger.LogLine($"Post to connection {count}: {connectionId}");
73 | stream.Position = 0;
74 | await apiClient.PostToConnectionAsync(postConnectionRequest);
75 | count++;
76 | }
77 | catch (AmazonServiceException e)
78 | {
79 | // API Gateway returns a status of 410 GONE when the connection is no
80 | // longer available. If this happens, we simply delete the identifier
81 | // from our DynamoDB table.
82 | if (e.StatusCode == HttpStatusCode.Gone)
83 | {
84 | var ddbDeleteRequest = new DeleteItemRequest
85 | {
86 | TableName = Constants.TABLE_NAME,
87 | Key = new Dictionary
88 | {
89 | {Constants.ConnectionIdField, new AttributeValue {S = connectionId}}
90 | }
91 | };
92 |
93 | context.Logger.LogLine($"Deleting gone connection: {connectionId}");
94 | await _ddbClient.DeleteItemAsync(ddbDeleteRequest);
95 | }
96 | else
97 | {
98 | context.Logger.LogLine($"Error posting message to {connectionId}: {e.Message}");
99 | context.Logger.LogLine(e.StackTrace);
100 | }
101 | }
102 | }
103 |
104 | return new APIGatewayProxyResponse
105 | {
106 | StatusCode = 200,
107 | Body = "Data send to " + count + " connection" + (count == 1 ? "" : "s")
108 | };
109 | }
110 | catch (Exception e)
111 | {
112 | context.Logger.LogLine("Error disconnecting: " + e.Message);
113 | context.Logger.LogLine(e.StackTrace);
114 | return new APIGatewayProxyResponse
115 | {
116 | StatusCode = 500,
117 | Body = $"Failed to send message: {e.Message}"
118 | };
119 | }
120 |
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/SendMessage/SendMessage.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp2.1
5 | true
6 | Lambda
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/aws-lambda-tools-defaults.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "region" : "",
4 | "s3-bucket" : "",
5 | "template" : "template.yaml",
6 | "stack-name" : ""
7 | }
--------------------------------------------------------------------------------
/netcore-simple-websockets-chat-app.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OnConnect", "OnConnect\OnConnect.csproj", "{1BD72495-6305-4EC3-A788-3F339E3FFF88}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OnDisconnect", "OnDisconnect\OnDisconnect.csproj", "{6EC3BB68-0C96-4535-AC3B-929310C94E93}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SendMessage", "SendMessage\SendMessage.csproj", "{1492235A-CC99-4641-8293-4D33CA74F3EE}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommonChat", "CommonChat\CommonChat.csproj", "{EE382036-9E15-4811-A063-8C4671ACD69F}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6E3022A8-9F87-4ABC-8D6D-94ADBEACDE24}"
15 | ProjectSection(SolutionItems) = preProject
16 | README.md = README.md
17 | template.yaml = template.yaml
18 | EndProjectSection
19 | EndProject
20 | Global
21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
22 | Debug|Any CPU = Debug|Any CPU
23 | Release|Any CPU = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {1BD72495-6305-4EC3-A788-3F339E3FFF88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {1BD72495-6305-4EC3-A788-3F339E3FFF88}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {1BD72495-6305-4EC3-A788-3F339E3FFF88}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {1BD72495-6305-4EC3-A788-3F339E3FFF88}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {6EC3BB68-0C96-4535-AC3B-929310C94E93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {6EC3BB68-0C96-4535-AC3B-929310C94E93}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {6EC3BB68-0C96-4535-AC3B-929310C94E93}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {6EC3BB68-0C96-4535-AC3B-929310C94E93}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {1492235A-CC99-4641-8293-4D33CA74F3EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {1492235A-CC99-4641-8293-4D33CA74F3EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {1492235A-CC99-4641-8293-4D33CA74F3EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {1492235A-CC99-4641-8293-4D33CA74F3EE}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {EE382036-9E15-4811-A063-8C4671ACD69F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {EE382036-9E15-4811-A063-8C4671ACD69F}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {EE382036-9E15-4811-A063-8C4671ACD69F}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {EE382036-9E15-4811-A063-8C4671ACD69F}.Release|Any CPU.Build.0 = Release|Any CPU
42 | EndGlobalSection
43 | GlobalSection(SolutionProperties) = preSolution
44 | HideSolutionNode = FALSE
45 | EndGlobalSection
46 | GlobalSection(ExtensibilityGlobals) = postSolution
47 | SolutionGuid = {0857701F-6581-4441-B2B1-277D17FF5F99}
48 | EndGlobalSection
49 | EndGlobal
50 |
--------------------------------------------------------------------------------
/template.yaml:
--------------------------------------------------------------------------------
1 | AWSTemplateFormatVersion: '2010-09-09'
2 | Transform: AWS::Serverless-2016-10-31
3 | Description: >
4 | .NET Core port of simple-websockets-chat-app https://github.com/aws-samples/simple-websockets-chat-app
5 |
6 |
7 | Parameters:
8 | TableName:
9 | Type: String
10 | Default: 'simplechat_connections'
11 | Description: (Required) The name of the new DynamoDB to store connection identifiers for each connected clients. Minimum 3 characters
12 | MinLength: 3
13 | MaxLength: 50
14 | AllowedPattern: ^[A-Za-z_]+$
15 | ConstraintDescription: 'Required. Can be characters and underscore only. No numbers or special characters allowed.'
16 |
17 | Resources:
18 | ConnectionsTable:
19 | Type: AWS::DynamoDB::Table
20 | Properties:
21 | AttributeDefinitions:
22 | - AttributeName: "connectionId"
23 | AttributeType: "S"
24 | KeySchema:
25 | - AttributeName: "connectionId"
26 | KeyType: "HASH"
27 | ProvisionedThroughput:
28 | ReadCapacityUnits: 5
29 | WriteCapacityUnits: 5
30 | SSESpecification:
31 | SSEEnabled: True
32 | TableName: !Ref TableName
33 |
34 | OnConnectFunction:
35 | Type: AWS::Serverless::Function
36 | Properties:
37 | CodeUri: OnConnect/
38 | Handler: OnConnect::OnConnect.Function::FunctionHandler
39 | MemorySize: 256
40 | Timeout: 30
41 | Runtime: dotnetcore2.1
42 | Environment:
43 | Variables:
44 | TABLE_NAME: !Ref TableName
45 | Policies:
46 | - DynamoDBCrudPolicy:
47 | TableName: !Ref TableName
48 |
49 | OnDisconnectFunction:
50 | Type: AWS::Serverless::Function
51 | Properties:
52 | CodeUri: OnDisconnect/
53 | Handler: OnDisconnect::OnDisconnect.Function::FunctionHandler
54 | MemorySize: 256
55 | Timeout: 30
56 | Runtime: dotnetcore2.1
57 | Environment:
58 | Variables:
59 | TABLE_NAME: !Ref TableName
60 | Policies:
61 | - DynamoDBCrudPolicy:
62 | TableName: !Ref TableName
63 |
64 | SendMessageFunction:
65 | Type: AWS::Serverless::Function
66 | Properties:
67 | CodeUri: SendMessage/
68 | Handler: SendMessage::SendMessage.Function::FunctionHandler
69 | MemorySize: 256
70 | Timeout: 30
71 | Runtime: dotnetcore2.1
72 | Environment:
73 | Variables:
74 | TABLE_NAME: !Ref TableName
75 | Policies:
76 | - DynamoDBCrudPolicy:
77 | TableName: !Ref TableName
78 | - Statement:
79 | - Effect: Allow
80 | Action:
81 | - 'execute-api:ManageConnections'
82 | Resource:
83 | - 'arn:aws:execute-api:*:*:*/@connections/*'
84 |
85 | Outputs:
86 | ConnectionsTableArn:
87 | Description: "Connections table ARN"
88 | Value: !GetAtt ConnectionsTable.Arn
89 |
90 | OnConnectFunctionArn:
91 | Description: "OnConnect function ARN"
92 | Value: !GetAtt OnConnectFunction.Arn
93 |
94 | OnDisconnectFunctionArn:
95 | Description: "OnDisconnect function ARN"
96 | Value: !GetAtt OnDisconnectFunction.Arn
97 |
98 | SendMessageFunctionArn:
99 | Description: "SendMessage function ARN"
100 | Value: !GetAtt SendMessageFunction.Arn
--------------------------------------------------------------------------------