使用Loco快速搭建自己的后台系统
除非是为了学习,不然数据的增删改查写起来是很无聊的,所以出现了相关的代码库,将这些操作给封装起来,Rust
也是有类似的框架的,而且不止于此,比如本文的Loco.rs
它提供类似Ruby on Rails
的相关功能,可以很快的搭建起来一个后台。
当然了,写起来无聊的不止增删改查还有权限验证, 发送邮件,后台任务等,这些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:[email protected]: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": "[email protected]",
"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": "[email protected]",
"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":"[email protected]"}
总结
以前我我不是很喜欢Python
的Django
, 因为我觉得它剥夺了我写代码的乐趣,后来代码写多了,我没有那么不喜欢Django
,因为重复的写一些差不多的代码是很烦人的,所以Django
还是很棒的,虽然我几乎没用过它了。
虽然后台代码不总是CRUD, 但是很多时候都会落在CRUD, 而CRUD是可以高度抽象出来的,比如大多数操作是差不多的,创建用POST, 查询用GET,然后查询会提供两个接口一个是查询结果是列表,另一个提供单个结果的查询,这些都可以代码生成,我们在此基础上再加入自己的业务逻辑就行。
loco
应该还是很有前途的,总体使用下来以及粗略的看下代码各方面都是简洁清晰的,如果一直迭代下去,应该会有不错的市场,就像非常出名的Ruby on Rails
那样,以后我有机会快速的做原型也会选择loco
。