DEV Community

nabbisen
nabbisen

Posted on • Originally published at scqr.net

Loco 0.14 on Cathyos: Getting started

Summary

Loco is a relatively new Rust web framework which first appeared around 2021. It is strongly inspired by Ruby on Rails, and designed to bring developers productivity as various functionality on routing, middlewares, and request handling. They aim to provide modern and intuitive development experience.

This post shows how to start Web API development to manage users in several minutes thanks to their great app template.

Environment

  • OS: Cathyos (based on Arch Linux)
  • Programming Language: Rust 1.84.0
  • App: Loco 0.14.0

Tutorial

loco installation

Get loco executable first.

$ cargo install loco
Enter fullscreen mode Exit fullscreen mode

The result was:

    Updating crates.io index
  Downloaded loco v0.14.0
  Downloaded 1 crate (367.8 KB) in 0.16s
  Installing loco v0.14.0
  (...)
   Compiling loco v0.14.0
    Finished `release` profile [optimized] target(s) in 16.72s
  Installing /home/nabbisen/.cargo/bin/loco
   Installed package `loco v0.14.0` (executable `loco`)
Enter fullscreen mode Exit fullscreen mode

Then :)

$ loco --version
loco 0.14.0
Enter fullscreen mode Exit fullscreen mode

Activate executables which cargo installs

When $PATH doesn't include ~/.cargo/bin, loco must be missing. In such case, it is necessary to append the line below to ~/.fish_profile to:

set -U fish_user_paths $HOME/.cargo/bin $fish_user_paths
Enter fullscreen mode Exit fullscreen mode

Prepare ORM (Optional)

Install the crate below in addition when database is required:

$ cargo install sea-orm-cli
Enter fullscreen mode Exit fullscreen mode

I installed it.

Create a project

OK. Run to start:

$ loco new
Enter fullscreen mode Exit fullscreen mode

You will be asked what kind of app you want to create. My reponses were:

✔ ❯ App name? · loco-example
? ❯ What would you like to build? ›
  Saas App with server side rendering
  Saas App with client side rendering
❯ Rest API (with DB and user auth)
  lightweight-service (minimal, only controllers and views)
  Advanced
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)
Enter fullscreen mode Exit fullscreen mode

The result was:

🚂 Loco app generated successfully in:
/(...)/loco-example
Enter fullscreen mode Exit fullscreen mode

Understand the project structure

Yay, the project was created. Let's come in:

$ cd loco-example/
Enter fullscreen mode Exit fullscreen mode

And see what there are:

$ ls
drwxr-xr-x    - (user) 10  1月 12:46 .cargo
drwxr-xr-x    - (user) 10  1月 12:46 .github
drwxr-xr-x    - (user) 10  1月 12:46 config
drwxr-xr-x    - (user) 10  1月 12:46 examples
drwxr-xr-x    - (user) 10  1月 12:46 migration
drwxr-xr-x    - (user) 10  1月 12:46 src
drwxr-xr-x    - (user) 10  1月 12:46 tests
.rw-r--r--  339 (user) 10  1月 12:46 .gitignore
.rw-r--r--   49 (user) 10  1月 12:46 .rustfmt.toml
.rw-r--r-- 1.3k (user) 10  1月 12:46 Cargo.toml
.rw-r--r-- 2.4k (user) 10  1月 12:46 README.md
Enter fullscreen mode Exit fullscreen mode

Start the server

$ cargo loco start
Enter fullscreen mode Exit fullscreen mode

The result was:

   Compiling loco-example v0.1.0 (/(...)/loco-example)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 41.10s
     Running `target/debug/loco_example-cli start`
