Rust開發問題記錄

cannot find derive macro Deserializ in this scope

error: 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


cannot infer type for 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?sql

Using the provided examples for a simple-auth-server I can
authenticate a request and create a cookie accordingly.docker

Now 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.centos

I 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

完整代碼已提交github rust_cms

部署的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 struct std::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:

相關文章
相關標籤/搜索