Skip to content

Partial implementation of the RealWorld Example App Backend with Actix Web and PostgreSQL

License

Notifications You must be signed in to change notification settings

corrieriluca/realworld-actix-web

Repository files navigation

RealWorld Example App

codecov mit rust

Actix Web codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld spec and API.

Demo    RealWorld

This codebase was created to demonstrate a fully fledged fullstack application named Conduit (Medium-like) built with Actix Web (4.0) including CRUD operations, authentication, routing, pagination, and more.

For more information on how to this works with other frontends/backends, head over to the RealWorld repo.

Other tools used

Table of contents

Introduction

This project is a partial implementation of the RealWorld spec.

I aimed to use as much as good practices as I could from the Rust community. I also extensively used functional and unit testing in order to have a great code coverage.

GitHub Actions is used to test the whole project, audit security of supply chain and continuously deliver containers.

What is implemented is the following:

  • JWT Authentication
  • Users API (Registration, Login, Update)
  • Profiles API (Get, Follow, Unfollow)
  • Articles API (List, Feed, Comments, Tags...)

Getting started

🔨 With Cargo and Docker (recommended)

Your first need to install the SQLx CLI:

cargo install sqlx-cli --no-default-features --features rustls,postgres

You need PostgreSQL running somewhere, and to run migrations on it. To run on localhost, Docker is the preferred way:

docker run \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=password \
  -e POSTGRES_DB=conduit \
  -p 5432:5432 \
  -d postgres:14 \
  postgres -N 1000

sqlx database create
sqlx migrate run

💡 Tip: For faster deployment you can use the dev_env.sh script.

Finally you can run the API on port 8080:

cargo run

And in another terminal (or in Postman):

curl -i -X POST http://127.0.0.1:8080/api/users \
    -H "Content-Type: application/json" \
    --data '{"user":{"username":"john","email":"[email protected]","password":"test1234"}}'

🧪 Run Tests

Make sure a database a Postgres database is running on localhost.

Just run:

cargo test

📦 With Docker Compose

Running with Docker Compose is fairly simple but not very flexible during development (requires to build the API image for each change of the source code).

Just go into the docker folder, and run the stack:

cd docker/
docker compose up -d

The API will be exposed on port 8080, you can run your own tests with tools such as curl or Postman.

How does it work?

⚙️ Configuration files

The config crate is used to provide a convenient layered configuration system (satisfies the third of the 12-factor).

The config files are written in YAML and are placed under the configuration folder in the same directory as the app.

You can see an example of layers with the base.yml file which contains a default listening port and credentials for the database, and the local.yml and production.yml that overrides some settings from the base as well as adding others (such as the listening address).

Config values can also be overriden with environment variables (highest precedence) following this naming convention: CONDUIT__<settings-category>__<setting>.

Example: override the DB hostname with CONDUIT__DATABASE__HOST.

🔑 Authentication middleware

Almost all API endpoints require authentication (see RealWorld backend specs) with a JWT token.

This implementation thus makes use of the jsonwebtoken crate coupled with a custom authentication middleware that wraps endpoints which need authentication and validate (or reject) requests before they arrive to the endpoint (adding authenticated user information on top of the request).

Please take a look at the auth.rs source file if you want to know more about the implementation of the middleware, code is documented.

🏛 Code architecture

The source code of this implementation resides in the src directory:

src
├── domain
│   └── ...
├── dtos
│   └── ...
├── handlers
│   └── ...
├── middlewares
│   ├── auth.rs
│   └── mod.rs
├── repositories
│   └── ...
├── configuration.rs
├── lib.rs
├── main.rs
└── startup.rs

The conduit library is exposed through the lib.rs file.

The main.rs source file use the configuration and startup modules to respectively configure and run the application on the desired listening address and port.

The middlewares module contains middlewares such as the Authentication middleware described above.

The repositories module contains exposed functions doing SQL queries to the database.

The dtos module contains Data Transfer Objects (DTOs) for defining input and output types (as struct) of the API.

The domain module contains functions and modules dealing with business logic (input validation, JWT tokens...) for the API.

Finally, the handlers module contains functions and modules for the handlers: the functions mapped to API endpoints. These handlers use the dtos, domain and repositories modules for their internal logic.

🧪 Functional Tests (API)

Under the tests folder, you will find all the functional tests of the application, this means API tests.

Especially, the reqwest, claim and tokio crates are used for HTTP requests, assert functions and background tasks (e.g.: running a test server) respectively.

Before each test, a database with a random name is created, SQLx migrations are runned against it and an API server is launched in background on a random port (this is called a TestApp within the code). The details are in the helpers.rs source file.

Resources & Bibliography

About

Partial implementation of the RealWorld Example App Backend with Actix Web and PostgreSQL

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published