2025-01-10T03:51:27.386666Z  WARN app: loco_rs::boot: pretty backtraces are enabled (this is great for development but has a runtime cost for production. disable with `logger.pretty_backtrace` in your config yaml) environment=development
2025-01-10T03:51:27.394779Z  INFO app: loco_rs::db: auto migrating environment=development
2025-01-10T03:51:27.398632Z  INFO app: sea_orm_migration::migrator: Applying all pending migrations environment=development
2025-01-10T03:51:27.399422Z  INFO app: sea_orm_migration::migrator: Applying migration 'm20220101_000001_users' environment=development
2025-01-10T03:51:27.399875Z  INFO app: sea_orm_migration::migrator: Migration 'm20220101_000001_users' has been applied environment=development
2025-01-10T03:51:27.400196Z  INFO app: loco_rs::boot: initializers loaded initializers="" environment=development
2025-01-10T03:51:27.412320Z  INFO app: loco_rs::controller::app_routes: [GET] /_ping environment=development
2025-01-10T03:51:27.412500Z  INFO app: loco_rs::controller::app_routes: [GET] /_health environment=development
2025-01-10T03:51:27.412558Z  INFO app: loco_rs::controller::app_routes: [POST] /api/auth/register environment=development
2025-01-10T03:51:27.412591Z  INFO app: loco_rs::controller::app_routes: [GET] /api/auth/verify/{token} environment=development
2025-01-10T03:51:27.412648Z  INFO app: loco_rs::controller::app_routes: [POST] /api/auth/login environment=development
2025-01-10T03:51:27.412693Z  INFO app: loco_rs::controller::app_routes: [POST] /api/auth/forgot environment=development
2025-01-10T03:51:27.412724Z  INFO app: loco_rs::controller::app_routes: [POST] /api/auth/reset environment=development
2025-01-10T03:51:27.412758Z  INFO app: loco_rs::controller::app_routes: [GET] /api/auth/current environment=development
2025-01-10T03:51:27.412796Z  INFO app: loco_rs::controller::app_routes: [POST] /api/auth/magic-link environment=development
2025-01-10T03:51:27.412827Z  INFO app: loco_rs::controller::app_routes: [GET] /api/auth/magic-link/{token} environment=development
2025-01-10T03:51:27.412957Z  INFO app: loco_rs::controller::app_routes: +middleware name="limit_payload" environment=development
2025-01-10T03:51:27.413002Z  INFO app: loco_rs::controller::app_routes: +middleware name="catch_panic" environment=development
2025-01-10T03:51:27.413040Z  INFO app: loco_rs::controller::app_routes: +middleware name="etag" environment=development
2025-01-10T03:51:27.413106Z  INFO app: loco_rs::controller::app_routes: +middleware name="logger" environment=development
2025-01-10T03:51:27.413144Z  INFO app: loco_rs::controller::app_routes: +middleware name="request_id" environment=development
2025-01-10T03:51:27.413184Z  INFO app: loco_rs::controller::app_routes: +middleware name="fallback" environment=development
2025-01-10T03:51:27.413239Z  INFO app: loco_rs::controller::app_routes: +middleware name="powered_by" environment=development

                      ▄     ▀                     
                                 ▀  ▄             
                  ▄       ▀     ▄  ▄ ▄▀           
                                    ▄ ▀▄▄         
                        ▄     ▀    ▀  ▀▄▀█▄       
                                          ▀█▄     
▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄   ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▀▀█    
 ██████  █████   ███ █████   ███ █████   ███ ▀█   
 ██████  █████   ███ █████   ▀▀▀ █████   ███ ▄█▄  
 ██████  █████   ███ █████       █████   ███ ████▄
 ██████  █████   ███ █████   ▄▄▄ █████   ███ █████
 ██████  █████   ███  ████   ███ █████   ███ ████▀
   ▀▀▀██▄ ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀ ██▀  
       ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀    
                https://loco.rs

environment: development
   database: automigrate
     logger: debug
compilation: debug
      modes: server

listening on http://localhost:5150
Enter fullscreen mode Exit fullscreen mode

The server started !!

Besides, the routing is defined in src/controllers/auth.rs:

pub fn routes() -> Routes {
    Routes::new()
        .prefix("/api/auth")
        .add("/register", post(register))
        .add("/verify/{token}", get(verify))
        .add("/login", post(login))
        .add("/forgot", post(forgot))
        .add("/reset", post(reset))
        .add("/current", get(current))
        .add("/magic-link", post(magic_link))
        .add("/magic-link/{token}", get(magic_link_verify))
}
Enter fullscreen mode Exit fullscreen mode

Access via browser (Optional)

http://localhost:5150 looks like:

access via browser

Register users via curl

If there is no local email service, edit config/development.yaml to disable smtp beforehand:

  mailer:
    # SMTP mailer configuration.
    smtp:
      # Enable/Disable smtp mailer.
-       enable: true
+       enable: false
Enter fullscreen mode Exit fullscreen mode

and restart the server.

Access via curl to register a user:

$ curl -X POST http://localhost:5150/api/auth/register -H "content-type: application/json" --data '{"email":"test@test.test", "password":"testpassword", "name":"testname"}'
Enter fullscreen mode Exit fullscreen mode

You will see SQLite database file is created in the root directory named loco-example_development.sqlite.
Open the database:

$ sqlite3 loco-example_development.sqlite
Enter fullscreen mode Exit fullscreen mode

Check it:

sqlite> .tables
seaql_migrations  users           

sqlite> select * from users;
2025-01-10 04:08:06|2025-01-10 04:08:06|(...)|test@test.test|$argon2id$v=19$m=19456,t=2,p=(...)|(...)|testname|||(...)|2025-01-10T13:08:06.638250752+09:00|||

sqlite> .schema users
CREATE TABLE IF NOT EXISTS "users" ( "created_at" timestamp_with_timezone_text NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" timestamp_with_timezone_text NOT NULL DEFAULT CURRENT_TIMESTAMP, "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "pid" uuid_text NOT NULL, "email" varchar NOT NULL UNIQUE, "password" varchar NOT NULL, "api_key" varchar NOT NULL UNIQUE, "name" varchar NOT NULL, "reset_token" varchar NULL, "reset_sent_at" timestamp_with_timezone_text NULL, "email_verification_token" varchar NULL, "email_verification_sent_at" timestamp_with_timezone_text NULL, "email_verified_at" timestamp_with_timezone_text NULL, "magic_link_token" varchar NULL, "magic_link_expiration" timestamp_with_timezone_text NULL );
Enter fullscreen mode Exit fullscreen mode

Conclusion

We saw how to install Loco via cargo and create Web API to register users. There are other API provided such as to login or reset an account.

Hope it helps in some way you to get familiar with the wonderful framework !!!

Reference

Top comments (0)