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: