Blog Classic Style

Posted on 1月 5, 2020

上次有人问我关于OPTIONS,我的知识还停留在HTTP的GET/POST,

现在的HTTP 1.1已经有GET/POST/PUT/DELETE/PATCH了,那还有一个OPTIONS是什么呢?

其实就是flash年代的跨站访问!浏览器firefox/chrome为了网站的安全,在访问前,先发送一个OPTIONS的请求,在得到服务器的回应并允许之后,再发送其它的请求,actix_web提供了actix_cors来解决这下问题!

如下代码:

use actix_cors::Cors;
...
    
HttpServer::new(move || {
        App::new()
            .wrap(Cors::new() //
                // .allowed_origin("http://127.0.0.1:8080")
                .send_wildcard()
                .allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
                .allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT])
                .allowed_header(http::header::CONTENT_TYPE)
                .max_age(3600)
                .finish())
            .data(pool.clone())
            .wrap(actix_web::middleware::Logger::default())
            .wrap(crate::middleware::authen_middleware::Authentication)
            .wrap_fn(|req, srv| {
               srv.call(req).map(|res| res)
           })
            .configure(config::app::config_services)
        })
    .bind(&app_url)?
    .run()
    .await

如上代码,允许所有的访问来源(Access-Control-Allow-Origin: *); 如果取消注释,就仅允许来自于http://127.0.0.1:8080的访问!

 

Posted on 1月 2, 2020

 Diesel使用宏定义,来定义数据库映射数据,导入的话只要如下语句:

    use crate::schema::warehouse::{dsl::*},

在上一篇讲的,inner join的话, 如下:

warehouse::table
    .inner_join(commodity::table.on(warehouse::commodity_id.eq(commodity::id)))
    .select((warehouse::id, warehouse::commodity_id,
             commodity::title, commodity::summary, warehouse::num))
    .filter(warehouse::user_id.eq(uid))
    .get_results::<WareHouseCommodityDTO>(conn)

 即指定字段的来源,即表名:warehouse::id

然而今天在做一个transaction时,还是出现如下的问题

error[E0659]: `commodity_id` is ambiguous (glob import vs glob import in the same module)
  --> src/services/apply_service.rs:40:54
   |
40 |                  .set((expired_date.eq(new_expired), commodity_id.eq(appdt.commodity_id)))
   |                                                      ^^^^^^^^^^^^ ambiguous name
   |
note: `commodity_id` could refer to the unit struct imported here

来本以为用table1::commodity_id这样就能解决,原因就在于table1与table2都存在一个同名的commodity_id的字段,diesel的issues上也没有同样的问题,

最后解决的代码如下:

    schema::warehouse::{dsl::*},
    schema::users::{
        dsl::{users, expired_date, commodity_id as users_cmd_id, email, devices_limit},
    },

warehouse还是按原来一样的导入,users的commodity_id修改成新的名字!问题解决!

Posted on 1月 1, 2020

用Rust写的第一个小项目,按IP地址来统计服务器的流量!

首先,用iftop指令收集数据:

crontab -e

*/3 * * * *     /usr/sbin/iftop -t -s 30 >> /var/log/traffic.log

第三分钟收集一下流量数据!存入到traffic.log文件!

其次,用shell批令精简一下数据!

cat traffic.log |awk '{ print $1,$2,$6,$7 }' > traffic-reduce.log

最后, cargo run traffic-reduce.log 得到数据!按流量排名!如图!toptraffic

源代码地址: https://github.com/wenewzhang/top-traffic

Posted on 12月 29, 2019

inner join 的代码如下:

        warehouse::table
            .inner_join(commodity::table.on(warehouse::commodity_id.eq(commodity::id)))
            .select((warehouse::commodity_id,commodity::title,commodity::summary,warehouse::num))
            .filter(warehouse::user_id.eq(uid))
            .get_results::<WareHouseCommodityDTO>(conn)

有两点需要注意:

第一  在schema里定义好宏

allow_tables_to_appear_in_same_query!(
    commodity,
    warehouse,
);

第二 定放好接收的数据结构

#[derive(Serialize, Queryable, Debug)]
pub struct WareHouseCommodityDTO {
    pub commodity_id: i32,
    pub title: String,
    pub summary: String,
    // pub body: String,
    pub num: i32,
}

 

Posted on 12月 29, 2019

基于Actix_web的REST API项目,用JWT来认证,很多的Request会需要使用到同样的login_session等内容,

可以在路由到特定的目标路径之前,将token里的login_session解密后取出,并注入到Header中:

if let Ok(token_data) = token_utils::decode_token(token.to_string()) {
    info!("Decoding token...");
    let email = HeaderValue::from_str(&token_data.claims.user).unwrap();
    let headers = req.headers_mut();
    // let val = HeaderValue::from_str("hello").unwrap();
    headers.append(HeaderName::from_static("email"),email);

在需要使用的模块中,再取出:

    match req.headers().get("email") {
        Some(email) => {
//do something here
        },
        None => ()
    };

 

Posted on 12月 26, 2019

Rust与erlang一样,什么样的语句后面需要或不需要分号,都有不好言说的特点,这些特点,

编译器会告诉你,比如下面的语句,IF的Ok/Err都是匹配到Result, 此时不需要加分号!

pub fn myinfo(email: &str, pool: &web::Data<Pool>) -> Result<User, ServiceError> {
    if let Ok(user) = User::find_user_by_email(&email,  &pool.get().unwrap()) {
         Ok(user)
    } else {
         Err(ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_PROCESS_TOKEN_ERROR.to_string()))
    }

下面的写法也没有问题(Ok/Err后面的分号是可以去掉的):

pub fn myinfo(email: &str, pool: &web::Data<Pool>) -> Result<User, ServiceError> {
    if let Ok(user) = User::find_user_by_email(&email,  &pool.get().unwrap()) {
         return Ok(user);
    } else {
         return Err(ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, constants::MESSAGE_PROCESS_TOKEN_ERROR.to_string()));
    }

但为了代码的简洁,用第一种方法即可!

下面的代码,第个match语句的ok前必需加return:

pub fn myinfo(req: HttpRequest, pool: web::Data<Pool>) -> impl Future<Item = HttpResponse, Error = Error> {
    info!("{:?}",req);
    match req.headers().get("email") {
        Some(email) => {
            match account_service::myinfo(email.to_str().unwrap(), &pool) {
                Err(e) => error!("{:?}", e),
                Ok(user) => return ok(HttpResponse::Ok().json(ResponseBody::new(constants::MESSAGE_OK, user))),
            }},
        None => ()
    }
    ok(HttpResponse::BadRequest().json(ResponseBody::new(constants::MESSAGE_TOKEN_MISSING, constants::EMPTY)))
}

因为return是直接将数据返回,这是一个Future的结构体,如果不加return, 则是返回给外层的match, 而外层

的match需要的是一个(), 如None返回的那样,这时就会产生一个编译错误!

error[E0308]: match arms have incompatible types
  --> src/api/account_controller.rs:76:29
   |
74 | /             match account_service::myinfo(email.to_str().unwrap(), &pool) {
75 | |                 Err(e) => error!("{:?}", e),
   | |                           ----------------- this is found to be of type `()`
76 | |                 Ok(user) => ok(HttpResponse::Ok().json(ResponseBody::new(constants::MESSAGE_OK, user))),
   | |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `futures::Done`
77 | |             }},
   | |_____________- `match` arms have incompatible types
   |
   = note: expected type `()`
              found type `futures::Done<actix_web::HttpResponse, _>`
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

 

Posted on 12月 23, 2019

在交易相关的书中,我花的最多的时间就是缠论,写过10多本笔记,有一半是写缠论的!

总结这几年的心得:

  1. 真传一句话,假传万卷书!
  2. 他在缠论课外的讨论中,透出了真实想法: 第一 交易体系需要三个独立的系统来支撑,也就是说三个观察的体系保证投资总体走向盈利!第二 任何想通过一次交易发大财的是不可行的,最后结局都会很惨! Livemore就是一个实例!
  3. 多看K线自己总结,108课提供了具体的分析方法!

最后,盘整/调整 背驰的识别是高级技巧,缠师反复强调了,但他并没有明说!

今年最后几天了,空仓的,4个月A股总收益6.58%, 远远达不到梁宏的单用9%, 但我似乎猜到梁大师玩的是什么股,未来一年会调整一下交易的标的!

six-percent