ddimaria/rust-actix-example

Rust/Actix Example

REST server using the Rust language to give you an idea of how it all works

Rust/Actix Example

An Actix 2.0 REST server using the Rust language.

Motivation

Actix Web is a fast, powerful web framework for building web applications in Rust. This project aims to create ergonomic abstractions comparable to frameworks in other languages while attempting to maintain the performance benefits of Actix.

Features

  • Actix 2.x HTTP Server
  • Multi-Database Support (CockroachDB, Postgres, MySQL, Sqlite)
  • JWT Support
  • Async Caching Layer with a Simple API
  • Public and Secure Static File Service
  • Diesel Database Operations are Non-Blocking
  • Filesystem Organized for Scale
  • .env for Local Development
  • Integrated Application State with a Simple API
  • Lazy Static Config struct
  • Built-in Healthcheck (includes cargo version info)
  • Listeners configured for TDD
  • Custom Errors and HTTP Payload/Json Validation
  • Secure Argon2i Password Hashing
  • CORS Support
  • Unit and Integration Tests
  • Test Coverage Reports
  • Dockerfile for Running the Server in a Container
  • TravisCI Integration

Featured Packages

  • Argon2i: Argon2i Password Hasning
  • actix-cors: CORS Support
  • actix-identity: User Authentication
  • actix-redis and redis-async: Async Caching Layer
  • actix-web: Actix Web Server
  • derive_more: Error Formatting
  • diesel: ORM that Operates on Several Databases
  • dotenv: Configuration Loader (.env)
  • envy: Deserializes Environment Variables into a Config Struct
  • jsonwebtoken: JWT encoding/decoding
  • kcov: Coverage Analysis
  • listenfd: Listens for Filesystem Changes
  • rayon: Parallelize
  • r2d2: Database Connection Pooling
  • validator: Validates incoming Json

Installation

Clone the repo and cd into the repo:

Copy over the example .env file:

IMPORTANT: Change .env values for your setup, paying special attention to the salt and various keys.

After you set the DATABASE value in .env, you'll need it to match the default value in the features section in Cargo.toml with the DATABASE value in .env:

note: Only supply a SINGLE database in the default array.

Next, you'll need to install the Diesel CLI:

If you run into errors, see http://diesel.rs/guides/getting-started/

Now run the migrations via the Diesel CLI:

Running the Server

To startup the server:

Autoreloading

To startup the server and autoreload on code changes:

Tests

Integration tests are in the /src/tests folder. There are helper functions to make testing the API straightforward. For example, if we want to test the GET /api/v1/user route:

Using the Actix test server, the request is sent and the response is asserted for a successful response:

assert!(response.status().is_success());

Similarly, to test a POST route:

Running Tests

To run all of the tests:

Test Covearage

I created a repo on DockerHub that I'll update with each Rust version (starting at 1.37), whose tags will match the Rust version.

In the root of the project:

note: coverage takes a long time to run (up to 30 mins).

You can view the HTML output of the report at target/cov/index.html

Docker

To build a Docker image of the application:

Once the image is built, you can run the container in port 3000:

Public Static Files

Static files are served up from the /static folder. Directory listing is turned off. Index files are supported (index.html).

Example:

Secure Static Files

To serve static files to authenticated users only, place them in the /static-secure folder. These files are referenced using the root-level /secure path.

Example:

Application State

A shared, mutable hashmap is automatically added to the server. To invoke this data in a handler, simply add data: AppState<'_, String> to the function signature.

Helper Functions

get<T>(data: AppState<T>, key: &str) -> Option<T>

Retrieves a copy of the entry in application state by key.

Example:

set<T>(data: AppState<T>, key: &str, value: T) -> Option<T>

Inserts or updates an entry in application state.

Example:

delete<T>(data: AppState<T>, key: &str) -> Option<T>

Deletes an entry in application state by key.

Example:

Application Cache

Asynchronous access to redis is automatically added to the server if a value is provided for the REDIS_URL environment variable. To invoke this data in a handler, simply add cache: Cache to the function signature.

Helper Functions

get(cache: Cache, key: &str) -> Result<String, ApiError>

Retrieves a copy of the entry in the application cache by key.

Example:

set(cache: Cache, key: &str, value: &str) -> Result<String, ApiError>

Inserts or updates an entry in the application cache.

Example:

delete(cache: Cache, key: &str) -> Result<String, ApiError>

Deletes an entry in the application cache by key.

Example:

Non-Blocking Diesel Database Operations

When accessing a database via Diesel, operations block the main server thread. This blocking can be mitigated by running the blocking code in a thread pool from within the handler.

Example:

Blocking errors are automatically converted into ApiErrors to keep the api simple:

Endpoints

Healthcheck

Determine if the system is healthy.

GET /health

Response

Example:

Login

POST /api/v1/auth/login

Request

Param Type Description Required Validations
email String The user's email address yes valid email address
password String The user's password yes at least 6 characters

Response

Header

Json Body

When sending subsequent requests, create a header variable cookie with the value auth=COOKIE_VALUE_HERE

