Deserializ
in this scopeerror: cannot find derive macro `Serialize` in this scope --> common/src/result.rs:2:10 | 2 | #[derive(Serialize,Deserializ)] | ^^^^^^^^^ error: cannot find derive macro `Deserializ` in this scope --> common/src/result.rs:2:20 | 2 | #[derive(Serialize,Deserializ)] 12345678910
在新版本的serde中使用derive须要开启对应的featureshtml
serde = { version = "1.0", features = ["derive"] }1
参考serde官网文档mysql
Conn
error[E0282]: type annotations needed --> user/src/lib.rs:29:31 | 29 | let count: usize = repos::add_login_info( conn, &new_login_info).expect("add login info error"); | ^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `Conn`12345
刚开始觉得是推导不出参数conn的类型,甚是奇怪,仔细看发现是Conn一个全小写一个首字母大写,代码里也没用到Conn啊,是否是调diesel API里的,在翻看diesel文档时确实见过Conngit
fn execute(self, conn: &Conn) -> QueryResult<usize> where **Conn**: Connection, Self: ExecuteDsl<Conn>1234
查API也没发现泛型参数,最终发现是本身的代码里声明了个泛型Conn,没有用到忘记删掉了。github
pub fn add_login_info<Conn>(conn: &MysqlConnection, new_login_info: &NewLoginInfo) -> Result<usize, Error>1
在网上看到这个问题:web
What is the best approach to implement http authentication
(validation) using actix web?sqlUsing the provided examples for a simple-auth-server I can
authenticate a request and create a cookie accordingly.dockerNow I want to validate the cookie/identity in order to prevent access
from certain routes. A Guard 3 doesn’t cut it because I can only
retrieve the stored identity using Identity::from_request(HttpRequest,
Payload) and in RequestHead (guard implementation), there is neither
the full request nor its payload.centosI can not use Middleware 3 either because I will only get access to
ServiceRequest but not HttpRequest.cookie
看样子是想基于Session作登陆验证,但官方的Demo只有使用Cookie Identity的,那咱们就实现个吧
一个基于Session验证用户是否登陆的中间件:网络
use std::cell::RefCell; use std::ops::{Deref, DerefMut}; use std::pin::Pin; use std::rc::Rc; use std::sync::Arc; use std::task::{Context, Poll}; use futures::future::{ok, Ready}; use futures::Future; use actix_service::{Service, Transform}; use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error, HttpMessage, HttpResponse}; use actix_session::{UserSession}; use log::{info}; use super::userctrl; #[derive(Clone)] pub struct AuthService { } impl<S, B> Transform<S> for AuthService where S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static, S::Future: 'static, B: 'static, { type Request = ServiceRequest; type Response = ServiceResponse<B>; type Error = Error; type InitError = (); type Transform = AuthMiddleware<S>; type Future = Ready<Result<Self::Transform, Self::InitError>>; fn new_transform(&self, service: S) -> Self::Future { ok(AuthMiddleware { service: Rc::new(RefCell::new(service)), }) } } pub struct AuthMiddleware<S> { service: Rc<RefCell<S>>, } impl<S, B> Service for AuthMiddleware<S> where S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static, S::Future: 'static, B: 'static, { type Request = ServiceRequest; type Response = ServiceResponse<B>; type Error = Error; type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { self.service.poll_ready(cx) } fn call(&mut self, req: ServiceRequest) -> Self::Future { let mut srv = self.service.clone(); Box::pin(async move { let path = req.path().to_string(); info!("path:{}", path); if path.find("/admin") .is_some() && userctrl::get_username_from_session(req.get_session()).is_none() { Ok(req.into_response(HttpResponse::Unauthorized().finish().into_body())) } else { let res_fut = srv.call(req); res_fut.await } }) } }123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
部署的Rust应用启动时报:
/lib64/libc.so.6: version `GLIBC_2.18’ not found (required by ./web)
能够经过在生成发布包时指定不依赖glibc的发布包解决也能够在安装机器上安装对应版本的glibc解决(网上有安装glibc的教程),可是升级glibc有风险,由于不少程序都依赖这个库,最后我选择了使用docker部署rust应用。 也能够使用跟部署操做系统同样的docker环境编译生成安装包也能够使用比较低版本的glibc环境好比centos5 。解决问题的方法不仅一种,找到最适合最易实现的就好。因为Rust程序中使用diesel访问mysql因此须要 libmysqlclient.so.20
libmysqlclient.so.20 not found
参考博客执行:
apt-get install libzdb-dev
解决
项目执行cargo check报错:
error[E0271]: type mismatch resolving
<impl std::future::Future as std::future::Future>::Output == &mut T
-->
/home/tianlang/.cargo/registry/src/github.com-1ecc6299db9ec823/blocking-0.4.6/src/lib.rs:630:40
| 630 | pub async fn get_mut(&mut self) -> &mut T {
| ^^^^^^ expected structstd::boxed::Box
, found type parameter
|
= note: expected type&mut std::boxed::Box<T>
found type&mut T
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
= note: the return type of a function must have a statically known size
从错误信息看是引用的第三方crate blocking里报的错误,我又没升级过依赖库为何会报错呢? 百思不得其解中…
忽然想起来是否是在开发另外一个项目时修改了Rust版本,赶忙查看Rust版本:
rustc --version
rustc 1.39.0 (4560ea788 2019-11-04)
额地那个娘啊,这2020年都过去一半了,rust咋还回到2019年了呢?此事必有蹊跷!
赶忙执行 :
rustup update
升级rust ,因为默认访问的国外软件仓库,因为网络缘由update了几回都失败了,我这小暴脾气,这得使用国内的软件源啊:
export RUSTUP_DIST_SERVER=“https://mirrors.ustc.edu.cn/rust-static”
reustup update
此次就更新成功了:
rustc --version1
rustc 1.44.1 (c7087fe00 2020-06-17)
再次执行cargo check就没问题了
修改rustup/cargo镜像源能够参考博客
在函数中须要根据不一样的状况返回不一样类型的值,这俩种类型都实现了Responder特征,使用impl Responder定义返回值类型一直报错:
expected opaque type, found struct `actix_http::response::Response
在网上找到使用Box解决返回实现了相同特征的不一样具体类型的方法,能够参考1参考2参考3,后来在actix-web的API文档中发现提供有Either类型,用于解决此种需求
use actix_web::{Either, Error, HttpResponse}; type RegisterResult = Either<HttpResponse, Result<HttpResponse, Error>>; fn index() -> RegisterResult { if is_a_variant() { // <- choose left variant Either::A(HttpResponse::BadRequest().body("Bad data")) } else { Either::B( // <- Right variant Ok(HttpResponse::Ok() .content_type("text/html") .body("Hello!")) ) } }1234567891011121314151617
问题解决
遇到个奇怪的问题,使用diesel的find方法查找数据,明明是使用的ID,却查出了多条数据.
pub fn find_article_by_id(conn: &DbConnection, id: &str) -> Result<ArticleModel, Error> { use self::tb_article::dsl::*; tb_article.find(id).first(conn) }1234
还好,当准备使用info!输出日志打印时,报id并无实现Display特征。参数id明明是&str类型的啊,怎么没实现Display特征呢?
看到
use self::tb_article::dsl: