头图

除非是为了学习,不然数据的增删改查写起来是很无聊的,所以出现了相关的代码库,将这些操作给封装起来,Rust也是有类似的框架的,而且不止于此,比如本文的Loco.rs它提供类似Ruby on Rails的相关功能,可以很快的搭建起来一个后台。

<!--more-->

当然了,写起来无聊的不止增删改查还有权限验证, 发送邮件,后台任务等,这些Loco也是提供了开箱即用的接口的。

快速入门

这部分内容几乎是直接复制自官方文档, 但是也解决了一些问题,比如怎么跳过邮箱验证的逻辑。

相关命令行安装

$ cargo install loco-cli
$ cargo install sea-orm-cli

这两个安装可能要很久很久, 因为cargo似乎都是现场编译代码的, 而编译代码是很费时间的。

创建项目

这会问你各种问题,这应该没什么奇怪的,大多数脚手架框架都是这样,一共就两个问题,应用名叫啥, 使用哪个模板,下面选择的是第三个。

$ loco new
✔ ❯ App name? · myapp
? ❯ What would you like to build? ›
  lightweight-service (minimal, only controllers and views)
  Rest API (with DB and user auth)
❯ Saas app (with DB and user auth)
🚂 Loco app generated successfully in:
myapp

比如上面,我们创建了一个叫做myapp的应用,并且在当前工作目录会看到一个myapp的目录。

数据库

在运行之前,我们需要一个数据库, 这可以使用docker来完成。

$ docker run -d -p 5432:5432 -e POSTGRES_USER=loco -e POSTGRES_DB=myapp_development -e POSTGRES_PASSWORD="loco" postgres:15.3-alpine

如果本地无法运行,就在局域网运行一个,如果运行在局域网,那就需要改一下config/目录里面的配置文件,默认postgres的连接配置是localhost

其实我测试的时候发现一个问题就是, 配置文件写的数据库名是loco_app, 但是运行的docker命令却是设置的myapp_development, 这会导致连不上数据库,比如报错如下:

2024-02-03T09:10:16.785908Z  INFO loco_rs::config: loading environment from selected_path="config\\development.yaml"
2024-02-03T09:10:16.791266Z  WARN 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)
Error: Connection Error: error returned from database: database "loco_app" does not exist

Caused by:
   0: error returned from database: database "loco_app" does not exist
   1: error returned from database: database "loco_app" does not exist
   2: database "loco_app" does not exist

解决很简单,就是使用docker创建的数据名就行

database:
  # Database connection URI
  # 之前
  #uri: {{ get_env(name="DATABASE_URL", default="postgres://loco:loco@localhost:5432/loco_app") }}
  # 之后
  uri: {{ get_env(name="DATABASE_URL", default="postgres://loco:loco@192.168.31.197:5432/myapp_development") }}

loco的代码我还没仔细研究过, 所以我感觉可能是文档没跟代码保持同步导致的。

运行应用

运行需要编译, 然后又是漫长的等待。

cd myapp
cargo loco start
Finished dev [unoptimized + debuginfo] target(s) in 5m 36s
    Running `target/debug/myapp start`

    :
    :
    :

controller/app_routes.rs:203: [Middleware] Adding log trace id

                      ▄     ▀
                                 ▀  ▄
                  ▄       ▀     ▄  ▄ ▄▀
                                    ▄ ▀▄▄
                        ▄     ▀    ▀  ▀▄▀█▄
                                          ▀█▄
▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄   ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▀▀█
 ██████  █████   ███ █████   ███ █████   ███ ▀█
 ██████  █████   ███ █████   ▀▀▀ █████   ███ ▄█▄
 ██████  █████   ███ █████       █████   ███ ████▄
 ██████  █████   ███ █████   ▄▄▄ █████   ███ █████
 ██████  █████   ███  ████   ███ █████   ███ ████▀
   ▀▀▀██▄ ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀ ██▀
       ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

started on port 3000

如果能够运行起来,那就可以继续下一步了,也就是增加必要的数据表。

增加CRUD API

假设我们想要构建一个博客, 那么必然需要一张文章(post)的表, 我们可以将这张表简化到两个字段,标题(title)和内容(content),命令如下:

cargo loco generate scaffold post title:string content:text
如果这条命令失败了,就重新在执行一遍,一定要保证这条命令执行成功,否则不会创建对应的处理函数(handler)。

上面创建的数据表如下

myapp_development=# \d posts
                                        Table "public.posts"
   Column   |            Type             | Collation | Nullable |              Default              
------------+-----------------------------+-----------+----------+-----------------------------------
 created_at | timestamp without time zone |           | not null | CURRENT_TIMESTAMP
 updated_at | timestamp without time zone |           | not null | CURRENT_TIMESTAMP
 id         | integer                     |           | not null | nextval('posts_id_seq'::regclass)
 title      | character varying           |           |          | 
 content    | text                        |           |          | 
Indexes:
    "posts_pkey" PRIMARY KEY, btree (id)

启动

有了数据表,我们可以重新在启动

cargo loco start

接口测试

通过loco构建后台系统,我们只需要指定数据表的字段就行,loco会为我们创建对应的处理函数,所以我们可以直接测试了。

