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是树状结构的日志

  • instrumentfuture polled 时进入 span,在 future parked 时退出 span
  • Registry 记录span的元数据、实现 Subscriber trait、对应 logLog
  • layer 是一个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:quickcheckproptest

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: 'static should be read as T is bounded by a 'static lifetime” (not T has a 'static lifetime”. T can be a borrowed type with a 'static lifetime or an owned type.

  • &'a T requires and implies T: 'a since a reference of lifetime 'a to T cannot be valid for 'a if T itself is not valid for 'a. T: 'a includes all &'a T but 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-else statement and every match arm in a match statement 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.

  • &mut re-borrow 为 &,会延长&mut的生命上限

  • 闭包不遵循函数的生命周期省略规则

参考:关于生命周期的误解

Sized、Unsized

  • pointers of dynamically sized views into arrays are called slices
  • ?Sized pronounced optionally sized or maybe sized , ?Sized is the only relaxed bound in Rust
  • generic type parameters are Sized by default. if we have a generic function which takes an argument of some T behind a pointer, e.g. &T, Box<T>, Rc<T>, et cetera, then we almost always want to opt-out of the default Sized bound with T: ?Sized
  • traits are ?Sized by default

参考:sizedness in rust

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)) 
	) 
);

服务端请求伪造预防