1
0
mirror of https://github.com/actix/examples synced 2024-11-23 22:41:07 +01:00

update deps

This commit is contained in:
Nikolay Kim 2019-03-29 13:43:03 -07:00
parent 48b8e7c335
commit e4f71e8fd5
47 changed files with 307 additions and 415 deletions

View File

@ -2,13 +2,15 @@
name = "actix_redis" name = "actix_redis"
version = "0.1.0" version = "0.1.0"
authors = ["dowwie <dkcdkg@gmail.com>"] authors = ["dowwie <dkcdkg@gmail.com>"]
edition = "2018"
workspace = ".."
[dependencies] [dependencies]
actix = "0.7.3" actix = "0.8.0-alpha.2"
actix-web = "0.7.3" actix-web = "1.0.0-alpha.1"
actix-redis = "0.5.1" actix-redis = { git="https://github.com/actix/actix-redis.git" }
futures = "0.1.23" futures = "0.1.23"
redis-async = "0.4.0" redis-async = "0.4.0"
serde = "1.0.71" serde = "1.0.71"
serde_derive = "1.0.71" serde_derive = "1.0.71"
env_logger = "0.5.12" env_logger = "0.6"

View File

@ -1,23 +1,13 @@
extern crate actix;
extern crate actix_redis;
extern crate actix_web;
extern crate env_logger;
extern crate futures;
#[macro_use] #[macro_use]
extern crate redis_async; extern crate redis_async;
extern crate serde;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
use actix::prelude::*; use actix::prelude::*;
use actix_redis::{Command, Error as ARError, RedisActor}; use actix_redis::{Command, Error as ARError, RedisActor};
use actix_web::{ use actix_web::{middleware, web, App, Error as AWError, HttpResponse, HttpServer};
http::Method, middleware, server, App, AsyncResponder, Error as AWError,
HttpRequest, HttpResponse, Json,
};
use futures::future::{join_all, Future}; use futures::future::{join_all, Future};
use redis_async::resp::RespValue; use redis_async::resp::RespValue;
use std::sync::Arc;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct CacheInfo { pub struct CacheInfo {
@ -27,10 +17,10 @@ pub struct CacheInfo {
} }
fn cache_stuff( fn cache_stuff(
(info, req): (Json<CacheInfo>, HttpRequest<AppState>), info: web::Json<CacheInfo>,
redis: web::Data<Addr<RedisActor>>,
) -> impl Future<Item = HttpResponse, Error = AWError> { ) -> impl Future<Item = HttpResponse, Error = AWError> {
let info = info.into_inner(); let info = info.into_inner();
let redis = req.state().redis_addr.clone();
let one = redis.send(Command(resp_array!["SET", "mydomain:one", info.one])); let one = redis.send(Command(resp_array!["SET", "mydomain:one", info.one]));
let two = redis.send(Command(resp_array!["SET", "mydomain:two", info.two])); let two = redis.send(Command(resp_array!["SET", "mydomain:two", info.two]));
@ -46,26 +36,23 @@ fn cache_stuff(
let info_set = join_all(vec![one, two, three].into_iter()); let info_set = join_all(vec![one, two, three].into_iter());
info_set info_set
.map_err(AWError::from) .map_err(AWError::from)
.and_then(|res: Vec<Result<RespValue, ARError>>| .and_then(|res: Vec<Result<RespValue, ARError>>|
// successful operations return "OK", so confirm that all returned as so // successful operations return "OK", so confirm that all returned as so
if !res.iter().all(|res| match res { if !res.iter().all(|res| match res {
Ok(RespValue::SimpleString(x)) if x=="OK" => true, Ok(RespValue::SimpleString(x)) if x=="OK" => true,
_ => false _ => false
}) { }) {
Ok(HttpResponse::InternalServerError().finish()) Ok(HttpResponse::InternalServerError().finish())
} else { } else {
Ok(HttpResponse::Ok().body("successfully cached values")) Ok(HttpResponse::Ok().body("successfully cached values"))
} }
) )
.responder()
} }
fn del_stuff( fn del_stuff(
req: HttpRequest<AppState>, redis: web::Data<Addr<RedisActor>>,
) -> impl Future<Item = HttpResponse, Error = AWError> { ) -> impl Future<Item = HttpResponse, Error = AWError> {
let redis = req.state().redis_addr.clone();
redis redis
.send(Command(resp_array![ .send(Command(resp_array![
"DEL", "DEL",
@ -83,33 +70,24 @@ fn del_stuff(
Ok(HttpResponse::InternalServerError().finish()) Ok(HttpResponse::InternalServerError().finish())
} }
}) })
.responder()
} }
pub struct AppState { fn main() -> std::io::Result<()> {
pub redis_addr: Arc<Addr<RedisActor>>, std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info");
}
fn main() {
::std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info");
env_logger::init(); env_logger::init();
let sys = actix::System::new("actix_redis_ex");
server::new(|| { HttpServer::new(|| {
let redis_addr = Arc::new(RedisActor::start("127.0.0.1:6379")); let redis_addr = RedisActor::start("127.0.0.1:6379");
let app_state = AppState { redis_addr };
App::with_state(app_state) App::new()
.middleware(middleware::Logger::default()) .data(redis_addr)
.resource("/stuff", |r| { .wrap(middleware::Logger::default())
r.method(Method::POST).with_async(cache_stuff); .service(
r.method(Method::DELETE).with_async(del_stuff) web::resource("/stuff")
}) .route(web::post().to_async(cache_stuff))
.route(web::delete().to_async(del_stuff)),
)
}) })
.bind("0.0.0.0:8080") .bind("0.0.0.0:8080")?
.unwrap() .run()
.workers(1)
.start();
let _ = sys.run();
} }

View File

@ -6,9 +6,9 @@ workspace = ".."
edition = "2018" edition = "2018"
[dependencies] [dependencies]
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
actix-files = { git="https://github.com/actix/actix-web.git" } actix-files = "0.1.0-alpha.1"
actix-session = { git="https://github.com/actix/actix-web.git" } actix-session = "0.1.0-alpha.1"
dotenv = "0.13.0" dotenv = "0.13.0"
env_logger = "0.5.10" env_logger = "0.5.10"
futures = "0.1.22" futures = "0.1.22"

View File

@ -7,7 +7,7 @@ workspace = ".."
[dependencies] [dependencies]
actix-rt = "0.2" actix-rt = "0.2"
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
dotenv = "0.10" dotenv = "0.10"
env_logger = "0.5" env_logger = "0.5"

View File

@ -7,7 +7,7 @@ workspace = ".."
[dependencies] [dependencies]
actix-rt = "0.2" actix-rt = "0.2"
actix-web = { git="https://github.com/actix/actix-web.git", features=["ssl"] } actix-web = { version="1.0.0-alpha.1", features=["ssl"] }
futures = "0.1" futures = "0.1"
serde = "1.0.43" serde = "1.0.43"

View File

@ -7,9 +7,9 @@ edition = "2018"
[dependencies] [dependencies]
actix-rt = "0.2" actix-rt = "0.2"
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
actix-files = { git="https://github.com/actix/actix-web.git" } actix-files = "0.1.0-alpha.1"
actix-session = { git="https://github.com/actix/actix-web.git" } actix-session = "0.1.0-alpha.1"
futures = "0.1.25" futures = "0.1.25"
env_logger = "0.5" env_logger = "0.5"

View File

@ -6,5 +6,5 @@ edition = "2018"
workspace = ".." workspace = ".."
[dependencies] [dependencies]
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
env_logger = "0.6" env_logger = "0.6"

View File

@ -6,8 +6,8 @@ workspace = ".."
edition = "2018" edition = "2018"
[dependencies] [dependencies]
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
actix-session = { git="https://github.com/actix/actix-web.git" } actix-session = "0.1.0-alpha.1"
futures = "0.1" futures = "0.1"
time = "0.1" time = "0.1"

View File

@ -6,7 +6,7 @@ workspace = ".."
edition = "2018" edition = "2018"
[dependencies] [dependencies]
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
bytes = "0.4" bytes = "0.4"
env_logger = "0.6" env_logger = "0.6"

View File

@ -6,7 +6,7 @@ edition = "2018"
workspace = ".." workspace = ".."
[dependencies] [dependencies]
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
derive_more = "0.14.0" derive_more = "0.14.0"
futures = "0.1.23" futures = "0.1.23"

View File

@ -6,7 +6,7 @@ edition = "2018"
workspace = ".." workspace = ".."
[dependencies] [dependencies]
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"

View File

@ -6,5 +6,5 @@ workspace = ".."
edition = "2018" edition = "2018"
[dependencies] [dependencies]
actix-web = "1.0.0-alpha.1"
env_logger = "0.6" env_logger = "0.6"
actix-web = { git="https://github.com/actix/actix-web.git" }

View File

@ -7,7 +7,7 @@ edition = "2018"
[dependencies] [dependencies]
actix-rt = "0.2" actix-rt = "0.2"
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
clap = "2.32.0" clap = "2.32.0"
futures = "0.1.25" futures = "0.1.25"

View File

@ -15,7 +15,7 @@ path = "src/server.rs"
[dependencies] [dependencies]
actix-rt = "0.2" actix-rt = "0.2"
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
env_logger = "0.5" env_logger = "0.5"
futures = "0.1" futures = "0.1"

View File

@ -6,7 +6,7 @@ workspace = ".."
edition = "2018" edition = "2018"
[dependencies] [dependencies]
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
bytes = "0.4" bytes = "0.4"
futures = "0.1" futures = "0.1"

View File

@ -6,7 +6,7 @@ workspace = ".."
edition = "2018" edition = "2018"
[dependencies] [dependencies]
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
env_logger = "0.6" env_logger = "0.6"
futures = "0.1" futures = "0.1"
serde = "1.0" serde = "1.0"

View File

@ -7,6 +7,6 @@ workspace = ".."
[dependencies] [dependencies]
actix-service = "0.3.3" actix-service = "0.3.3"
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
futures = "0.1.25" futures = "0.1.25"
env_logger = "0.6" env_logger = "0.6"

View File

@ -2,15 +2,16 @@
name = "multipart-example" name = "multipart-example"
version = "0.1.0" version = "0.1.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
workspace = "../" workspace = ".."
edition = "2018"
[[bin]] [[bin]]
name = "multipart" name = "multipart"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
env_logger = "*" #actix-web = "1.0.0-alpha.1"
futures = "0.1" actix-web = { git="https://github.com/actix/actix-web.git" }
actix = "0.7" env_logger = "0.6"
actix-web = "0.7" futures = "0.1.25"

View File

@ -1,44 +1,30 @@
#![allow(unused_variables)]
extern crate actix;
extern crate actix_web;
extern crate env_logger;
extern crate futures;
use std::cell::Cell; use std::cell::Cell;
use std::fs; use std::fs;
use std::io::Write; use std::io::Write;
use actix_web::{ use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer};
dev, error, http, middleware, multipart, server, App, Error, FutureResponse, use futures::future::{err, Either};
HttpMessage, HttpRequest, HttpResponse,
};
use futures::future;
use futures::{Future, Stream}; use futures::{Future, Stream};
pub struct AppState { pub struct AppState {
pub counter: Cell<usize>, pub counter: Cell<usize>,
} }
pub fn save_file( pub fn save_file(field: web::MultipartField) -> impl Future<Item = i64, Error = Error> {
field: multipart::Field<dev::Payload>,
) -> Box<Future<Item = i64, Error = Error>> {
let file_path_string = "upload.png"; let file_path_string = "upload.png";
let mut file = match fs::File::create(file_path_string) { let mut file = match fs::File::create(file_path_string) {
Ok(file) => file, Ok(file) => file,
Err(e) => return Box::new(future::err(error::ErrorInternalServerError(e))), Err(e) => return Either::A(err(error::ErrorInternalServerError(e))),
}; };
Box::new( Either::B(
field field
.fold(0i64, move |acc, bytes| { .fold(0i64, move |acc, bytes| {
let rt = file file.write_all(bytes.as_ref())
.write_all(bytes.as_ref())
.map(|_| acc + bytes.len() as i64) .map(|_| acc + bytes.len() as i64)
.map_err(|e| { .map_err(|e| {
println!("file.write_all failed: {:?}", e); println!("file.write_all failed: {:?}", e);
error::MultipartError::Payload(error::PayloadError::Io(e)) error::MultipartError::Payload(error::PayloadError::Io(e))
}); })
future::result(rt)
}) })
.map_err(|e| { .map_err(|e| {
println!("save_file failed, {:?}", e); println!("save_file failed, {:?}", e);
@ -48,13 +34,11 @@ pub fn save_file(
} }
pub fn handle_multipart_item( pub fn handle_multipart_item(
item: multipart::MultipartItem<dev::Payload>, item: web::MultipartItem,
) -> Box<Stream<Item = i64, Error = Error>> { ) -> Box<Stream<Item = i64, Error = Error>> {
match item { match item {
multipart::MultipartItem::Field(field) => { web::MultipartItem::Field(field) => Box::new(save_file(field).into_stream()),
Box::new(save_file(field).into_stream()) web::MultipartItem::Nested(mp) => Box::new(
}
multipart::MultipartItem::Nested(mp) => Box::new(
mp.map_err(error::ErrorInternalServerError) mp.map_err(error::ErrorInternalServerError)
.map(handle_multipart_item) .map(handle_multipart_item)
.flatten(), .flatten(),
@ -62,24 +46,26 @@ pub fn handle_multipart_item(
} }
} }
pub fn upload(req: HttpRequest<AppState>) -> FutureResponse<HttpResponse> { pub fn upload(
req.state().counter.set(req.state().counter.get() + 1); multipart: web::Multipart,
println!("{:?}", req.state().counter.get()); counter: web::Data<Cell<usize>>,
Box::new( ) -> impl Future<Item = HttpResponse, Error = Error> {
req.multipart() counter.set(counter.get() + 1);
.map_err(error::ErrorInternalServerError) println!("{:?}", counter.get());
.map(handle_multipart_item)
.flatten() multipart
.collect() .map_err(error::ErrorInternalServerError)
.map(|sizes| HttpResponse::Ok().json(sizes)) .map(handle_multipart_item)
.map_err(|e| { .flatten()
println!("failed: {}", e); .collect()
e .map(|sizes| HttpResponse::Ok().json(sizes))
}), .map_err(|e| {
) println!("failed: {}", e);
e
})
} }
fn index(_req: HttpRequest<AppState>) -> Result<HttpResponse, error::Error> { fn index() -> HttpResponse {
let html = r#"<html> let html = r#"<html>
<head><title>Upload Test</title></head> <head><title>Upload Test</title></head>
<body> <body>
@ -90,28 +76,23 @@ fn index(_req: HttpRequest<AppState>) -> Result<HttpResponse, error::Error> {
</body> </body>
</html>"#; </html>"#;
Ok(HttpResponse::Ok().body(html)) HttpResponse::Ok().body(html)
} }
fn main() { fn main() -> std::io::Result<()> {
::std::env::set_var("RUST_LOG", "actix_web=info"); std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info");
env_logger::init(); env_logger::init();
let sys = actix::System::new("multipart-example");
server::new(|| { HttpServer::new(|| {
App::with_state(AppState { App::new()
counter: Cell::new(0), .data(Cell::new(0usize))
}) .wrap(middleware::Logger::default())
.middleware(middleware::Logger::default()) .service(
.resource("/", |r| { web::resource("/")
r.method(http::Method::GET).with(index); .route(web::get().to(index))
r.method(http::Method::POST).with(upload); .route(web::post().to_async(upload)),
}) )
}) })
.bind("127.0.0.1:8080") .bind("127.0.0.1:8080")?
.unwrap() .run()
.start();
println!("Starting http server: 127.0.0.1:8080");
let _ = sys.run();
} }

View File

@ -3,11 +3,11 @@ name = "r2d2-example"
version = "0.1.0" version = "0.1.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
edition = "2018" edition = "2018"
workspace = "../" workspace = ".."
[dependencies] [dependencies]
actix-rt = "0.2" actix-rt = "0.2"
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
futures = "0.1" futures = "0.1"
env_logger = "0.6" env_logger = "0.6"

View File

@ -2,10 +2,12 @@
name = "redis-session" name = "redis-session"
version = "0.1.0" version = "0.1.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
workspace = "../" workspace = ".."
edition = "2018"
[dependencies] [dependencies]
env_logger = "0.5" actix = "0.8.0-alpha.2"
actix = "0.7" actix-web = "1.0.0-alpha.1"
actix-web = "0.7.3" actix-session = "0.1.0-alpha.1"
actix-redis = { version = "0.5.1", features = ["web"] } actix-redis = { git = "https://github.com/actix/actix-redis.git", features = ["web"] }
env_logger = "0.6"

View File

@ -1,50 +1,38 @@
//! Example of redis based session //! Example of redis based session
//! //!
//! [User guide](https://actix.rs/book/actix-web/sec-9-middlewares.html#user-sessions) //! [User guide](https://actix.rs/book/actix-web/sec-9-middlewares.html#user-sessions)
extern crate actix; use actix_redis::RedisSession;
extern crate actix_redis; use actix_session::Session;
extern crate actix_web; use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer, Result};
extern crate env_logger;
use actix_redis::RedisSessionBackend;
use actix_web::middleware::session::{RequestSession, SessionStorage};
use actix_web::{middleware, server, App, HttpRequest, HttpResponse, Result};
/// simple handler /// simple handler
fn index(req: &HttpRequest) -> Result<HttpResponse> { fn index(req: HttpRequest, session: Session) -> Result<HttpResponse> {
println!("{:?}", req); println!("{:?}", req);
// session // session
if let Some(count) = req.session().get::<i32>("counter")? { if let Some(count) = session.get::<i32>("counter")? {
println!("SESSION value: {}", count); println!("SESSION value: {}", count);
req.session().set("counter", count + 1)?; session.set("counter", count + 1)?;
} else { } else {
req.session().set("counter", 1)?; session.set("counter", 1)?;
} }
Ok("Welcome!".into()) Ok("Welcome!".into())
} }
fn main() { fn main() -> std::io::Result<()> {
::std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info"); std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info");
env_logger::init(); env_logger::init();
let sys = actix::System::new("basic-example");
server::new(|| { HttpServer::new(|| {
App::new() App::new()
// enable logger // enable logger
.middleware(middleware::Logger::default()) .wrap(middleware::Logger::default())
// redis session middleware // redis session middleware
.middleware(SessionStorage::new(RedisSessionBackend::new( .wrap(RedisSession::new("127.0.0.1:6379", &[0; 32]))
"127.0.0.1:6379",
&[0; 32],
)))
// register simple route, handle all methods // register simple route, handle all methods
.resource("/", |r| r.f(index)) .service(web::resource("/").to(index))
}) })
.bind("127.0.0.1:8080") .bind("127.0.0.1:8080")?
.unwrap() .run()
.start();
let _ = sys.run();
} }

View File

@ -2,18 +2,22 @@
name = "simple-auth-server" name = "simple-auth-server"
version = "0.1.0" version = "0.1.0"
authors = ["mygnu <tech@hgill.io>"] authors = ["mygnu <tech@hgill.io>"]
edition = "2018"
workspace = ".."
[dependencies] [dependencies]
actix = "0.7.7" actix = { version = "0.8.0-alpha.2", features = ["http"] }
actix-web = "0.7.14" actix-web = "1.0.0-alpha.1"
actix-files = "0.1.0-alpha.1"
bcrypt = "0.2.1" bcrypt = "0.2.1"
chrono = { version = "0.4.6", features = ["serde"] } chrono = { version = "0.4.6", features = ["serde"] }
diesel = { version = "1.3.3", features = ["postgres", "uuid", "r2d2", "chrono"] } diesel = { version = "1.3.3", features = ["postgres", "uuid", "r2d2", "chrono"] }
dotenv = "0.13.0" dotenv = "0.13.0"
derive_more = "0.14"
env_logger = "0.6.0" env_logger = "0.6.0"
failure = "0.1.3"
jsonwebtoken = "5.0" jsonwebtoken = "5.0"
futures = "0.1" futures = "0.1.25"
r2d2 = "0.8.3" r2d2 = "0.8.3"
serde_derive="1.0.80" serde_derive="1.0.80"
serde_json="1.0" serde_json="1.0"

View File

@ -1,56 +0,0 @@
use actix::prelude::*;
use actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService};
use actix_web::{fs, http::Method, middleware::Logger, App};
use auth_routes::{get_me, login, logout};
use chrono::Duration;
use invitation_routes::register_email;
use models::DbExecutor;
use register_routes::register_user;
pub struct AppState {
pub db: Addr<DbExecutor>,
}
/// creates and returns the app after mounting all routes/resources
pub fn create_app(db: Addr<DbExecutor>) -> App<AppState> {
// secret is a random minimum 32 bytes long base 64 string
let secret: String =
std::env::var("SECRET_KEY").unwrap_or_else(|_| "0123".repeat(8));
let domain: String =
std::env::var("DOMAIN").unwrap_or_else(|_| "localhost".to_string());
App::with_state(AppState { db })
.middleware(Logger::default())
.middleware(IdentityService::new(
CookieIdentityPolicy::new(secret.as_bytes())
.name("auth")
.path("/")
.domain(domain.as_str())
.max_age(Duration::days(1))
.secure(false), // this can only be true if you have https
))
// everything under '/api/' route
.scope("/api", |api| {
// routes for authentication
api.resource("/auth", |r| {
r.method(Method::POST).with(login);
r.method(Method::DELETE).with(logout);
r.method(Method::GET).with(get_me);
})
// routes to invitation
.resource("/invitation", |r| {
r.method(Method::POST).with(register_email);
})
// routes to register as a user after the
.resource("/register/{invitation_id}", |r| {
r.method(Method::POST).with(register_user);
})
})
// serve static files
.handler(
"/",
fs::StaticFiles::new("./static/")
.unwrap()
.index_file("index.html"),
)
}

View File

@ -1,10 +1,12 @@
use actix::{Handler, Message}; use actix::{Handler, Message};
use actix_web::{middleware::identity::RequestIdentity, FromRequest, HttpRequest}; use actix_web::{dev::ServiceFromRequest, Error};
use actix_web::{middleware::identity::Identity, FromRequest, HttpRequest};
use bcrypt::verify; use bcrypt::verify;
use diesel::prelude::*; use diesel::prelude::*;
use errors::ServiceError;
use models::{DbExecutor, SlimUser, User}; use crate::errors::ServiceError;
use utils::decode_token; use crate::models::{DbExecutor, SlimUser, User};
use crate::utils::decode_token;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct AuthData { pub struct AuthData {
@ -19,7 +21,7 @@ impl Message for AuthData {
impl Handler<AuthData> for DbExecutor { impl Handler<AuthData> for DbExecutor {
type Result = Result<SlimUser, ServiceError>; type Result = Result<SlimUser, ServiceError>;
fn handle(&mut self, msg: AuthData, _: &mut Self::Context) -> Self::Result { fn handle(&mut self, msg: AuthData, _: &mut Self::Context) -> Self::Result {
use schema::users::dsl::{email, users}; use crate::schema::users::dsl::{email, users};
let conn: &PgConnection = &self.0.get().unwrap(); let conn: &PgConnection = &self.0.get().unwrap();
let mut items = users.filter(email.eq(&msg.email)).load::<User>(conn)?; let mut items = users.filter(email.eq(&msg.email)).load::<User>(conn)?;
@ -44,14 +46,15 @@ impl Handler<AuthData> for DbExecutor {
// simple aliasing makes the intentions clear and its more readable // simple aliasing makes the intentions clear and its more readable
pub type LoggedUser = SlimUser; pub type LoggedUser = SlimUser;
impl<S> FromRequest<S> for LoggedUser { impl<P> FromRequest<P> for LoggedUser {
type Config = (); type Error = Error;
type Result = Result<LoggedUser, ServiceError>; type Future = Result<LoggedUser, Error>;
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
if let Some(identity) = req.identity() { fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
if let Some(identity) = Identity::from_request(req)?.identity() {
let user: SlimUser = decode_token(&identity)?; let user: SlimUser = decode_token(&identity)?;
return Ok(user as LoggedUser); return Ok(user as LoggedUser);
} }
Err(ServiceError::Unauthorized) Err(ServiceError::Unauthorized.into())
} }
} }

View File

@ -1,34 +1,32 @@
use actix_web::middleware::identity::RequestIdentity; use actix::Addr;
use actix_web::{ use actix_web::middleware::identity::Identity;
AsyncResponder, FutureResponse, HttpRequest, HttpResponse, Json, ResponseError, use actix_web::{web, Error, HttpRequest, HttpResponse, Responder, ResponseError};
}; use futures::Future;
use futures::future::Future;
use utils::create_token;
use app::AppState; use crate::auth_handler::{AuthData, LoggedUser};
use auth_handler::{AuthData, LoggedUser}; use crate::models::DbExecutor;
use crate::utils::create_token;
pub fn login( pub fn login(
(auth_data, req): (Json<AuthData>, HttpRequest<AppState>), auth_data: web::Json<AuthData>,
) -> FutureResponse<HttpResponse> { id: Identity,
req.state() db: web::Data<Addr<DbExecutor>>,
.db ) -> impl Future<Item = HttpResponse, Error = Error> {
.send(auth_data.into_inner()) db.send(auth_data.into_inner())
.from_err() .from_err()
.and_then(move |res| match res { .and_then(move |res| match res {
Ok(user) => { Ok(user) => {
let token = create_token(&user)?; let token = create_token(&user)?;
req.remember(token); id.remember(token);
Ok(HttpResponse::Ok().into()) Ok(HttpResponse::Ok().into())
} }
Err(err) => Ok(err.error_response()), Err(err) => Ok(err.error_response()),
}) })
.responder()
} }
pub fn logout(req: HttpRequest<AppState>) -> HttpResponse { pub fn logout(id: Identity) -> impl Responder {
req.forget(); id.forget();
HttpResponse::Ok().into() HttpResponse::Ok()
} }
pub fn get_me(logged_user: LoggedUser) -> HttpResponse { pub fn get_me(logged_user: LoggedUser) -> HttpResponse {

View File

@ -1,4 +1,4 @@
use models::Invitation; use crate::models::Invitation;
use sparkpost::transmission::{ use sparkpost::transmission::{
EmailAddress, Message, Options, Recipient, Transmission, TransmissionResponse, EmailAddress, Message, Options, Recipient, Transmission, TransmissionResponse,
}; };

View File

@ -1,17 +1,18 @@
use actix_web::{error::ResponseError, HttpResponse}; use actix_web::{error::ResponseError, HttpResponse};
use derive_more::Display;
use diesel::result::{DatabaseErrorKind, Error}; use diesel::result::{DatabaseErrorKind, Error};
use std::convert::From; use std::convert::From;
use uuid::ParseError; use uuid::ParseError;
#[derive(Fail, Debug)] #[derive(Debug, Display)]
pub enum ServiceError { pub enum ServiceError {
#[fail(display = "Internal Server Error")] #[display(fmt = "Internal Server Error")]
InternalServerError, InternalServerError,
#[fail(display = "BadRequest: {}", _0)] #[display(fmt = "BadRequest: {}", _0)]
BadRequest(String), BadRequest(String),
#[fail(display = "Unauthorized")] #[display(fmt = "Unauthorized")]
Unauthorized, Unauthorized,
} }

View File

@ -1,10 +1,11 @@
use actix::{Handler, Message}; use actix::{Handler, Message};
use chrono::{Duration, Local}; use chrono::{Duration, Local};
use diesel::{self, prelude::*}; use diesel::{self, prelude::*};
use errors::ServiceError;
use models::{DbExecutor, Invitation};
use uuid::Uuid; use uuid::Uuid;
use crate::errors::ServiceError;
use crate::models::{DbExecutor, Invitation};
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct CreateInvitation { pub struct CreateInvitation {
pub email: String, pub email: String,
@ -18,7 +19,7 @@ impl Handler<CreateInvitation> for DbExecutor {
type Result = Result<Invitation, ServiceError>; type Result = Result<Invitation, ServiceError>;
fn handle(&mut self, msg: CreateInvitation, _: &mut Self::Context) -> Self::Result { fn handle(&mut self, msg: CreateInvitation, _: &mut Self::Context) -> Self::Result {
use schema::invitations::dsl::*; use crate::schema::invitations::dsl::*;
let conn: &PgConnection = &self.0.get().unwrap(); let conn: &PgConnection = &self.0.get().unwrap();
// creating a new Invitation object with expired at time that is 24 hours from now // creating a new Invitation object with expired at time that is 24 hours from now

View File

@ -1,18 +1,16 @@
use actix_web::{ use actix::Addr;
AsyncResponder, FutureResponse, HttpResponse, Json, ResponseError, State, use actix_web::{web, Error, HttpResponse, ResponseError};
};
use futures::future::Future; use futures::future::Future;
use app::AppState; use crate::email_service::send_invitation;
use email_service::send_invitation; use crate::invitation_handler::CreateInvitation;
use invitation_handler::CreateInvitation; use crate::models::DbExecutor;
pub fn register_email( pub fn register_email(
(signup_invitation, state): (Json<CreateInvitation>, State<AppState>), signup_invitation: web::Json<CreateInvitation>,
) -> FutureResponse<HttpResponse> { db: web::Data<Addr<DbExecutor>>,
state ) -> impl Future<Item = HttpResponse, Error = Error> {
.db db.send(signup_invitation.into_inner())
.send(signup_invitation.into_inner())
.from_err() .from_err()
.and_then(|db_response| match db_response { .and_then(|db_response| match db_response {
Ok(invitation) => { Ok(invitation) => {
@ -21,5 +19,4 @@ pub fn register_email(
} }
Err(err) => Ok(err.error_response()), Err(err) => Ok(err.error_response()),
}) })
.responder()
} }

View File

@ -1,26 +1,21 @@
// to avoid the warning from diesel macros #![allow(unused_imports)]
#![allow(proc_macro_derive_resolution_fallback)]
extern crate actix;
extern crate actix_web;
extern crate bcrypt;
extern crate chrono;
extern crate dotenv;
extern crate env_logger;
extern crate futures;
extern crate jsonwebtoken as jwt;
extern crate r2d2;
extern crate serde;
extern crate sparkpost;
extern crate uuid;
#[macro_use] #[macro_use]
extern crate diesel; extern crate diesel;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[macro_use]
extern crate failure;
mod app; use actix::prelude::*;
use actix_files as fs;
use actix_web::middleware::{
identity::{CookieIdentityPolicy, IdentityService},
Logger,
};
use actix_web::{web, App, HttpServer};
use chrono::Duration;
use diesel::{r2d2::ConnectionManager, PgConnection};
use dotenv::dotenv;
mod auth_handler; mod auth_handler;
mod auth_routes; mod auth_routes;
mod email_service; mod email_service;
@ -33,20 +28,17 @@ mod register_routes;
mod schema; mod schema;
mod utils; mod utils;
use actix::prelude::*; use crate::models::DbExecutor;
use actix_web::server;
use diesel::{r2d2::ConnectionManager, PgConnection};
use dotenv::dotenv;
use models::DbExecutor;
use std::env;
fn main() { fn main() -> std::io::Result<()> {
dotenv().ok(); dotenv().ok();
std::env::set_var("RUST_LOG", "simple-auth-server=debug,actix_web=info"); std::env::set_var(
std::env::set_var("RUST_BACKTRACE", "1"); "RUST_LOG",
"simple-auth-server=debug,actix_web=info,actix_server=info",
);
env_logger::init(); env_logger::init();
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let sys = actix::System::new("Actix_Tutorial"); let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
// create db connection pool // create db connection pool
let manager = ConnectionManager::<PgConnection>::new(database_url); let manager = ConnectionManager::<PgConnection>::new(database_url);
@ -57,10 +49,49 @@ fn main() {
let address: Addr<DbExecutor> = let address: Addr<DbExecutor> =
SyncArbiter::start(4, move || DbExecutor(pool.clone())); SyncArbiter::start(4, move || DbExecutor(pool.clone()));
server::new(move || app::create_app(address.clone())) HttpServer::new(move || {
.bind("127.0.0.1:3000") // secret is a random minimum 32 bytes long base 64 string
.expect("Can not bind to '127.0.0.1:3000'") let secret: String =
.start(); std::env::var("SECRET_KEY").unwrap_or_else(|_| "0123".repeat(8));
let domain: String =
std::env::var("DOMAIN").unwrap_or_else(|_| "localhost".to_string());
sys.run(); App::new()
.data(address.clone())
.wrap(Logger::default())
.wrap(IdentityService::new(
CookieIdentityPolicy::new(secret.as_bytes())
.name("auth")
.path("/")
.domain(domain.as_str())
.max_age(Duration::days(1))
.secure(false), // this can only be true if you have https
))
// everything under '/api/' route
.service(
web::scope("/api")
// routes for authentication
.service(
web::resource("/auth")
.route(web::post().to_async(auth_routes::login))
.route(web::delete().to(auth_routes::logout))
.route(web::get().to_async(auth_routes::get_me)),
)
// routes to invitation
.service(
web::resource("/invitation").route(
web::post().to_async(invitation_routes::register_email),
),
)
// routes to register as a user after the
.service(
web::resource("/register/{invitation_id}")
.route(web::post().to_async(register_routes::register_user)),
),
)
// serve static files
.service(fs::Files::new("/", "./static/").index_file("index.html"))
})
.bind("127.0.0.1:3000")?
.run()
} }

View File

@ -5,7 +5,7 @@ use diesel::r2d2::{ConnectionManager, Pool};
use std::convert::From; use std::convert::From;
use uuid::Uuid; use uuid::Uuid;
use schema::{invitations, users}; use crate::schema::{invitations, users};
/// This is db executor actor. can be run in parallel /// This is db executor actor. can be run in parallel
pub struct DbExecutor(pub Pool<ConnectionManager<PgConnection>>); pub struct DbExecutor(pub Pool<ConnectionManager<PgConnection>>);

View File

@ -1,11 +1,12 @@
use actix::{Handler, Message}; use actix::{Handler, Message};
use chrono::Local; use chrono::Local;
use diesel::prelude::*; use diesel::prelude::*;
use errors::ServiceError;
use models::{DbExecutor, Invitation, SlimUser, User};
use utils::hash_password;
use uuid::Uuid; use uuid::Uuid;
use crate::errors::ServiceError;
use crate::models::{DbExecutor, Invitation, SlimUser, User};
use crate::utils::hash_password;
// UserData is used to extract data from a post request by the client // UserData is used to extract data from a post request by the client
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct UserData { pub struct UserData {
@ -26,8 +27,8 @@ impl Message for RegisterUser {
impl Handler<RegisterUser> for DbExecutor { impl Handler<RegisterUser> for DbExecutor {
type Result = Result<SlimUser, ServiceError>; type Result = Result<SlimUser, ServiceError>;
fn handle(&mut self, msg: RegisterUser, _: &mut Self::Context) -> Self::Result { fn handle(&mut self, msg: RegisterUser, _: &mut Self::Context) -> Self::Result {
use schema::invitations::dsl::{id, invitations}; use crate::schema::invitations::dsl::{id, invitations};
use schema::users::dsl::users; use crate::schema::users::dsl::users;
let conn: &PgConnection = &self.0.get().unwrap(); let conn: &PgConnection = &self.0.get().unwrap();
// try parsing the string provided by the user as url parameter // try parsing the string provided by the user as url parameter

View File

@ -1,27 +1,25 @@
use actix_web::{ use actix::Addr;
AsyncResponder, FutureResponse, HttpResponse, Json, Path, ResponseError, State, use actix_web::{web, Error, HttpResponse, ResponseError};
}; use futures::Future;
use futures::future::Future;
use app::AppState; use crate::models::DbExecutor;
use register_handler::{RegisterUser, UserData}; use crate::register_handler::{RegisterUser, UserData};
pub fn register_user( pub fn register_user(
(invitation_id, user_data, state): (Path<String>, Json<UserData>, State<AppState>), invitation_id: web::Path<String>,
) -> FutureResponse<HttpResponse> { user_data: web::Json<UserData>,
db: web::Data<Addr<DbExecutor>>,
) -> impl Future<Item = HttpResponse, Error = Error> {
let msg = RegisterUser { let msg = RegisterUser {
// into_inner() returns the inner string value from Path // into_inner() returns the inner string value from Path
invitation_id: invitation_id.into_inner(), invitation_id: invitation_id.into_inner(),
password: user_data.password.clone(), password: user_data.password.clone(),
}; };
state db.send(msg)
.db
.send(msg)
.from_err() .from_err()
.and_then(|db_response| match db_response { .and_then(|db_response| match db_response {
Ok(slim_user) => Ok(HttpResponse::Ok().json(slim_user)), Ok(slim_user) => Ok(HttpResponse::Ok().json(slim_user)),
Err(service_error) => Ok(service_error.error_response()), Err(service_error) => Ok(service_error.error_response()),
}) })
.responder()
} }

View File

@ -1,14 +1,13 @@
use bcrypt::{hash, DEFAULT_COST}; use bcrypt::{hash, DEFAULT_COST};
use chrono::{Duration, Local}; use chrono::{Duration, Local};
use errors::ServiceError; use jsonwebtoken::{decode, encode, Header, Validation};
use jwt::{decode, encode, Header, Validation};
use models::SlimUser; use crate::errors::ServiceError;
use std::convert::From; use crate::models::SlimUser;
use std::env;
pub fn hash_password(plain: &str) -> Result<String, ServiceError> { pub fn hash_password(plain: &str) -> Result<String, ServiceError> {
// get the hashing cost from the env variable or use default // get the hashing cost from the env variable or use default
let hashing_cost: u32 = match env::var("HASH_ROUNDS") { let hashing_cost: u32 = match std::env::var("HASH_ROUNDS") {
Ok(cost) => cost.parse().unwrap_or(DEFAULT_COST), Ok(cost) => cost.parse().unwrap_or(DEFAULT_COST),
_ => DEFAULT_COST, _ => DEFAULT_COST,
}; };
@ -64,5 +63,5 @@ pub fn decode_token(token: &str) -> Result<SlimUser, ServiceError> {
} }
fn get_secret() -> String { fn get_secret() -> String {
env::var("JWT_SECRET").unwrap_or_else(|_| "my secret".into()) std::env::var("JWT_SECRET").unwrap_or_else(|_| "my secret".into())
} }

View File

@ -6,7 +6,6 @@ workspace = ".."
edition = "2018" edition = "2018"
[dependencies] [dependencies]
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
futures = "0.1.25"
futures = "0.1"
env_logger = "0.6" env_logger = "0.6"

View File

@ -9,5 +9,5 @@ edition = "2018"
futures = "0.1" futures = "0.1"
env_logger = "0.5" env_logger = "0.5"
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
actix-files = { git="https://github.com/actix/actix-web.git" } actix-files = "0.1.0-alpha.1"

View File

@ -6,9 +6,9 @@ workspace = ".."
edition = "2018" edition = "2018"
[dependencies] [dependencies]
actix-web = "1.0.0-alpha.1"
env_logger = "0.6" env_logger = "0.6"
askama = "0.6" askama = "0.6"
actix-web = { git="https://github.com/actix/actix-web.git" }
[build-dependencies] [build-dependencies]
askama = "0.6" askama = "0.6"

View File

@ -1,6 +1,3 @@
#[macro_use]
extern crate askama;
use std::collections::HashMap; use std::collections::HashMap;
use actix_web::{web, App, HttpResponse, HttpServer, Result}; use actix_web::{web, App, HttpResponse, HttpServer, Result};

View File

@ -7,5 +7,5 @@ edition = "2018"
[dependencies] [dependencies]
env_logger = "0.6" env_logger = "0.6"
tera = "*" tera = "0.11"
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"

View File

@ -4,14 +4,12 @@ version = "0.0.1"
authors = ["Rust-iendo Barcelona <riendocontributions@gmail.com>"] authors = ["Rust-iendo Barcelona <riendocontributions@gmail.com>"]
publish = false publish = false
edition = "2018" edition = "2018"
workspace = ".." workspace = ".."
[dependencies] [dependencies]
actix-web = "1.0.0-alpha.1"
env_logger = "0.6" env_logger = "0.6"
yarte = "0.1" yarte = "0.1"
actix-web = { git="https://github.com/actix/actix-web.git" }
[build-dependencies] [build-dependencies]
yarte = "0.1" yarte = "0.1"

View File

@ -10,8 +10,7 @@ name = "tls-server"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
env_logger = "0.5"
openssl = { version="0.10" }
actix-rt = "0.2" actix-rt = "0.2"
actix-web = { git="https://github.com/actix/actix-web.git", features=["ssl"] } actix-web = { version="1.0.0-alpha.1", features=["ssl"] }
env_logger = "0.6"
openssl = { version="0.10" }

View File

@ -3,16 +3,13 @@ name = "actix-web-cors"
version = "0.1.0" version = "0.1.0"
authors = ["krircc <krircc@aliyun.com>"] authors = ["krircc <krircc@aliyun.com>"]
workspace = "../../" workspace = "../../"
edition = "2018"
[dependencies] [dependencies]
actix-web = "1.0.0-alpha.1"
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
serde_json = "1.0" serde_json = "1.0"
http = "0.1"
actix = "0.7"
actix-web = "0.7"
dotenv = "0.10" dotenv = "0.10"
env_logger = "0.5" env_logger = "0.6"
futures = "0.1" futures = "0.1"

View File

@ -1,49 +1,29 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
extern crate actix;
extern crate actix_web;
extern crate env_logger;
extern crate futures;
extern crate serde;
extern crate serde_json;
use actix_web::{ use actix_web::{
http::{header, Method}, http::header, middleware::cors::Cors, middleware::Logger, web, App, HttpServer,
middleware,
middleware::cors::Cors,
server, App,
}; };
use std::env;
mod user; mod user;
use user::info;
fn main() { fn main() -> std::io::Result<()> {
env::set_var("RUST_LOG", "actix_web=info"); std::env::set_var("RUST_LOG", "actix_web=info");
env_logger::init(); env_logger::init();
let sys = actix::System::new("Actix-web-CORS"); HttpServer::new(move || {
server::new(move || {
App::new() App::new()
.middleware(middleware::Logger::default()) .wrap(
.configure(|app| { Cors::new()
Cors::for_app(app)
.allowed_origin("http://localhost:1234") .allowed_origin("http://localhost:1234")
.allowed_methods(vec!["GET", "POST"]) .allowed_methods(vec!["GET", "POST"])
.allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT]) .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
.allowed_header(header::CONTENT_TYPE) .allowed_header(header::CONTENT_TYPE)
.max_age(3600) .max_age(3600),
.resource("/user/info", |r| { )
r.method(Method::POST).with(info); .wrap(Logger::default())
}) .service(web::resource("/user/info").route(web::post().to(user::info)))
.register()
})
}) })
.bind("127.0.0.1:8000") .bind("127.0.0.1:8000")?
.unwrap() .run()
.shutdown_timeout(2)
.start();
let _ = sys.run();
} }

View File

@ -1,4 +1,4 @@
use actix_web::{Json, Result}; use actix_web::web;
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
pub struct Info { pub struct Info {
@ -8,12 +8,12 @@ pub struct Info {
confirm_password: String, confirm_password: String,
} }
pub fn info(info: Json<Info>) -> Result<Json<Info>> { pub fn info(info: web::Json<Info>) -> web::Json<Info> {
println!("=========={:?}=========", info); println!("=========={:?}=========", info);
Ok(Json(Info { web::Json(Info {
username: info.username.clone(), username: info.username.clone(),
email: info.email.clone(), email: info.email.clone(),
password: info.password.clone(), password: info.password.clone(),
confirm_password: info.confirm_password.clone(), confirm_password: info.confirm_password.clone(),
})) })
} }

View File

@ -14,10 +14,10 @@ path = "src/main.rs"
#path = "src/client.rs" #path = "src/client.rs"
[dependencies] [dependencies]
actix = { git="https://github.com/actix/actix.git" } actix = "0.8.0-alpha.1"
actix-web = { git="https://github.com/actix/actix-web.git" } actix-web = "1.0.0-alpha.1"
actix-web-actors = { git="https://github.com/actix/actix-web.git" } actix-web-actors = "1.0.0-alpha.1"
actix-files = { git="https://github.com/actix/actix-web.git" } actix-files = "0.1.0-alpha.1"
env_logger = "0.6" env_logger = "0.6"
futures = "0.1" futures = "0.1"
bytes = "0.4" bytes = "0.4"

View File

@ -1,16 +1,9 @@
//! Simple websocket client. //! Simple websocket client.
#![allow(unused_variables)]
extern crate actix;
extern crate actix_web;
extern crate env_logger;
extern crate futures;
use std::time::Duration; use std::time::Duration;
use std::{io, thread}; use std::{io, thread};
use actix::*; use actix::*;
use actix_web::ws::{Client, ClientWriter, Message, ProtocolError}; use actix_web::client::{Client, ClientWriter, Message, ProtocolError};
use futures::Future; use futures::Future;
fn main() { fn main() {