1
cargo watch -x check 文件变动时后台编译
cargo-clippy linting
cargo tarpaulin --ignore-tests 查代码覆盖率
cargo-audit 查安全漏洞
cargo-expand 展开宏
3
TcpListener::bind("127.0.0.1:0") 绑定的随机端口,可以通过listener.local_addr().unwrap().port()获取
actix-web会为请求处理函数的每个参数调用from_request方法,以从请求中反序列化出参数数据。
4
可观测性处理”未知的未知”
库tracing是树状结构的日志
instrument在futurepolled 时进入 span,在futureparked 时退出 spanRegistry记录span的元数据、实现Subscribertrait、对应log的Loglayer是一个pipeline处理层
cargo-udeps 查无用依赖 (unused dependencies)
5
5.4 deploy
为sqlx离线模式生成sqlx-data.json
cargo sqlx prepare -- --lib发布到digitalocean
doctl apps create --spec spec.yaml
doctl apps list
doctl apps update YOUR-APP-ID --spec=spec.yaml
doctl apps delete YOUR-APP-ID
运行数据库迁移
在数据库设置中临时关闭Trusted Sources,再运行
DATABASE_URL=YOUR-DIGITAL-OCEAN-DB-CONNECTION-STRING sqlx migrate run
6
property-based testing:quickcheck、proptest
TryFrom:a fallible conversion between two types which consumes the input value
7
在结构中存储引用,需要添加生命周期参数
tests文件夹的下一级测试文件或目录都被编译为自己的可执行文件
8
thiserror:给开发者的错误枚举
anyhow:给用户的opaque错误
10
哈希是一种单向函数,加密是一种双向函数
加盐防止对某哈希算法的预计算攻击(如彩虹表)
- 盐值不是秘密,可以随机生成并与密码哈希一起存储
- 盐位数必须足够大,否则攻击者可为每个盐预计算表
如果所有密码哈希再用一个对称密钥加密,这个对称密钥叫做pepper
参考 密码存储备忘单
PHC串
The PHC string format provides a standard representation for a password hash: it includes the hash itself, the salt, the algorithm and all its associated parameters.
OAuth2
OpenID是OAuth2之上的身份层
生命周期
-
T、&T、&mut T都表示类型集合,T是&T和&mut T的超集,&T和&mut T正交 -
T: 'staticshould be read as ”Tis bounded by a'staticlifetime” (not ”Thas a'staticlifetime”.Tcan be a borrowed type with a'staticlifetime or an owned type. -
&'a Trequires and impliesT: 'asince a reference of lifetime'atoTcannot be valid for'aifTitself is not valid for'a.T: 'aincludes all&'a Tbut the reverse is not true. -
函数的生命周期省略规则
- 函数的每个输入ref有着不同的生命上限
- 若只有一个输入ref,其生命上限应用到所有输出ref
- 多个输入ref中只要有一个输入ref是
&self或&mut self,其生命上限应用到所有输出ref - 其他情况下,输出ref的生命上限必须写明
-
Lifetimes have to be statically verified at compile-time and the Rust borrow checker only does very basic control flow analysis, so it assumes every block in an
if-elsestatement and every match arm in amatchstatement can be taken and then chooses the shortest possible lifetime for the variable. The lifetime of a variable can only shrink, and all the shrinkage is determined at compile-time. Once a variable is bounded by a lifetime it is bounded by that lifetime forever. -
将
&mutre-borrow 为&,会延长&mut的生命上限 -
闭包不遵循函数的生命周期省略规则
参考:关于生命周期的误解
Sized、Unsized
- pointers of dynamically sized views into arrays are called slices
?Sizedpronouncedoptionally sizedormaybe sized,?Sizedis the only relaxed bound in Rust- generic type parameters are
Sizedby default. if we have a generic function which takes an argument of someTbehind a pointer, e.g.&T,Box<T>,Rc<T>, et cetera, then we almost always want to opt-out of the defaultSizedbound withT: ?Sized - traits are
?Sizedby default
str是utf-8变长编码,所以是Unsized,作为String和&str的底层类型。
指向Sized的指针宽1,指向Unsized的指针宽2。因此&String宽1,&str宽2。
rust不支持宽度超过2的指针。
let hmac_tag = hash(
concat(
key,
hash(concat(key, message))
)
);