Post

How I Build a Serverless Chan Forum

Intro

This post is intended to share an experiment I performed trying to create a chan forum. As a personal goal, I had the idea to build everything in just three days. Forant Anonymous Topics is based/inspired by the famous 4Chan. In it, users post random topics anonymously, where the newest ones are above the old ones. However, on Forant Anonymous Topics, daily, topics are automatically deleted. The interface is simple and, image upload is not allowed. Creating it was 100% free for testing (Using the AWS Cloud’s free tier services.)

Flowchart and overview

The application was created using ASP.NET, which allows the creation of dynamic pages, together with AWS Cloud, allowing the creation of REST APIs (API Gateway), a NoSQL database (DynamoDB), and Lambdas (Python 3.8). The application’s core is the data requests for the API Gateway using the Services.cs class. The REST APIs make a call to a specific lambda of put, get, or comment. With the information received, it is possible to create dynamic pages, listing comments, topics, authors… Using a Topic object, which shapes the elements brought from the database, which has the following structure:

ParameterValue
IdA Guid that looks like this: be5d82ffff744f86ac817c39dc0d8582
NicknameField filled in by the user at the time of topic creation
TitleTopic title, filled in by the user at the time of topic creation
TextThe content of the topic, filled in by the user at the time of topic creation
CommentsAnonymous comments on the topic in question

And daily, using the AWS Cloud’s EventBridge service, the daily-remover lambda is called, completely cleaning the database (DynamoDB).

For better visualization of the communication, see the flowchart: 4TAN - Frame 3

ASP.NET Technology

“ASP.NET offers three frameworks for building Web applications: Web Forms, ASP.NET MVC, and ASP.NET Web Pages. All three frameworks are stable and mature, and you can build great web apps with any of them. Regardless of which framework you choose, you’ll get all the benefits and features of ASP.NET everywhere. Each framework targets a different development style. What you choose depends on a combination of your programming assets (development knowledge, skills, and experience), the type of application you are building, and the development approach you are familiar with. Below is an overview of each of the structures and some ideas on how to choose between them. If you prefer an introduction to the video, see Making Sites With ASP.net and What Are Web Tools?” - Explanation taken from Microsoft documentation.

Why?

  • Separation of business rules and logic from the presentation itself;
  • Greater control over the application;
  • Enables isolated maintenance on both sides;
  • Ease of integration with JavaScript libraries like jQuery;
  • The HTML served to the browser is generated by a separate, replaceable engine;
  • Control over requests (URL).

Binding Method

An example of binding is the one done for our Nickname field:

HTML:

1
<input type="text" asp-for="Nickname" placeholder="Your Nick">

Controller:

1
[BindProperty] public string Nickname { get; set; } = "";

So when the post method is called the values ​​are mapped to the string Nickname. “This means action methods will have one or more parameters and those parameters will receive their values ​​from the model binding framework.” http://www.binaryintellect.net/articles/85fb9a1d-6b0d-4d1f-932c-555bd27ba401.aspx

Services.cs

It is used to create and send HTTP requests in a fully async way. We can see an example when creating a new topic:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public async Task PutTopic(Topic newTopic)
{
   WebRequest request = WebRequest.Create ("https://url.execute-api.us-east-2.amazonaws.com/default/topic-setter");
   request.Method = "POST";
   request.ContentType = "application/json";
   request.Headers.Add("x-api-key","key");

   using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
   {
       string json = JsonConvert.SerializeObject(newTopic);
       await streamWriter.WriteAsync(json);
   }

   await request.GetResponseAsync();
}

It makes a request to the topic-setter, which creates a new topic in DynamoDB and returns a statuscode 200.

Lambdas

Why

  • There’s No Infrastructure to Manage
  • AWS Lambda Has Strong Security Support
  • AWS Lambdas Are Event Driven
  • You Only Pay for What You Use

To create the lambdas follow these steps:

  1. Inside of console, look for the lambda service

  2. Go to “Create a function”


  1. Set the following informations:

    1
    2
    3
    4
    5
    6
    7
    
    1.  Function Name
    
    2.  Use architecture x86_64
    
    3.  Choose the language to use to write your function. (Python3.8)
    
    4.  To create roles, let it create automatically and change it later
    
  2. After creating it, go to Configurations > Permissions > Click on your Role
  3. Add policies > add “AmazonDynamoDBFullAccess”

Code

Topic-Getter

In this lambda we can have two different types of responses. The first one, sent a “Id = /” in the request body, to receive all topics. The second sent a valid id thus receiving a specific topic. The code can be seen at: https://github.com/GabrielPrzybysz/forant-anonymous-topics/blob/main/aws-lambdas/topic-getter.py

Topic-Setter

It receives the following object serialized by the Newtonsoft library in its body:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Topic
{
	public Topic(string id, string author, string title, string text , List<string> comments)
	{
		Id = id;

		Author = author;
		Title = title;
		Text = text;
		Comments = comments;
	}

	public string Id { get; set; }

	public string Author { get; set; }

	public string Title { get; set; }

	public string Text { get; set; }

	public List<string> Comments { get; set; }
}

Thus, performing a put operation for DynamoDB, adding one more daily topic.

Daily-Remover

It scans the entire dynamo table daily and using boto3’s batch_writer feature, it deletes item by item

API Gateway

All my REST APIs have an api-key, thus making the process more secure, and also in them, there is a limit of requests per second, thus avoiding any attack of multiple requests.

  1. In the tab of your lambda, look for the “Add Trigger”


  1. When choosing the trigger configuration, choose “API Gateway”


  1. Configure following the following image


Author: Gabriel Przybysz Gonçalves Júnior - Backend Programmer
GitHub: https://github.com/GabrielPrzybysz/forant-anonymous-topics

Youtube Example: https://www.youtube.com/watch?v=Iq_ghoTfu24

This post is licensed under CC BY 4.0 by the author.