面包屑
- 首页
- 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 得到数据!按流量排名!如图!
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多本笔记,有一半是写缠论的!
总结这几年的心得:
最后,盘整/调整 背驰的识别是高级技巧,缠师反复强调了,但他并没有明说!
今年最后几天了,空仓的,4个月A股总收益6.58%, 远远达不到梁宏的单用9%, 但我似乎猜到梁大师玩的是什么股,未来一年会调整一下交易的标的!