创建数据

$ curl -X POST -H "Content-Type: application/json" -d '{
  "title": "Your Title",
  "content": "Your Content xxx"
}' localhost:3000/api/posts

返回结果如下

{"created_at":"2024-02-03T09:27:02.454070","updated_at":"2024-02-03T09:27:02.454070","id":1,"title":"Your Title","content":"Your Content xxx"}

查询数据

$ curl localhost:3000/api/posts

返回结果如下

[{"created_at":"2024-02-03T09:27:02.454070","updated_at":"2024-02-03T09:27:02.454070","id":1,"title":"Your Title","content":"Your Content xxx"}]

认证

一个后端一定需要认证的啦,所以loco也是内置认证的,要启用loco的认证需要一个redis服务, 之所以需要redis服务应该是为了无限水平扩展,方便部署吧。

如果没有redis服务, 就像数据一样使用docker即可.

docker run -p 6379:6379 -d redis redis-server

如果不是本地部署,也需要配置一下redis的连接地址。

服务测试

在启动之前,我们可以测试一下数据库, redis的连接是否正常。

cargo loco doctor

正常输出应该如下

    Finished dev [unoptimized + debuginfo] target(s) in 1.13s
     Running `target\debug\myapp-cli.exe doctor`
✅ SeaORM CLI is installed
✅ DB connection: success
✅ Redis connection: success

注册用户

因为loco提供的是一个Rest API风格的后端,所以应该是所有接口都可以使用http客户端进行操作的。

官方的代码都是用的127.0.0.1, 但是代码似乎不会响应127.0.0.1, 只会响应localhost, 虽然它们几乎一样,但是后者可以作为域名,这和ip还是不一样的,后文都是使用localhost测试, 亲测127.0.0.1不行, 可能是有啥域名验证逻辑更新了,但是文档没同步。
curl --location 'localhost:3000/api/auth/register' \
     --header 'Content-Type: application/json' \
     --data-raw '{
         "name": "Loco user",
         "email": "admin@youerning.top",
         "password": "12341234"
     }'

但是要发送邮件应该是需要配置邮件服务器之类的东西的,所以这个接口一定会失败的,为了让流程可以继续走下去,我们可以直接修改数据库,如果你看一下代码里面的验证逻辑,就会发现只是将email_verified_at字段设置一个日期即可,所以我们使用sql来修改数据库。

update users set email_verified_at = '2024-02-03 17:41:16.170637' where id = 1;

可以通过下面命令连接数据库,如果你是docker运行的话。

docker exec -it c40 psql -U loco -d myapp_development

登录用户

登录用户就是为了获取token。

curl --location 'localhost:3000/api/auth/login' \
     --header 'Content-Type: application/json' \
     --data-raw '{
         "email": "admin@youerning.top",
         "password": "12341234"
     }'

正常情况下我们会得到一个类似下面的输出

{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJwaWQiOiI0OTE5YTVjYi0xNWQzLTRkNmQtOGE0Ni0xNDRiZTdmOTE3MTgiLCJleHAiOjE3MDc1NTg0OTV9.4H1CGeX1gJ-phVLBDYrw8NhcAsZMxE3rn3Xmp7OCrV-14NHgMjFMTyFM1-lEXm8jHr5XJCJdKqdDmCaQqIcnwQ","pid":"4919a5cb-15d3-4d6d-8a46-144be7f91718","name":"Loco user","is_verified":true}

测试token

我们可以测试/api/user/current这个接口验证。

$ curl --location --request GET 'localhost:3000/api/user/current' \
     --header 'Content-Type: application/json' \
     --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJwaWQiOiI0OTE5YTVjYi0xNWQzLTRkNmQtOGE0Ni0xNDRiZTdmOTE3MTgiLCJleHAiOjE3MDc1NTg0OTV9.4H1CGeX1gJ-phVLBDYrw8NhcAsZMxE3rn3Xmp7OCrV-14NHgMjFMTyFM1-lEXm8jHr5XJCJdKqdDmCaQqIcnwQ'

正常输出应该如下

{"pid":"4919a5cb-15d3-4d6d-8a46-144be7f91718","name":"Loco user","email":"admin@youerning.top"}

总结

以前我我不是很喜欢PythonDjango, 因为我觉得它剥夺了我写代码的乐趣,后来代码写多了,我没有那么不喜欢Django,因为重复的写一些差不多的代码是很烦人的,所以Django还是很棒的,虽然我几乎没用过它了。

虽然后台代码不总是CRUD, 但是很多时候都会落在CRUD, 而CRUD是可以高度抽象出来的,比如大多数操作是差不多的,创建用POST, 查询用GET,然后查询会提供两个接口一个是查询结果是列表,另一个提供单个结果的查询,这些都可以代码生成,我们在此基础上再加入自己的业务逻辑就行。

loco应该还是很有前途的,总体使用下来以及粗略的看下代码各方面都是简洁清晰的,如果一直迭代下去,应该会有不错的市场,就像非常出名的Ruby on Rails那样,以后我有机会快速的做原型也会选择loco

参考链接


又耳笔记
1 声望2 粉丝