Logout

GET /api/v1/auth/logout

Response

200 OK

Example:

Get All Users

GET /api/v1/user

Response

Example:

Get a User

GET /api/v1/user/{id}

Request

Param Type Description
id Uuid The user's id

Response

Example:

Response - Not Found

404 Not Found

Create a User

POST /api/v1/user

Request

Param Type Description Required Validations
first_name String The user's first name yes at least 3 characters
last_name String The user's last name yes at least 3 characters
email String The user's email address yes valid email address

Response

Example:

Response - Validation Errors

422 Unprocessable Entity

Update a User

PUT /api/v1/{id}

Request

Path

Param Type Description
id Uuid The user's id

Body

Param Type Description Required Validations
first_name String The user's first name yes at least 3 characters
last_name String The user's last name yes at least 3 characters
email String The user's email address yes valid email address

Response

Example:

Response - Validation Errors

422 Unprocessable Entity

Response - Not Found

404 Not Found

Delete a User

DELETE /api/v1/user/{id}

Request

Param Type Description
id Uuid The user's id

Response

Response

200 OK

Example:

Response - Not Found

404 Not Found

License

This project is licensed under:

  • MIT license (LICENSE-MIT or #404)
Issues

Collection of the latest Issues

abariatti

abariatti

Comment Icon0

On the up.sql script that is used as a first migration.

This: created_at TIMESTAMP NOT NULL DEFAULT NOW(), fails when using sqlite as a database.

One way to solve it is to replace it with: created_at TIMESTAMP NOT NULL DEFAULT (strftime('%s','now')),

Vendelieu

Vendelieu

Comment Icon1

thread 'main' panicked at 'Configuration Error: Custom( "invalid digit found in string while parsing value 'short' provided by RUST_BACKTRACE", )', src/config.rs:43:23

vietlib

vietlib

Comment Icon1

i have installed demo and try to access: http://127.0.0.1:3000/user however, i got this: The system cannot find the file specified. (os error 2)

Also, tried: http://127.0.0.1:3000/user/00000000-0000-0000-0000-000000000000 and get this [2020-04-30T05:49:58Z INFO actix_web::middleware::logger] 127.0.0.1:52709 "GET /user/00000000-0000-0000-0000-000000000000 HTTP/1.1" 404 55 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36" 0.000000 The system cannot find the path specified. (os error 3)

flyq

flyq

Comment Icon1

ENV

Ubuntu 18.04 in VMware

steps

follow the README.md:

  1. install postgres

  2. install diesel_cli(to make it succeed, I install mysql, libsqlite3-dev and so on)

  3. modify the Cargo.toml:

  4. modify the .env I JUST modify the DATABASE_URL to postgres link.

  5. diesel migration run it succeeds

  6. run:

Problem

What should I do to just use postgres? Because I think problem is caused by the program trying to connect other database like mysql, redis and so on: log:

Piping

Piping

Comment Icon3

Hi,

I am trying out the example inside a relative new VM (ubuntu16.04).

The cargo test report a linker error at the end.

Is it possible to update the README to include some steps for a brand new linux VM setup?

Information - Updated Apr 13, 2022

Stars: 200
Forks: 48
Issues: 8

This is an example project that puts together Rust, Actix, Juniper and Diesel

I've started with only very little knowledge of Rust

This is an example project that puts together Rust, Actix, Juniper and Diesel
JSON

1.1K

Monorepo for dprint—a pluggable and configurable code formatting platform

This project is under active early development

Monorepo for dprint—a pluggable and configurable code formatting platform

A middleware for actix-web that provides

rate-limiting backed by Triox-Poject

A middleware for actix-web that provides

Notatin is a Rust parser for offline Windows Registry files

This project is currently pre-release and should not be used for active investigations

Notatin is a Rust parser for offline Windows Registry files

A language bindings generator for `witx`

Note: this project is still relatively young and active development with

A language bindings generator for `witx`

tmdc - Tiny Markdown Compiler

This project is still in active development, use it at your own risk!

tmdc - Tiny Markdown Compiler

&quot;Card Game API&quot; is a project made in Rust with Actix

&quot;Card Game API&quot; is a project made in Actix

&quot;Card Game API&quot; is a project made in Rust with Actix

This project is still a WIP and not yet published on crates

Building a Json Api for actix can be a lot of boilerplace code to write

This project is still a WIP and not yet published on crates

Rustix is a Rust project template that uses Actix-web for API services

Rustix is a Rust project template that uses Actix-web: 4

Rustix is a Rust project template that uses Actix-web for API services

This is a simple web project uses (rust, sqlx, and actix)

Actix Handle the HTTP requests to access a REST API endpoints

This is a simple web project uses (rust, sqlx, and actix)

actix-web-graphql-api

This project is a example api using graphql query language

actix-web-graphql-api

actix-react-starter-template

Actix web + React + Redux + Redux Saga project starter template

actix-react-starter-template
Facebook Instagram Twitter GitHub Dribbble
Privacy