Skip to content

A server-side rendering article sharing website developed by Go. No frontend framework used.

Notifications You must be signed in to change notification settings

cwhuang29/article-sharing-website

Repository files navigation

article-sharing-website

An article sharing website developed by Go.

Here is a live demo: inews (hosting on AWS EC2 with Load Balancer, Route 53, SES, Certificate Manager.)
The website has been closed due to the cost of maintenance being too high. See the Demo section at the end of the README.

Overview

I choose gin as the backend web framework for its simplicity and high performance (it is also the most popular framework in Go, see Top Go Web Frameworks).

For database ORM, I choose gorm. It is a full-featured ORM with great community support and easy to follow documentation. Besides, if you choose sqlite as the database driver, then you can get rid of the setting database burden (the data will be stored in a file tmp.db in the root of project) and focus on the backend development.

If you are a novice to the database with no idea about the many-to-many relationship, the databases/bookmark.go is a good example. I utilize many-to-many relationship to implement features such as searching articles with tags and bookmarking articles.

Architecture

The following diagram illustrates the architecture I built on AWS:

                                             │
                                             ▼
                      ┌─────────────────────────────────────────────┐
                      │   ALB (application load balancer, layer 7)  │
                      └─────────────────────────────────────────────┘
                                             │
             ┌───────────────────────────────────────────────────────────────┐
             │                               │                               │
             ▼                               ▼                               ▼
┌───────────────────────────┐  ┌───────────────────────────┐  ┌───────────────────────────┐ 
│  Listener (HTTP, port80)  │  │ Listener (HTTPS, port443) │  │          Listener         │
└───────────────────────────┘  └───────────────────────────┘  └───────────────────────────┘
             │                               │                               │
             ▼                               ▼                               ▼
┌───────────────────────────┐  ┌───────────────────────────┐  ┌───────────────────────────┐
│     Target Group (dev)    │  │    Target Group (prod)    │  │    Target Group (other)   │
│ ┌───────────────────────┐ │  │ ┌───────────────────────┐ │  │                           │
│ │  EC2 (Testing, AZ #1) │ │  │ |      EC2 (AZ #1)      │ │  │                           │
│ └───────────────────────┘ │  │ └───────────────────────┘ │  │           .....           │
│ ┌───────────────────────┐ │  │ ┌───────────────────────┐ │  │                           │
│ │  EC2 (Staging, AZ #1) │ │  │ │      EC2 (AZ #2)      │ │  │                           │
│ └───────────────────────┘ │  │ └───────────────────────┘ │  │                           │
└───────────────────────────┘  └───────────────────────────┘  └───────────────────────────┘
            ▲  │                           ▲  │
            |  ▼                           |  ▼
┌───────────────────────────┐  ┌───────────────────────────┐ 
│                           │  │                           │
│        RDS (MySQL)        │  │        RDS (MySQL)        │ 
│                           │  │                           │
└───────────────────────────┘  └───────────────────────────┘ 

Setup

The credentials are stored in config.yml. There are some environment variables that can be overwritten (inside config/config.go). Environment variables have a WEB_ prefix. You might want to use some of them: WEB_APP_HTTP_PORT, WEB_APP_HTTPS_PORT, WEB_DB_PORT, and WEB_DB_HOST.

The admin users are created by the following mechanism:

  1. Write down their emails in config.yml
  2. Setup web server
  3. Register with these corresponding emails on the website

To send reset password emails, see the Others section.

Local

# Set the env values if needed
# export WEB_APP_HTTP_PORT=8080
# export WEB_APP_HTTPS_PORT=8443
# export WEB_DB_PORT=3306
# export WEB_DB_HOST=127.0.0.1
go run cmd/main.go

Docker

  1. Build
  • Development
docker build . --target builder -t cwhuang29/article-sharing-website:dev
  • Production
docker build . -t cwhuang29/article-sharing-website:prod
  1. Run
  • Database
docker run -d \
    --name db \
    -e MYSQL_DATABASE=inews \
    -e MYSQL_ROOT_PASSWORD=a1234567 \
    -e MYSQL_USER=user01 \
    -e MYSQL_PASSWORD=a1234567 \
    mysql:5.7.32 \
    mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
  • Web server
docker run -d \
    --name web \
    --link db:db \
    -e WEB_APP_HTTP_PORT=80 \
    -e WEB_APP_HTTPS_PORT=443 \
    -e WEB_DB_PORT=3306 \
    -e WEB_DB_HOST=db \
    -e WEB_APP_URL=https://example.com \
    -e WEB_EMAIL_SENDER=<sender email address> \
    -e WEB_EMAIL_REGION=us-east-1
    -p 80:80 \
    -p 443:443 \
    cwhuang29/article-sharing-website:prod

Others

Sending emails via AWS SES

  1. Fill in settings in the email section in config.yml. Sender email address and region can be overwritten by env WEB_EMAIL_SENDER and WEB_EMAIL_REGION respectively.
  2. app.url is mandatory cause the reset password link is based on this value (can be overwritten byWEB_APP_URL)
  3. email.numPerDay and email.numPerSec in config.yml, which represent maximum send quota/rate, is the restrictions imposed by AWS.
  4. AWS retrieves credentials under ~/.aws/credentials. Copy credentials from the AWS web console and create this file with the following content:
[default]
aws_access_key_id=
aws_secret_access_key=
  1. Verify domains and (sender) email addresses on AWS console (see here).
  2. Submit a request to AWS to increase sending limits and move your account out of the Amazon SES sandbox (see here).

Connect to database

Instead of connecting to the database container (which name is db in my case) directly, we can run another MySQL container and query the database container.

docker run -it --rm --link db:db mysql:5.7.32 mysql -hdb -u user01 -pa1234567 inews

Dump database

To dump the database, run

docker exec -it db mysqldump -u user01 -pa1234567 inews > data-`date +"%Y-%m-%d-%H-%M-%S"`.sql

There is some warning messages while dumping out data. To avoid warning, you can run:

docker exec -it db mysqldump -u user01 -pa1234567 --no-tablespaces inews <tables, seperated by space> \
    grep -v "Using a password on the command line interface can be insecure" > data-`date +"%Y-%m-%d-%H-%M-%S"`.sql

SSL/TLS Certificates

Since all cookies are sent only with encrypted requests and responses, you may want to get certificates for localhost. Here is a good example: How to get HTTPS working on your local development environment in 5 minutes. After setting up the certificates, copy server.crt and server.key to the certs/ folder (in the root of the project), and then connect to URL https://localhost.

Install environment on AWS

If you want to host the website on AWS EC2, run the following script to install Docker and MySQL Do note that installing docker takes about 1.5~2 GB space. You might want to create an EC2 with a larger disk space

# Install Docker
sudo yum update -y
sudo amazon-linux-extras install docker
sudo service docker start
sudo usermod -a -G docker ec2-user
# Logout and log back in

# Install MySQL
sudo yum -y install mysql

TODO

  • Register
  • Logout
  • Modify articles
  • Delete articles
  • Optimize Docker builds
  • Pagination
  • Middleware
  • CSRF token
  • Support HTTPS
  • Add an "only administrators can view" option
  • Outline and cover photo for the overview page
  • Reset password
  • Login Throttling
  • Tag-based search
  • Preserve fetched data while going to the previous page
  • Save (bookmark) button
  • Like button
  • Logger
  • Admin overview page (e.g. show statistics)
  • Security issues about uploading files
  • Support CLI
  • Integrate AWS SES to send emails

Demo

Feature - article list

Articles List

Feature - browse

Browse

Feature - edit

Edit

About

A server-side rendering article sharing website developed by Go. No frontend framework used.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published