From 71e83fb87c75ebaa7d9ee52c19b2823db278eed6 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 5 Mar 2019 22:16:42 -0800 Subject: [PATCH 01/23] update basic example --- async_db/Cargo.toml | 2 +- basics/Cargo.toml | 11 ++-- basics/src/main.rs | 141 ++++++++++++++++++++++---------------------- 3 files changed, 79 insertions(+), 75 deletions(-) diff --git a/async_db/Cargo.toml b/async_db/Cargo.toml index 55105f57..56e97c2f 100644 --- a/async_db/Cargo.toml +++ b/async_db/Cargo.toml @@ -11,7 +11,7 @@ dotenv = "0.10" env_logger = "0.5" failure = "0.1.1" futures = "0.1" -num_cpus = "1.8.0" +num_cpus = "1.10.0" r2d2 = "0.8.2" r2d2_sqlite = "0.5.0" serde = "1.0" diff --git a/basics/Cargo.toml b/basics/Cargo.toml index 2db8e75a..b13337c7 100644 --- a/basics/Cargo.toml +++ b/basics/Cargo.toml @@ -1,13 +1,16 @@ [package] name = "basics" -version = "0.1.0" +version = "1.0.0" authors = ["Nikolay Kim "] workspace = "../" +edition = "2018" [dependencies] -actix = "0.7" -actix-web = "0.7" +actix-rt = "0.1" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-staticfiles = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -futures = "0.1" +futures = "0.1.25" env_logger = "0.5" bytes = "0.4" diff --git a/basics/src/main.rs b/basics/src/main.rs index b4fbe9e9..fded1c3a 100644 --- a/basics/src/main.rs +++ b/basics/src/main.rs @@ -1,43 +1,34 @@ -#![allow(unused_variables)] -#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] - -extern crate actix; -extern crate actix_web; -extern crate bytes; -extern crate env_logger; -extern crate futures; - -use bytes::Bytes; -use futures::sync::mpsc; -use futures::Stream; - -use actix_web::http::{header, Method, StatusCode}; -use actix_web::middleware::session::{self, RequestSession}; -use actix_web::{ - error, fs, middleware, pred, server, App, Error, HttpRequest, HttpResponse, Path, - Result, -}; -use futures::future::{result, FutureResult}; use std::{env, io}; +use actix_session::{CookieSession, Session}; +use actix_staticfiles as fs; +use actix_web::extract::Path; +use actix_web::http::{header, Method, StatusCode}; +use actix_web::{ + error, guard, web, App, Error, HttpRequest, HttpResponse, HttpServer, Result, +}; +use bytes::Bytes; +use futures::unsync::mpsc; +use futures::{future::ok, Future, Stream}; + /// favicon handler -fn favicon(req: &HttpRequest) -> Result { +fn favicon() -> Result { Ok(fs::NamedFile::open("static/favicon.ico")?) } /// simple index handler -fn welcome(req: &HttpRequest) -> Result { +fn welcome(session: Session, req: HttpRequest) -> Result { println!("{:?}", req); // session let mut counter = 1; - if let Some(count) = req.session().get::("counter")? { + if let Some(count) = session.get::("counter")? { println!("SESSION value: {}", count); counter = count + 1; } // set counter to session - req.session().set("counter", counter)?; + session.set("counter", counter)?; // response Ok(HttpResponse::build(StatusCode::OK) @@ -46,17 +37,17 @@ fn welcome(req: &HttpRequest) -> Result { } /// 404 handler -fn p404(req: &HttpRequest) -> Result { +fn p404() -> Result { Ok(fs::NamedFile::open("static/404.html")?.set_status_code(StatusCode::NOT_FOUND)) } /// async handler -fn index_async(req: &HttpRequest) -> FutureResult { +fn index_async(req: HttpRequest) -> impl Future { println!("{:?}", req); - result(Ok(HttpResponse::Ok().content_type("text/html").body( - format!("Hello {}!", req.match_info().get("name").unwrap()), - ))) + ok(HttpResponse::Ok() + .content_type("text/html") + .body(format!("Hello {}!", req.match_info().get("name").unwrap()))) } /// async body @@ -67,76 +58,86 @@ fn index_async_body(path: Path) -> HttpResponse { let _ = tx.unbounded_send(Bytes::from(text.as_bytes())); HttpResponse::Ok() - .streaming(rx_body.map_err(|e| error::ErrorBadRequest("bad request"))) + .streaming(rx_body.map_err(|_| error::ErrorBadRequest("bad request"))) } /// handler with path parameters like `/user/{name}/` -fn with_param(req: &HttpRequest) -> HttpResponse { +fn with_param(req: HttpRequest, path: Path<(String,)>) -> HttpResponse { println!("{:?}", req); HttpResponse::Ok() .content_type("text/plain") - .body(format!("Hello {}!", req.match_info().get("name").unwrap())) + .body(format!("Hello {}!", path.0)) } -fn main() { +fn main() -> io::Result<()> { env::set_var("RUST_LOG", "actix_web=debug"); env::set_var("RUST_BACKTRACE", "1"); env_logger::init(); - let sys = actix::System::new("basic-example"); + let sys = actix_rt::System::new("basic-example"); - let addr = server::new( - || App::new() + HttpServer::new(|| { + App::new() // enable logger - .middleware(middleware::Logger::default()) + // .middleware(middleware::Logger::default()) // cookie session middleware - .middleware(session::SessionStorage::new( - session::CookieSessionBackend::signed(&[0; 32]).secure(false) - )) + .middleware(CookieSession::signed(&[0; 32]).secure(false)) // register favicon - .resource("/favicon", |r| r.f(favicon)) + .resource("/favicon", |r| r.to(favicon)) // register simple route, handle all methods - .resource("/welcome", |r| r.f(welcome)) + .resource("/welcome", |r| r.to(welcome)) // with path parameters - .resource("/user/{name}", |r| r.method(Method::GET).f(with_param)) + .resource("/user/{name}", |r| r.route(web::get().to(with_param))) // async handler - .resource("/async/{name}", |r| r.method(Method::GET).a(index_async)) + .resource("/async/{name}", |r| { + r.route(web::get().to_async(index_async)) + }) // async handler - .resource("/async-body/{name}", |r| r.method(Method::GET).with(index_async_body)) - .resource("/test", |r| r.f(|req| { - match *req.method() { + .resource("/async-body/{name}", |r| { + r.route(web::get().to(index_async_body)) + }) + .resource("/test", |r| { + r.to(|req: HttpRequest| match *req.method() { Method::GET => HttpResponse::Ok(), Method::POST => HttpResponse::MethodNotAllowed(), _ => HttpResponse::NotFound(), - } - })) - .resource("/error", |r| r.f(|req| { - error::InternalError::new( - io::Error::new(io::ErrorKind::Other, "test"), StatusCode::INTERNAL_SERVER_ERROR) - })) + }) + }) + .resource("/error", |r| { + r.to(|| { + error::InternalError::new( + io::Error::new(io::ErrorKind::Other, "test"), + StatusCode::INTERNAL_SERVER_ERROR, + ) + }) + }) // static files - .handler("/static", fs::StaticFiles::new("static").unwrap()) + .service(fs::StaticFiles::new("/static", "static").unwrap()) // redirect - .resource("/", |r| r.method(Method::GET).f(|req| { - println!("{:?}", req); - HttpResponse::Found() - .header(header::LOCATION, "static/welcome.html") - .finish() - })) + .resource("/", |r| { + r.route(web::get().to(|req: HttpRequest| { + println!("{:?}", req); + HttpResponse::Found() + .header(header::LOCATION, "static/welcome.html") + .finish() + })) + }) // default .default_resource(|r| { // 404 for GET request - r.method(Method::GET).f(p404); - - // all requests that are not `GET` - r.route().filter(pred::Not(pred::Get())).f( - |req| HttpResponse::MethodNotAllowed()); - })) - - .bind("127.0.0.1:8080").expect("Can not bind to 127.0.0.1:8080") - .shutdown_timeout(0) // <- Set shutdown timeout to 0 seconds (default 60s) - .start(); + r.route(web::get().to(p404)) + // all requests that are not `GET` + .route( + web::route() + .guard(guard::Not(guard::Get())) + .to(|| HttpResponse::MethodNotAllowed()), + ) + }) + }) + .bind("127.0.0.1:8080")? + .start(); println!("Starting http server: 127.0.0.1:8080"); let _ = sys.run(); + Ok(()) } From 40b5498902aced8ba3babd55ec2dc5979fd4a64e Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 6 Mar 2019 09:27:56 -0800 Subject: [PATCH 02/23] enable files listing --- basics/Cargo.toml | 5 +++++ basics/src/main.rs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/basics/Cargo.toml b/basics/Cargo.toml index b13337c7..ddb7736e 100644 --- a/basics/Cargo.toml +++ b/basics/Cargo.toml @@ -7,10 +7,15 @@ edition = "2018" [dependencies] actix-rt = "0.1" + actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-staticfiles = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +#actix-web = { path="../../actix-web/" } +#actix-session = { path="../../actix-web/actix-session/" } +#actix-staticfiles = { path="../../actix-web/actix-staticfiles/" } + futures = "0.1.25" env_logger = "0.5" bytes = "0.4" diff --git a/basics/src/main.rs b/basics/src/main.rs index fded1c3a..0700d9d2 100644 --- a/basics/src/main.rs +++ b/basics/src/main.rs @@ -112,7 +112,7 @@ fn main() -> io::Result<()> { }) }) // static files - .service(fs::StaticFiles::new("/static", "static").unwrap()) + .service(fs::StaticFiles::new("/static", "static").show_files_listing()) // redirect .resource("/", |r| { r.route(web::get().to(|req: HttpRequest| { From 10731e43c6ffe5e9138009af27f35feb25922084 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 6 Mar 2019 10:04:41 -0800 Subject: [PATCH 03/23] convert r2d2 example --- basics/Cargo.toml | 1 - r2d2/Cargo.toml | 19 +++++----- r2d2/src/db.rs | 44 ----------------------- r2d2/src/main.rs | 90 +++++++++++++++++++++-------------------------- 4 files changed, 48 insertions(+), 106 deletions(-) delete mode 100644 r2d2/src/db.rs diff --git a/basics/Cargo.toml b/basics/Cargo.toml index ddb7736e..4e288328 100644 --- a/basics/Cargo.toml +++ b/basics/Cargo.toml @@ -7,7 +7,6 @@ edition = "2018" [dependencies] actix-rt = "0.1" - actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-staticfiles = { git="https://github.com/actix/actix-web.git", branch = "1.0" } diff --git a/r2d2/Cargo.toml b/r2d2/Cargo.toml index 884d84c4..b9f8de7c 100644 --- a/r2d2/Cargo.toml +++ b/r2d2/Cargo.toml @@ -2,20 +2,17 @@ name = "r2d2-example" version = "0.1.0" authors = ["Nikolay Kim "] +edition = "2018" workspace = "../" [dependencies] -env_logger = "0.5" - -actix = "0.7" -actix-web = "0.7" +actix-rt = "0.1" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } futures = "0.1" -uuid = { version = "0.5", features = ["serde", "v4"] } -serde = "1.0" -serde_json = "1.0" -serde_derive = "1.0" +env_logger = "0.6" +uuid = { version = "0.7", features = ["v4"] } -r2d2 = "*" -r2d2_sqlite = "*" -rusqlite = "*" +r2d2 = "0.8" +r2d2_sqlite = "0.8" +rusqlite = "0.16" diff --git a/r2d2/src/db.rs b/r2d2/src/db.rs deleted file mode 100644 index 5df9b3ff..00000000 --- a/r2d2/src/db.rs +++ /dev/null @@ -1,44 +0,0 @@ -//! Db executor actor -use actix::prelude::*; -use actix_web::*; -use r2d2::Pool; -use r2d2_sqlite::SqliteConnectionManager; -use std::io; -use uuid; - -/// This is db executor actor. We are going to run 3 of them in parallel. -pub struct DbExecutor(pub Pool); - -/// This is only message that this actor can handle, but it is easy to extend -/// number of messages. -pub struct CreateUser { - pub name: String, -} - -impl Message for CreateUser { - type Result = Result; -} - -impl Actor for DbExecutor { - type Context = SyncContext; -} - -impl Handler for DbExecutor { - type Result = Result; - - fn handle(&mut self, msg: CreateUser, _: &mut Self::Context) -> Self::Result { - let conn = self.0.get().unwrap(); - - let uuid = format!("{}", uuid::Uuid::new_v4()); - conn.execute( - "INSERT INTO users (id, name) VALUES ($1, $2)", - &[&uuid, &msg.name], - ).unwrap(); - - Ok(conn - .query_row("SELECT name FROM users WHERE id=$1", &[&uuid], |row| { - row.get(0) - }) - .map_err(|_| io::Error::new(io::ErrorKind::Other, "db error"))?) - } -} diff --git a/r2d2/src/main.rs b/r2d2/src/main.rs index e3cdb421..c594253f 100644 --- a/r2d2/src/main.rs +++ b/r2d2/src/main.rs @@ -1,68 +1,58 @@ //! Actix web r2d2 example -extern crate actix; -extern crate actix_web; -extern crate env_logger; -extern crate futures; -extern crate r2d2; -extern crate r2d2_sqlite; -extern crate rusqlite; -extern crate serde; -extern crate serde_json; -extern crate uuid; +use std::io; -use actix::prelude::*; use actix_web::{ - http, middleware, server, App, AsyncResponder, Error, HttpRequest, HttpResponse, + blocking, extract::Path, web, App, Error, HttpResponse, HttpServer, State, }; -use futures::future::Future; +use futures::Future; +use r2d2::Pool; use r2d2_sqlite::SqliteConnectionManager; +use uuid; -mod db; -use db::{CreateUser, DbExecutor}; +/// Async request handler. Ddb pool is stored in application state. +fn index( + path: Path, + db: State>, +) -> impl Future { + // execute sync code in threadpool + blocking::run(move || { + let conn = db.get().unwrap(); -/// State with DbExecutor address -struct State { - db: Addr, + let uuid = format!("{}", uuid::Uuid::new_v4()); + conn.execute( + "INSERT INTO users (id, name) VALUES ($1, $2)", + &[&uuid, &path.into_inner()], + ) + .unwrap(); + + conn.query_row("SELECT name FROM users WHERE id=$1", &[&uuid], |row| { + row.get::<_, String>(0) + }) + }) + .then(|res| match res { + Ok(user) => Ok(HttpResponse::Ok().json(user)), + Err(_) => Ok(HttpResponse::InternalServerError().into()), + }) } -/// Async request handler -fn index(req: &HttpRequest) -> Box> { - let name = &req.match_info()["name"]; - - req.state() - .db - .send(CreateUser { - name: name.to_owned(), - }) - .from_err() - .and_then(|res| match res { - Ok(user) => Ok(HttpResponse::Ok().json(user)), - Err(_) => Ok(HttpResponse::InternalServerError().into()), - }) - .responder() -} - -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=debug"); +fn main() -> io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=debug"); env_logger::init(); - let sys = actix::System::new("r2d2-example"); + let sys = actix_rt::System::new("r2d2-example"); // r2d2 pool let manager = SqliteConnectionManager::file("test.db"); let pool = r2d2::Pool::new(manager).unwrap(); - // Start db executor actors - let addr = SyncArbiter::start(3, move || DbExecutor(pool.clone())); - - // Start http server - server::new(move || { - App::with_state(State{db: addr.clone()}) - // enable logger - .middleware(middleware::Logger::default()) - .resource("/{name}", |r| r.method(http::Method::GET).a(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + // start http server + HttpServer::new(move || { + App::new() + .state(pool.clone()) // <- store db pool in app state + .resource("/{name}", |r| r.route(web::get().to_async(index))) + }) + .bind("127.0.0.1:8080")? + .start(); let _ = sys.run(); + Ok(()) } From 80615b8579aa95f3237ae112e40ae4b84bb9207b Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 6 Mar 2019 10:29:01 -0800 Subject: [PATCH 04/23] use new actix-rt --- basics/Cargo.toml | 2 +- basics/src/main.rs | 3 +-- r2d2/Cargo.toml | 2 +- r2d2/src/main.rs | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/basics/Cargo.toml b/basics/Cargo.toml index 4e288328..95c7608b 100644 --- a/basics/Cargo.toml +++ b/basics/Cargo.toml @@ -6,7 +6,7 @@ workspace = "../" edition = "2018" [dependencies] -actix-rt = "0.1" +actix-rt = "0.2" actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-staticfiles = { git="https://github.com/actix/actix-web.git", branch = "1.0" } diff --git a/basics/src/main.rs b/basics/src/main.rs index 0700d9d2..344ff49c 100644 --- a/basics/src/main.rs +++ b/basics/src/main.rs @@ -138,6 +138,5 @@ fn main() -> io::Result<()> { .start(); println!("Starting http server: 127.0.0.1:8080"); - let _ = sys.run(); - Ok(()) + sys.run() } diff --git a/r2d2/Cargo.toml b/r2d2/Cargo.toml index b9f8de7c..7046f298 100644 --- a/r2d2/Cargo.toml +++ b/r2d2/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" workspace = "../" [dependencies] -actix-rt = "0.1" +actix-rt = "0.2" actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } futures = "0.1" diff --git a/r2d2/src/main.rs b/r2d2/src/main.rs index c594253f..05d07849 100644 --- a/r2d2/src/main.rs +++ b/r2d2/src/main.rs @@ -53,6 +53,5 @@ fn main() -> io::Result<()> { .bind("127.0.0.1:8080")? .start(); - let _ = sys.run(); - Ok(()) + sys.run() } From 1edbb348d9f327dbbb2a208c89f50468372c07d5 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 6 Mar 2019 11:51:05 -0800 Subject: [PATCH 05/23] port async_db to actix-web 1.0 --- async_db/Cargo.toml | 6 ++- async_db/src/db.rs | 50 ++++++++----------- async_db/src/main.rs | 115 +++++++++++++++---------------------------- 3 files changed, 66 insertions(+), 105 deletions(-) diff --git a/async_db/Cargo.toml b/async_db/Cargo.toml index 56e97c2f..9dee0d2f 100644 --- a/async_db/Cargo.toml +++ b/async_db/Cargo.toml @@ -2,10 +2,12 @@ name = "async_db" version = "0.1.0" authors = ["Darin Gordon "] +edition = "2018" +workspace = ".." [dependencies] -actix = "0.7" -actix-web = "0.7" +actix-rt = "0.2" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } dotenv = "0.10" env_logger = "0.5" diff --git a/async_db/src/db.rs b/async_db/src/db.rs index a7903d71..9b700237 100644 --- a/async_db/src/db.rs +++ b/async_db/src/db.rs @@ -1,17 +1,14 @@ -use actix::prelude::*; +use actix_web::{blocking, Error as AWError}; use failure::Error; +use futures::Future; use r2d2; use r2d2_sqlite; +use serde_derive::{Deserialize, Serialize}; use std::{thread::sleep, time::Duration}; pub type Pool = r2d2::Pool; pub type Connection = r2d2::PooledConnection; -pub struct DbExecutor(pub Pool); -impl Actor for DbExecutor { - type Context = SyncContext; -} - #[derive(Debug, Serialize, Deserialize)] pub enum WeatherAgg { AnnualAgg { year: i32, total: f64 }, @@ -25,29 +22,24 @@ pub enum Queries { GetTopTenColdestMonths, } -//pub struct GetTopTenHottestYears; -impl Message for Queries { - type Result = Result, Error>; -} -impl Handler for DbExecutor { - type Result = Result, Error>; - - fn handle(&mut self, msg: Queries, _: &mut Self::Context) -> Self::Result { - let conn: Connection = self.0.get()?; - - match msg { - Queries::GetTopTenHottestYears => get_hottest_years(conn), - Queries::GetTopTenColdestYears => get_coldest_years(conn), - Queries::GetTopTenHottestMonths => get_hottest_months(conn), - Queries::GetTopTenColdestMonths => get_coldest_months(conn), - } - } +pub fn execute( + pool: &Pool, + query: Queries, +) -> impl Future, Error = AWError> { + let pool = pool.clone(); + blocking::run(move || match query { + Queries::GetTopTenHottestYears => get_hottest_years(pool.get()?), + Queries::GetTopTenColdestYears => get_coldest_years(pool.get()?), + Queries::GetTopTenHottestMonths => get_hottest_months(pool.get()?), + Queries::GetTopTenColdestMonths => get_coldest_months(pool.get()?), + }) + .from_err() } fn get_hottest_years(conn: Connection) -> Result, Error> { let stmt = " SELECT cast(strftime('%Y', date) as int) as theyear, - sum(tmax) as total + sum(tmax) as total FROM nyc_weather WHERE tmax <> 'TMAX' GROUP BY theyear @@ -73,7 +65,7 @@ fn get_hottest_years(conn: Connection) -> Result, Error> { fn get_coldest_years(conn: Connection) -> Result, Error> { let stmt = " SELECT cast(strftime('%Y', date) as int) as theyear, - sum(tmax) as total + sum(tmax) as total FROM nyc_weather WHERE tmax <> 'TMAX' GROUP BY theyear @@ -98,8 +90,8 @@ fn get_coldest_years(conn: Connection) -> Result, Error> { fn get_hottest_months(conn: Connection) -> Result, Error> { let stmt = "SELECT cast(strftime('%Y', date) as int) as theyear, - cast(strftime('%m', date) as int) as themonth, - sum(tmax) as total + cast(strftime('%m', date) as int) as themonth, + sum(tmax) as total FROM nyc_weather WHERE tmax <> 'TMAX' GROUP BY theyear, themonth @@ -124,8 +116,8 @@ fn get_hottest_months(conn: Connection) -> Result, Error> { fn get_coldest_months(conn: Connection) -> Result, Error> { let stmt = "SELECT cast(strftime('%Y', date) as int) as theyear, - cast(strftime('%m', date) as int) as themonth, - sum(tmax) as total + cast(strftime('%m', date) as int) as themonth, + sum(tmax) as total FROM nyc_weather WHERE tmax <> 'TMAX' GROUP BY theyear, themonth diff --git a/async_db/src/main.rs b/async_db/src/main.rs index 42dcb1bd..cd66d3f0 100644 --- a/async_db/src/main.rs +++ b/async_db/src/main.rs @@ -8,122 +8,89 @@ This project illustrates two examples: 2. An asynchronous handler that executes 4 queries in *parallel*, collecting the results and returning them as a single serialized json object -*/ + */ +use std::io; -extern crate actix; -extern crate actix_web; -extern crate env_logger; -extern crate failure; -extern crate futures; -extern crate num_cpus; -extern crate r2d2; -extern crate r2d2_sqlite; -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; - -use actix::prelude::*; -use actix_web::{ - http, middleware, server, App, AsyncResponder, Error as AWError, FutureResponse, - HttpResponse, State, -}; +use actix_web::{web, App, Error as AWError, HttpResponse, HttpServer, State}; use futures::future::{join_all, ok as fut_ok, Future}; +use r2d2_sqlite; use r2d2_sqlite::SqliteConnectionManager; mod db; -use db::{DbExecutor, Pool, Queries, WeatherAgg}; - -/// State with DbExecutor address -struct AppState { - db: Addr, -} +use db::{Pool, Queries, WeatherAgg}; /// Version 1: Calls 4 queries in sequential order, as an asynchronous handler -fn asyncio_weather(state: State) -> FutureResponse { +fn asyncio_weather( + db: State, +) -> impl Future { let mut result: Vec> = vec![]; - state - .db - .send(Queries::GetTopTenHottestYears) + db::execute(&db, Queries::GetTopTenHottestYears) .from_err() .and_then(move |res| { - result.push(res.unwrap()); - state - .db - .send(Queries::GetTopTenColdestYears) + result.push(res); + db::execute(&db, Queries::GetTopTenColdestYears) .from_err() .and_then(move |res| { - result.push(res.unwrap()); - state - .db - .send(Queries::GetTopTenHottestMonths) + result.push(res); + db::execute(&db, Queries::GetTopTenHottestMonths) .from_err() .and_then(move |res| { - result.push(res.unwrap()); - state - .db - .send(Queries::GetTopTenColdestMonths) + result.push(res); + db::execute(&db, Queries::GetTopTenColdestMonths) .from_err() .and_then(move |res| { - result.push(res.unwrap()); + result.push(res); fut_ok(result) }) }) }) }) .and_then(|res| Ok(HttpResponse::Ok().json(res))) - .responder() } /// Version 2: Calls 4 queries in parallel, as an asynchronous handler /// Returning Error types turn into None values in the response -fn parallel_weather(state: State) -> FutureResponse { +fn parallel_weather( + db: State, +) -> impl Future { let fut_result = vec![ - Box::new(state.db.send(Queries::GetTopTenHottestYears)), - Box::new(state.db.send(Queries::GetTopTenColdestYears)), - Box::new(state.db.send(Queries::GetTopTenHottestMonths)), - Box::new(state.db.send(Queries::GetTopTenColdestMonths)), + Box::new(db::execute(&db, Queries::GetTopTenHottestYears)), + Box::new(db::execute(&db, Queries::GetTopTenColdestYears)), + Box::new(db::execute(&db, Queries::GetTopTenHottestMonths)), + Box::new(db::execute(&db, Queries::GetTopTenColdestMonths)), ]; join_all(fut_result) .map_err(AWError::from) - .and_then(|result| { - let res: Vec>> = - result.into_iter().map(|x| x.ok()).collect(); - - Ok(HttpResponse::Ok().json(res)) - }) - .responder() + .map(|result| HttpResponse::Ok().json(result)) } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("parallel_db_example"); + let sys = actix_rt::System::new("parallel_db_example"); // Start N db executor actors (N = number of cores avail) - let manager = SqliteConnectionManager::file("weather.db"); let pool = Pool::new(manager).unwrap(); - let addr = SyncArbiter::start(num_cpus::get(), move || DbExecutor(pool.clone())); - // Start http server - server::new(move || { - App::with_state(AppState{db: addr.clone()}) + HttpServer::new(move || { + App::new() + .state(pool.clone()) // enable logger - .middleware(middleware::Logger::default()) - .resource("/asyncio_weather", |r| - r.method(http::Method::GET) - .with(asyncio_weather)) - .resource("/parallel_weather", |r| - r.method(http::Method::GET) - .with(parallel_weather)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + // .middleware(middleware::Logger::default()) + .resource("/asyncio_weather", |r| { + r.route(web::get().to_async(asyncio_weather)) + }) + .resource("/parallel_weather", |r| { + r.route(web::get().to_async(parallel_weather)) + }) + }) + .bind("127.0.0.1:8080")? + .start(); println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + sys.run() } From 51860a4f2ad2403d102d2bbbc8a2b185f0f73e3e Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 6 Mar 2019 15:51:56 -0800 Subject: [PATCH 06/23] update web api --- async_db/src/main.rs | 14 ++++++----- basics/src/main.rs | 55 +++++++++++++++++++++----------------------- r2d2/src/main.rs | 2 +- 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/async_db/src/main.rs b/async_db/src/main.rs index cd66d3f0..fc3d910d 100644 --- a/async_db/src/main.rs +++ b/async_db/src/main.rs @@ -81,12 +81,14 @@ fn main() -> io::Result<()> { .state(pool.clone()) // enable logger // .middleware(middleware::Logger::default()) - .resource("/asyncio_weather", |r| { - r.route(web::get().to_async(asyncio_weather)) - }) - .resource("/parallel_weather", |r| { - r.route(web::get().to_async(parallel_weather)) - }) + .service( + web::resource("/asyncio_weather") + .route(web::get().to_async(asyncio_weather)), + ) + .service( + web::resource("/parallel_weather") + .route(web::get().to_async(parallel_weather)), + ) }) .bind("127.0.0.1:8080")? .start(); diff --git a/basics/src/main.rs b/basics/src/main.rs index 344ff49c..ccd73b05 100644 --- a/basics/src/main.rs +++ b/basics/src/main.rs @@ -83,45 +83,42 @@ fn main() -> io::Result<()> { // cookie session middleware .middleware(CookieSession::signed(&[0; 32]).secure(false)) // register favicon - .resource("/favicon", |r| r.to(favicon)) + .service(web::resource("/favicon").to(favicon)) // register simple route, handle all methods - .resource("/welcome", |r| r.to(welcome)) + .service(web::resource("/welcome").to(welcome)) // with path parameters - .resource("/user/{name}", |r| r.route(web::get().to(with_param))) + .service(web::resource("/user/{name}").route(web::get().to(with_param))) // async handler - .resource("/async/{name}", |r| { - r.route(web::get().to_async(index_async)) - }) + .service( + web::resource("/async/{name}").route(web::get().to_async(index_async)), + ) // async handler - .resource("/async-body/{name}", |r| { - r.route(web::get().to(index_async_body)) - }) - .resource("/test", |r| { - r.to(|req: HttpRequest| match *req.method() { + .service( + web::resource("/async-body/{name}") + .route(web::get().to(index_async_body)), + ) + .service( + web::resource("/test").to(|req: HttpRequest| match *req.method() { Method::GET => HttpResponse::Ok(), Method::POST => HttpResponse::MethodNotAllowed(), _ => HttpResponse::NotFound(), - }) - }) - .resource("/error", |r| { - r.to(|| { - error::InternalError::new( - io::Error::new(io::ErrorKind::Other, "test"), - StatusCode::INTERNAL_SERVER_ERROR, - ) - }) - }) + }), + ) + .service(web::resource("/error").to(|| { + error::InternalError::new( + io::Error::new(io::ErrorKind::Other, "test"), + StatusCode::INTERNAL_SERVER_ERROR, + ) + })) // static files .service(fs::StaticFiles::new("/static", "static").show_files_listing()) // redirect - .resource("/", |r| { - r.route(web::get().to(|req: HttpRequest| { - println!("{:?}", req); - HttpResponse::Found() - .header(header::LOCATION, "static/welcome.html") - .finish() - })) - }) + .service(web::resource("/").route(web::get().to(|req: HttpRequest| { + println!("{:?}", req); + HttpResponse::Found() + .header(header::LOCATION, "static/welcome.html") + .finish() + }))) // default .default_resource(|r| { // 404 for GET request diff --git a/r2d2/src/main.rs b/r2d2/src/main.rs index 05d07849..abe564d1 100644 --- a/r2d2/src/main.rs +++ b/r2d2/src/main.rs @@ -48,7 +48,7 @@ fn main() -> io::Result<()> { HttpServer::new(move || { App::new() .state(pool.clone()) // <- store db pool in app state - .resource("/{name}", |r| r.route(web::get().to_async(index))) + .route("/{name}", web::get().to_async(index)) }) .bind("127.0.0.1:8080")? .start(); From c4df3356c7ea54211a817dbb2f195bc675435cd2 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 6 Mar 2019 19:45:45 -0800 Subject: [PATCH 07/23] enable logger --- async_db/src/main.rs | 7 ++++--- basics/Cargo.toml | 4 ---- basics/src/main.rs | 5 +++-- r2d2/src/main.rs | 4 +++- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/async_db/src/main.rs b/async_db/src/main.rs index fc3d910d..11027032 100644 --- a/async_db/src/main.rs +++ b/async_db/src/main.rs @@ -11,7 +11,9 @@ This project illustrates two examples: */ use std::io; -use actix_web::{web, App, Error as AWError, HttpResponse, HttpServer, State}; +use actix_web::{ + middleware, web, App, Error as AWError, HttpResponse, HttpServer, State, +}; use futures::future::{join_all, ok as fut_ok, Future}; use r2d2_sqlite; use r2d2_sqlite::SqliteConnectionManager; @@ -79,8 +81,7 @@ fn main() -> io::Result<()> { HttpServer::new(move || { App::new() .state(pool.clone()) - // enable logger - // .middleware(middleware::Logger::default()) + .middleware(middleware::Logger::default()) .service( web::resource("/asyncio_weather") .route(web::get().to_async(asyncio_weather)), diff --git a/basics/Cargo.toml b/basics/Cargo.toml index 95c7608b..518a4637 100644 --- a/basics/Cargo.toml +++ b/basics/Cargo.toml @@ -11,10 +11,6 @@ actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-staticfiles = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -#actix-web = { path="../../actix-web/" } -#actix-session = { path="../../actix-web/actix-session/" } -#actix-staticfiles = { path="../../actix-web/actix-staticfiles/" } - futures = "0.1.25" env_logger = "0.5" bytes = "0.4" diff --git a/basics/src/main.rs b/basics/src/main.rs index ccd73b05..d4f6eae0 100644 --- a/basics/src/main.rs +++ b/basics/src/main.rs @@ -5,7 +5,8 @@ use actix_staticfiles as fs; use actix_web::extract::Path; use actix_web::http::{header, Method, StatusCode}; use actix_web::{ - error, guard, web, App, Error, HttpRequest, HttpResponse, HttpServer, Result, + error, guard, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer, + Result, }; use bytes::Bytes; use futures::unsync::mpsc; @@ -79,7 +80,7 @@ fn main() -> io::Result<()> { HttpServer::new(|| { App::new() // enable logger - // .middleware(middleware::Logger::default()) + .middleware(middleware::Logger::default()) // cookie session middleware .middleware(CookieSession::signed(&[0; 32]).secure(false)) // register favicon diff --git a/r2d2/src/main.rs b/r2d2/src/main.rs index abe564d1..da83a8a6 100644 --- a/r2d2/src/main.rs +++ b/r2d2/src/main.rs @@ -2,7 +2,8 @@ use std::io; use actix_web::{ - blocking, extract::Path, web, App, Error, HttpResponse, HttpServer, State, + blocking, extract::Path, middleware, web, App, Error, HttpResponse, HttpServer, + State, }; use futures::Future; use r2d2::Pool; @@ -48,6 +49,7 @@ fn main() -> io::Result<()> { HttpServer::new(move || { App::new() .state(pool.clone()) // <- store db pool in app state + .middleware(middleware::Logger::default()) .route("/{name}", web::get().to_async(index)) }) .bind("127.0.0.1:8080")? From ab2fdbd6391cbbae55bee5ee384a1b84dc646427 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 6 Mar 2019 23:16:56 -0800 Subject: [PATCH 08/23] migrate tls example --- tls/Cargo.toml | 10 ++++--- tls/cert.pem | 43 +++++++++------------------ tls/key.pem | 79 ++++++++++++++++++------------------------------- tls/src/main.rs | 35 ++++++++++------------ 4 files changed, 63 insertions(+), 104 deletions(-) diff --git a/tls/Cargo.toml b/tls/Cargo.toml index dcae3d35..b18ff5a7 100644 --- a/tls/Cargo.toml +++ b/tls/Cargo.toml @@ -1,8 +1,9 @@ [package] name = "tls-example" -version = "0.1.0" +version = "0.2.0" authors = ["Nikolay Kim "] -workspace = "../" +edition = "2018" +workspace = ".." [[bin]] name = "tls-server" @@ -11,5 +12,6 @@ path = "src/main.rs" [dependencies] env_logger = "0.5" openssl = { version="0.10" } -actix = "0.7" -actix-web = { version = "0.7", features=["ssl"] } + +actix-rt = "0.2" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0", features=["ssl"] } diff --git a/tls/cert.pem b/tls/cert.pem index 159aacea..9a744d16 100644 --- a/tls/cert.pem +++ b/tls/cert.pem @@ -1,31 +1,16 @@ -----BEGIN CERTIFICATE----- -MIIFPjCCAyYCCQDvLYiYD+jqeTANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJV -UzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMRAwDgYDVQQKDAdDb21wYW55MQww -CgYDVQQLDANPcmcxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xODAxMjUx -NzQ2MDFaFw0xOTAxMjUxNzQ2MDFaMGExCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD -QTELMAkGA1UEBwwCU0YxEDAOBgNVBAoMB0NvbXBhbnkxDDAKBgNVBAsMA09yZzEY -MBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEA2WzIA2IpVR9Tb9EFhITlxuhE5rY2a3S6qzYNzQVgSFggxXEPn8k1 -sQEcer5BfAP986Sck3H0FvB4Bt/I8PwOtUCmhwcc8KtB5TcGPR4fjXnrpC+MIK5U -NLkwuyBDKziYzTdBj8kUFX1WxmvEHEgqToPOZfBgsS71cJAR/zOWraDLSRM54jXy -voLZN4Ti9rQagQrvTQ44Vz5ycDQy7UxtbUGh1CVv69vNVr7/SOOh/Nw5FNOZWLWr -odGyoec5wh9iqRZgRqiTUc6Lt7V2RWc2X2gjwST2UfI+U46Ip3oaQ7ZD4eAkoqND -xdniBZAykVG3c/99ux4BAESTF8fsNch6UticBxYMuTu+ouvP0psfI9wwwNliJDmA -CRUTB9AgRynbL1AzhqQoDfsb98IZfjfNOpwnwuLwpMAPhbgd5KNdZaIJ4Hb6/stI -yFElOExxd3TAxF2Gshd/lq1JcNHAZ1DSXV5MvOWT/NWgXwbIzUgQ8eIi+HuDYX2U -UuaB6R8tbd52H7rbUv6HrfinuSlKWqjSYLkiKHkwUpoMw8y9UycRSzs1E9nPwPTO -vRXb0mNCQeBCV9FvStNVXdCUTT8LGPv87xSD2pmt7LijlE6mHLG8McfcWkzA69un -CEHIFAFDimTuN7EBljc119xWFTcHMyoZAfFF+oTqwSbBGImruCxnaJECAwEAATAN -BgkqhkiG9w0BAQsFAAOCAgEApavsgsn7SpPHfhDSN5iZs1ILZQRewJg0Bty0xPfk -3tynSW6bNH3nSaKbpsdmxxomthNSQgD2heOq1By9YzeOoNR+7Pk3s4FkASnf3ToI -JNTUasBFFfaCG96s4Yvs8KiWS/k84yaWuU8c3Wb1jXs5Rv1qE1Uvuwat1DSGXSoD -JNluuIkCsC4kWkyq5pWCGQrabWPRTWsHwC3PTcwSRBaFgYLJaR72SloHB1ot02zL -d2age9dmFRFLLCBzP+D7RojBvL37qS/HR+rQ4SoQwiVc/JzaeqSe7ZbvEH9sZYEu -ALowJzgbwro7oZflwTWunSeSGDSltkqKjvWvZI61pwfHKDahUTmZ5h2y67FuGEaC -CIOUI8dSVSPKITxaq3JL4ze2e9/0Lt7hj19YK2uUmtMAW5Tirz4Yx5lyGH9U8Wur -y/X8VPxTc4A9TMlJgkyz0hqvhbPOT/zSWB10zXh0glKAsSBryAOEDxV1UygmSir7 -YV8Qaq+oyKUTMc1MFq5vZ07M51EPaietn85t8V2Y+k/8XYltRp32NxsypxAJuyxh -g/ko6RVTrWa1sMvz/F9LFqAdKiK5eM96lh9IU4xiLg4ob8aS/GRAA8oIFkZFhLrt -tOwjIUPmEPyHWFi8dLpNuQKYalLYhuwZftG/9xV+wqhKGZO9iPrpHSYBRTap8w2y -1QU= +MIICljCCAX4CCQDztMNlxk6oeTANBgkqhkiG9w0BAQsFADANMQswCQYDVQQIDAJj +YTAeFw0xOTAzMDcwNzEyNThaFw0yMDAzMDYwNzEyNThaMA0xCzAJBgNVBAgMAmNh +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0GMP3YzDVFWgNhRiHnfe +d192131Zi23p8WiutneD9I5WO42c79fOXsxLWn+2HSqPvCPHIBLoMX8o9lgCxt2P +/JUCAWbrE2EuvhkMrWk6/q7xB211XZYfnkqdt7mA0jMUC5o32AX3ew456TAq5P8Y +dq9H/qXdRtAvKD0QdkFfq8ePCiqOhcqacZ/NWva7R4HdgTnbL1DRQjGBXszI07P9 +1yw8GOym46uxNHRujQp3lYEhc1V3JTF9kETpSBHyEAkQ8WHxGf8UBHDhh7hcc+KI +JHMlVYy5wDv4ZJeYsY1rD6/n4tyd3r0yzBM57UGf6qrVZEYmLB7Jad+8Df5vIoGh +WwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQB1DEu9NiShCfQuA17MG5O0Jr2/PS1z +/+HW7oW15WXpqDKOEJalid31/Bzwvwq0bE12xKE4ZLdbqJHmJTdSUoGfOfBZKka6 +R2thOjqH7hFvxjfgS7kBy5BrRZewM9xKIJ6zU6+6mxR64x9vmkOmppV0fx5clZjH +c7qn5kSNWTMsFbjPnb5BeJJwZdqpMLs99jgoMvGtCUmkyVYODGhh65g6tR9kIPvM +zu/Cw122/y7tFfkuknMSYwGEYF3XcZpXt54a6Lu5hk6PuOTsK+7lC+HX7CSF1dpv +u1szL5fDgiCBFCnyKeOqF61mxTCUht3U++37VDFvhzN1t6HIVTYm2JJ7 -----END CERTIFICATE----- diff --git a/tls/key.pem b/tls/key.pem index aac387c6..4416facc 100644 --- a/tls/key.pem +++ b/tls/key.pem @@ -1,51 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKAIBAAKCAgEA2WzIA2IpVR9Tb9EFhITlxuhE5rY2a3S6qzYNzQVgSFggxXEP -n8k1sQEcer5BfAP986Sck3H0FvB4Bt/I8PwOtUCmhwcc8KtB5TcGPR4fjXnrpC+M -IK5UNLkwuyBDKziYzTdBj8kUFX1WxmvEHEgqToPOZfBgsS71cJAR/zOWraDLSRM5 -4jXyvoLZN4Ti9rQagQrvTQ44Vz5ycDQy7UxtbUGh1CVv69vNVr7/SOOh/Nw5FNOZ -WLWrodGyoec5wh9iqRZgRqiTUc6Lt7V2RWc2X2gjwST2UfI+U46Ip3oaQ7ZD4eAk -oqNDxdniBZAykVG3c/99ux4BAESTF8fsNch6UticBxYMuTu+ouvP0psfI9wwwNli -JDmACRUTB9AgRynbL1AzhqQoDfsb98IZfjfNOpwnwuLwpMAPhbgd5KNdZaIJ4Hb6 -/stIyFElOExxd3TAxF2Gshd/lq1JcNHAZ1DSXV5MvOWT/NWgXwbIzUgQ8eIi+HuD -YX2UUuaB6R8tbd52H7rbUv6HrfinuSlKWqjSYLkiKHkwUpoMw8y9UycRSzs1E9nP -wPTOvRXb0mNCQeBCV9FvStNVXdCUTT8LGPv87xSD2pmt7LijlE6mHLG8McfcWkzA -69unCEHIFAFDimTuN7EBljc119xWFTcHMyoZAfFF+oTqwSbBGImruCxnaJECAwEA -AQKCAgAME3aoeXNCPxMrSri7u4Xnnk71YXl0Tm9vwvjRQlMusXZggP8VKN/KjP0/ -9AE/GhmoxqPLrLCZ9ZE1EIjgmZ9Xgde9+C8rTtfCG2RFUL7/5J2p6NonlocmxoJm -YkxYwjP6ce86RTjQWL3RF3s09u0inz9/efJk5O7M6bOWMQ9VZXDlBiRY5BYvbqUR -6FeSzD4MnMbdyMRoVBeXE88gTvZk8xhB6DJnLzYgc0tKiRoeKT0iYv5JZw25VyRM -ycLzfTrFmXCPfB1ylb483d9Ly4fBlM8nkx37PzEnAuukIawDxsPOb9yZC+hfvNJI -7NFiMN+3maEqG2iC00w4Lep4skHY7eHUEUMl+Wjr+koAy2YGLWAwHZQTm7iXn9Ab -L6adL53zyCKelRuEQOzbeosJAqS+5fpMK0ekXyoFIuskj7bWuIoCX7K/kg6q5IW+ -vC2FrlsrbQ79GztWLVmHFO1I4J9M5r666YS0qdh8c+2yyRl4FmSiHfGxb3eOKpxQ -b6uI97iZlkxPF9LYUCSc7wq0V2gGz+6LnGvTHlHrOfVXqw/5pLAKhXqxvnroDTwz -0Ay/xFF6ei/NSxBY5t8ztGCBm45wCU3l8pW0X6dXqwUipw5b4MRy1VFRu6rqlmbL -OPSCuLxqyqsigiEYsBgS/icvXz9DWmCQMPd2XM9YhsHvUq+R4QKCAQEA98EuMMXI -6UKIt1kK2t/3OeJRyDd4iv/fCMUAnuPjLBvFE4cXD/SbqCxcQYqb+pue3PYkiTIC -71rN8OQAc5yKhzmmnCE5N26br/0pG4pwEjIr6mt8kZHmemOCNEzvhhT83nfKmV0g -9lNtuGEQMiwmZrpUOF51JOMC39bzcVjYX2Cmvb7cFbIq3lR0zwM+aZpQ4P8LHCIu -bgHmwbdlkLyIULJcQmHIbo6nPFB3ZZE4mqmjwY+rA6Fh9rgBa8OFCfTtrgeYXrNb -IgZQ5U8GoYRPNC2ot0vpTinraboa/cgm6oG4M7FW1POCJTl+/ktHEnKuO5oroSga -/BSg7hCNFVaOhwKCAQEA4Kkys0HtwEbV5mY/NnvUD5KwfXX7BxoXc9lZ6seVoLEc -KjgPYxqYRVrC7dB2YDwwp3qcRTi/uBAgFNm3iYlDzI4xS5SeaudUWjglj7BSgXE2 -iOEa7EwcvVPluLaTgiWjlzUKeUCNNHWSeQOt+paBOT+IgwRVemGVpAgkqQzNh/nP -tl3p9aNtgzEm1qVlPclY/XUCtf3bcOR+z1f1b4jBdn0leu5OhnxkC+Htik+2fTXD -jt6JGrMkanN25YzsjnD3Sn+v6SO26H99wnYx5oMSdmb8SlWRrKtfJHnihphjG/YY -l1cyorV6M/asSgXNQfGJm4OuJi0I4/FL2wLUHnU+JwKCAQEAzh4WipcRthYXXcoj -gMKRkMOb3GFh1OpYqJgVExtudNTJmZxq8GhFU51MR27Eo7LycMwKy2UjEfTOnplh -Us2qZiPtW7k8O8S2m6yXlYUQBeNdq9IuuYDTaYD94vsazscJNSAeGodjE+uGvb1q -1wLqE87yoE7dUInYa1cOA3+xy2/CaNuviBFJHtzOrSb6tqqenQEyQf6h9/12+DTW -t5pSIiixHrzxHiFqOoCLRKGToQB+71rSINwTf0nITNpGBWmSj5VcC3VV3TG5/XxI -fPlxV2yhD5WFDPVNGBGvwPDSh4jSMZdZMSNBZCy4XWFNSKjGEWoK4DFYed3DoSt9 -5IG1YwKCAQA63ntHl64KJUWlkwNbboU583FF3uWBjee5VqoGKHhf3CkKMxhtGqnt -+oN7t5VdUEhbinhqdx1dyPPvIsHCS3K1pkjqii4cyzNCVNYa2dQ00Qq+QWZBpwwc -3GAkz8rFXsGIPMDa1vxpU6mnBjzPniKMcsZ9tmQDppCEpBGfLpio2eAA5IkK8eEf -cIDB3CM0Vo94EvI76CJZabaE9IJ+0HIJb2+jz9BJ00yQBIqvJIYoNy9gP5Xjpi+T -qV/tdMkD5jwWjHD3AYHLWKUGkNwwkAYFeqT/gX6jpWBP+ZRPOp011X3KInJFSpKU -DT5GQ1Dux7EMTCwVGtXqjO8Ym5wjwwsfAoIBAEcxlhIW1G6BiNfnWbNPWBdh3v/K -5Ln98Rcrz8UIbWyl7qNPjYb13C1KmifVG1Rym9vWMO3KuG5atK3Mz2yLVRtmWAVc -fxzR57zz9MZFDun66xo+Z1wN3fVxQB4CYpOEI4Lb9ioX4v85hm3D6RpFukNtRQEc -Gfr4scTjJX4jFWDp0h6ffMb8mY+quvZoJ0TJqV9L9Yj6Ksdvqez/bdSraev97bHQ -4gbQxaTZ6WjaD4HjpPQefMdWp97Metg0ZQSS8b8EzmNFgyJ3XcjirzwliKTAQtn6 -I2sd0NCIooelrKRD8EJoDUwxoOctY7R97wpZ7/wEHU45cBCbRV3H4JILS5c= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQYw/djMNUVaA2 +FGIed953X3bXfVmLbenxaK62d4P0jlY7jZzv185ezEtaf7YdKo+8I8cgEugxfyj2 +WALG3Y/8lQIBZusTYS6+GQytaTr+rvEHbXVdlh+eSp23uYDSMxQLmjfYBfd7Djnp +MCrk/xh2r0f+pd1G0C8oPRB2QV+rx48KKo6Fyppxn81a9rtHgd2BOdsvUNFCMYFe +zMjTs/3XLDwY7Kbjq7E0dG6NCneVgSFzVXclMX2QROlIEfIQCRDxYfEZ/xQEcOGH +uFxz4ogkcyVVjLnAO/hkl5ixjWsPr+fi3J3evTLMEzntQZ/qqtVkRiYsHslp37wN +/m8igaFbAgMBAAECggEAJI278rkGany6pcHdlEqik34DcrliQ7r8FoSuYQOF+hgd +uESXCttoL+jWLwHICEW3AOGlxFKMuGH95Xh6xDeJUl0xBN3wzm11rZLnTmPvHU3C +qfLha5Ex6qpcECZSGo0rLv3WXeZuCv/r2KPCYnj86ZTFpD2kGw/Ztc1AXf4Jsi/1 +478Mf23QmAvCAPimGCyjLQx2c9/vg/6K7WnDevY4tDuDKLeSJxKZBSHUn3cM1Bwj +2QzaHfSFA5XljOF5PLeR3cY5ncrrVLWChT9XuGt9YMdLAcSQxgE6kWV1RSCq+lbj +e6OOe879IrrqwBvMQfKQqnm1kl8OrfPMT5CNWKvEgQKBgQD8q5E4x9taDS9RmhRO +07ptsr/I795tX8CaJd/jc4xGuCGBqpNw/hVebyNNYQvpiYzDNBSEhtd59957VyET +hcrGyxD0ByKm8F/lPgFw5y6wi3RUnucCV/jxkMHmxVzYMbFUEGCQ0pIU9/GFS7RZ +9VjqRDeE86U3yHO+WCFoHtd8aQKBgQDTIhi0uq0oY87bUGnWbrrkR0UVRNPDG1BT +cuXACYlv/DV/XpxPC8iPK1UwG4XaOVxodtIRjdBqvb8fUM6HSY6qll64N/4/1jre +Ho+d4clE4tK6a9WU96CKxwHn2BrWUZJPtoldaCZJFJ7SfiHuLlqW7TtYFrOfPIjN +ADiqK+bHIwKBgQCpfIiAVwebo0Z/bWR77+iZFxMwvT4tjdJLVGaXUvXgpjjLmtkm +LTm2S8SZbiSodfz3H+M3dp/pj8wsXiiwyMlZifOITZT/+DPLOUmMK3cVM6ZH8QMy +fkJd/+UhYHhECSlTI10zKByXdi4LZNnIkhwfoLzBMRI9lfeV0dYu2qlfKQKBgEVI +kRbtk1kHt5/ceX62g3nZsV/TYDJMSkW4FJC6EHHBL8UGRQDjewMQUzogLgJ4hEx7 +gV/lS5lbftZF7CAVEU4FXjvRlAtav6KYIMTMjQGf9UrbjBEAWZxwxb1Q+y2NQxgJ +bHZMcRPWQnAMmBHTAEM6whicCoGcmb+77Nxa37ZFAoGBALBuUNeD3fKvQR8v6GoA +spv+RYL9TB4wz2Oe9EYSp9z5EiWlTmuvFz3zk8pHDSpntxYH5O5HJ/3OzwhHz9ym ++DNE9AP9LW9hAzMuu7Gob1h8ShGwJVYwrQN3q/83ooUL7WSAuVOLpzJ7BFFlcCjp +MhFvd9iOt/R0N30/3AbQXkOp +-----END PRIVATE KEY----- diff --git a/tls/src/main.rs b/tls/src/main.rs index 329e15db..f8c8961c 100644 --- a/tls/src/main.rs +++ b/tls/src/main.rs @@ -1,26 +1,21 @@ -#![allow(unused_variables)] -extern crate actix; -extern crate actix_web; -extern crate env_logger; -extern crate openssl; +use std::io; -use actix_web::{http, middleware, server, App, Error, HttpRequest, HttpResponse}; +use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer}; use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; /// simple handle -fn index(req: &HttpRequest) -> Result { +fn index(req: HttpRequest) -> Result { println!("{:?}", req); Ok(HttpResponse::Ok() .content_type("text/plain") .body("Welcome!")) } -fn main() { - if ::std::env::var("RUST_LOG").is_err() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); - } +fn main() -> io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=debug"); env_logger::init(); - let sys = actix::System::new("ws-example"); + + let sys = actix_rt::System::new("tls-example"); // load ssl keys let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); @@ -29,22 +24,22 @@ fn main() { .unwrap(); builder.set_certificate_chain_file("cert.pem").unwrap(); - server::new(|| { + HttpServer::new(|| { App::new() // enable logger .middleware(middleware::Logger::default()) // register simple handler, handle all methods - .resource("/index.html", |r| r.f(index)) + .service(web::resource("/index.html").to(index)) // with path parameters - .resource("/", |r| r.method(http::Method::GET).f(|req| { + .service(web::resource("/").route(web::get().to(|| { HttpResponse::Found() .header("LOCATION", "/index.html") .finish() - })) - }).bind_ssl("127.0.0.1:8443", builder) - .unwrap() - .start(); + }))) + }) + .bind_ssl("127.0.0.1:8443", builder)? + .start(); println!("Started http server: 127.0.0.1:8443"); - let _ = sys.run(); + sys.run() } From 60a9df8abdffd5f4aa16b22c5ea9893c0634fa91 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 6 Mar 2019 23:44:46 -0800 Subject: [PATCH 09/23] rename to Files --- basics/Cargo.toml | 2 +- basics/src/main.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/basics/Cargo.toml b/basics/Cargo.toml index 518a4637..71a98837 100644 --- a/basics/Cargo.toml +++ b/basics/Cargo.toml @@ -8,8 +8,8 @@ edition = "2018" [dependencies] actix-rt = "0.2" actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-files = { git="https://github.com/actix/actix-web.git", branch = "1.0" } actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -actix-staticfiles = { git="https://github.com/actix/actix-web.git", branch = "1.0" } futures = "0.1.25" env_logger = "0.5" diff --git a/basics/src/main.rs b/basics/src/main.rs index d4f6eae0..8768718c 100644 --- a/basics/src/main.rs +++ b/basics/src/main.rs @@ -1,7 +1,7 @@ use std::{env, io}; +use actix_files as fs; use actix_session::{CookieSession, Session}; -use actix_staticfiles as fs; use actix_web::extract::Path; use actix_web::http::{header, Method, StatusCode}; use actix_web::{ @@ -112,7 +112,7 @@ fn main() -> io::Result<()> { ) })) // static files - .service(fs::StaticFiles::new("/static", "static").show_files_listing()) + .service(fs::Files::new("/static", "static").show_files_listing()) // redirect .service(web::resource("/").route(web::get().to(|req: HttpRequest| { println!("{:?}", req); From f39a53ea3a3bdd8c7e783a9789c043f8aa4d4d71 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 7 Mar 2019 14:50:29 -0800 Subject: [PATCH 10/23] upgrade diesel, r2d2, state examples --- async_db/src/main.rs | 8 +-- basics/src/main.rs | 14 ++-- diesel/Cargo.toml | 11 ++- diesel/src/db.rs | 55 -------------- diesel/src/main.rs | 166 ++++++++++++++++++++----------------------- json/Cargo.toml | 8 +-- json/src/main.rs | 135 +++++++++++++++-------------------- r2d2/src/main.rs | 11 ++- state/Cargo.toml | 10 +-- state/src/main.rs | 49 +++++-------- 10 files changed, 185 insertions(+), 282 deletions(-) delete mode 100644 diesel/src/db.rs diff --git a/async_db/src/main.rs b/async_db/src/main.rs index 11027032..e9583999 100644 --- a/async_db/src/main.rs +++ b/async_db/src/main.rs @@ -11,9 +11,7 @@ This project illustrates two examples: */ use std::io; -use actix_web::{ - middleware, web, App, Error as AWError, HttpResponse, HttpServer, State, -}; +use actix_web::{middleware, web, App, Error as AWError, HttpResponse, HttpServer}; use futures::future::{join_all, ok as fut_ok, Future}; use r2d2_sqlite; use r2d2_sqlite::SqliteConnectionManager; @@ -23,7 +21,7 @@ use db::{Pool, Queries, WeatherAgg}; /// Version 1: Calls 4 queries in sequential order, as an asynchronous handler fn asyncio_weather( - db: State, + db: web::State, ) -> impl Future { let mut result: Vec> = vec![]; @@ -54,7 +52,7 @@ fn asyncio_weather( /// Version 2: Calls 4 queries in parallel, as an asynchronous handler /// Returning Error types turn into None values in the response fn parallel_weather( - db: State, + db: web::State, ) -> impl Future { let fut_result = vec![ Box::new(db::execute(&db, Queries::GetTopTenHottestYears)), diff --git a/basics/src/main.rs b/basics/src/main.rs index 8768718c..55f25bb0 100644 --- a/basics/src/main.rs +++ b/basics/src/main.rs @@ -1,8 +1,10 @@ +#[macro_use] +extern crate actix_web; + use std::{env, io}; use actix_files as fs; use actix_session::{CookieSession, Session}; -use actix_web::extract::Path; use actix_web::http::{header, Method, StatusCode}; use actix_web::{ error, guard, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer, @@ -13,11 +15,13 @@ use futures::unsync::mpsc; use futures::{future::ok, Future, Stream}; /// favicon handler +#[get("/favicon")] fn favicon() -> Result { Ok(fs::NamedFile::open("static/favicon.ico")?) } /// simple index handler +#[get("/welcome")] fn welcome(session: Session, req: HttpRequest) -> Result { println!("{:?}", req); @@ -52,7 +56,7 @@ fn index_async(req: HttpRequest) -> impl Future) -> HttpResponse { +fn index_async_body(path: web::Path) -> HttpResponse { let text = format!("Hello {}!", *path); let (tx, rx_body) = mpsc::unbounded(); @@ -63,7 +67,7 @@ fn index_async_body(path: Path) -> HttpResponse { } /// handler with path parameters like `/user/{name}/` -fn with_param(req: HttpRequest, path: Path<(String,)>) -> HttpResponse { +fn with_param(req: HttpRequest, path: web::Path<(String,)>) -> HttpResponse { println!("{:?}", req); HttpResponse::Ok() @@ -84,9 +88,9 @@ fn main() -> io::Result<()> { // cookie session middleware .middleware(CookieSession::signed(&[0; 32]).secure(false)) // register favicon - .service(web::resource("/favicon").to(favicon)) + .service(favicon) // register simple route, handle all methods - .service(web::resource("/welcome").to(welcome)) + .service(welcome) // with path parameters .service(web::resource("/user/{name}").route(web::get().to(with_param))) // async handler diff --git a/diesel/Cargo.toml b/diesel/Cargo.toml index a2f309b8..af94c957 100644 --- a/diesel/Cargo.toml +++ b/diesel/Cargo.toml @@ -2,15 +2,14 @@ name = "diesel-example" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [dependencies] +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } + bytes = "0.4" -env_logger = "0.5" - -actix = "0.7" -actix-web = "0.7" - +env_logger = "0.6" futures = "0.1" uuid = { version = "0.5", features = ["serde", "v4"] } serde = "1.0" diff --git a/diesel/src/db.rs b/diesel/src/db.rs deleted file mode 100644 index de3dd179..00000000 --- a/diesel/src/db.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! Db executor actor -use actix::prelude::*; -use actix_web::*; -use diesel; -use diesel::prelude::*; -use diesel::r2d2::{ConnectionManager, Pool}; -use uuid; - -use models; -use schema; - -/// This is db executor actor. We are going to run 3 of them in parallel. -pub struct DbExecutor(pub Pool>); - -/// This is only message that this actor can handle, but it is easy to extend -/// number of messages. -pub struct CreateUser { - pub name: String, -} - -impl Message for CreateUser { - type Result = Result; -} - -impl Actor for DbExecutor { - type Context = SyncContext; -} - -impl Handler for DbExecutor { - type Result = Result; - - fn handle(&mut self, msg: CreateUser, _: &mut Self::Context) -> Self::Result { - use self::schema::users::dsl::*; - - let uuid = format!("{}", uuid::Uuid::new_v4()); - let new_user = models::NewUser { - id: &uuid, - name: &msg.name, - }; - - let conn: &SqliteConnection = &self.0.get().unwrap(); - - diesel::insert_into(users) - .values(&new_user) - .execute(conn) - .map_err(|_| error::ErrorInternalServerError("Error inserting person"))?; - - let mut items = users - .filter(id.eq(&uuid)) - .load::(conn) - .map_err(|_| error::ErrorInternalServerError("Error loading person"))?; - - Ok(items.pop().unwrap()) - } -} diff --git a/diesel/src/main.rs b/diesel/src/main.rs index d30519d6..8ff8ce68 100644 --- a/diesel/src/main.rs +++ b/diesel/src/main.rs @@ -4,77 +4,74 @@ //! Actix supports sync actors by default, so we going to create sync actor //! that use diesel. Technically sync actors are worker style actors, multiple //! of them can run in parallel and process messages from same queue. -extern crate serde; -extern crate serde_json; -#[macro_use] -extern crate serde_derive; #[macro_use] extern crate diesel; -extern crate actix; -extern crate actix_web; -extern crate env_logger; -extern crate futures; -extern crate r2d2; -extern crate uuid; -extern crate bytes; -// extern crate json; - - -use bytes::BytesMut; -use actix::prelude::*; -use actix_web::{ - http, middleware, server, App, AsyncResponder, FutureResponse, HttpResponse, Path, Error, HttpRequest, - State, HttpMessage, error, Json -}; +#[macro_use] +extern crate serde_derive; +use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer}; +use bytes::{Bytes, BytesMut}; use diesel::prelude::*; -use diesel::r2d2::ConnectionManager; -use futures::{future, Future, Stream}; +use diesel::r2d2::{self, ConnectionManager}; +use futures::future::{err, Either}; +use futures::{Future, Stream}; -mod db; mod models; mod schema; -use db::{CreateUser, DbExecutor}; +type Pool = r2d2::Pool>; -/// State with DbExecutor address -struct AppState { - db: Addr, +/// Diesel query +fn query( + nm: String, + pool: web::State, +) -> Result { + use self::schema::users::dsl::*; + + let uuid = format!("{}", uuid::Uuid::new_v4()); + let new_user = models::NewUser { + id: &uuid, + name: nm.as_str(), + }; + let conn: &SqliteConnection = &pool.get().unwrap(); + + diesel::insert_into(users).values(&new_user).execute(conn)?; + + let mut items = users.filter(id.eq(&uuid)).load::(conn)?; + Ok(items.pop().unwrap()) } /// Async request handler fn add( - (name, state): (Path, State), -) -> FutureResponse { - // send async `CreateUser` message to a `DbExecutor` - state - .db - .send(CreateUser { - name: name.into_inner(), - }) - .from_err() - .and_then(|res| match res { - Ok(user) => Ok(HttpResponse::Ok().json(user)), - Err(_) => Ok(HttpResponse::InternalServerError().into()), - }) - .responder() + name: web::Path, + pool: web::State, +) -> impl Future { + // run diesel blocking code + web::block(move || query(name.into_inner(), pool)).then(|res| match res { + Ok(user) => Ok(HttpResponse::Ok().json(user)), + Err(_) => Ok(HttpResponse::InternalServerError().into()), + }) } #[derive(Debug, Serialize, Deserialize)] struct MyUser { - name: String + name: String, } const MAX_SIZE: usize = 262_144; // max payload size is 256k /// This handler manually load request payload and parse json object -fn index_add((req, state): (HttpRequest, State)) -> impl Future { - // HttpRequest::payload() is stream of Bytes objects - req.payload() +fn index_add

( + pl: web::Payload

, + pool: web::State, +) -> impl Future +where + P: Stream, +{ + pl // `Future::from_err` acts like `?` in that it coerces the error type from // the future into the final error type .from_err() - // `fold` will asynchronously read each chunk of the request body and // call supplied closure, then it resolves to result of closure .fold(BytesMut::new(), move |mut body, chunk| { @@ -92,45 +89,39 @@ fn index_add((req, state): (HttpRequest, State)) -> impl Fut // Douman NOTE: // The return value in this closure helps, to clarify result for compiler // as otheriwse it cannot understand it - .and_then(move |body| -> Box> { + .and_then(move |body| { // body is loaded, now we can deserialize serde-json let r_obj = serde_json::from_slice::(&body); // Send to the db for create match r_obj { Ok(obj) => { - let res = state.db.send(CreateUser { name: obj.name, }) - .from_err() - .and_then(|res| match res { - Ok(user) => Ok(HttpResponse::Ok().json(user)), - Err(_) => Ok(HttpResponse::InternalServerError().into()), - }); - - Box::new(res) + Either::A(web::block(move || query(obj.name, pool)).then(|res| { + match res { + Ok(user) => Ok(HttpResponse::Ok().json(user)), + Err(_) => Ok(HttpResponse::InternalServerError().into()), + } + })) } - Err(_) => Box::new(future::err(error::ErrorBadRequest("Json Decode Failed"))) + Err(_) => Either::B(err(error::ErrorBadRequest("Json Decode Failed"))), } }) } -fn add2((item, state): (Json, State)) -> impl Future { - state.db - .send(CreateUser { - // into_inner to move into the reference, then accessing name to - // move the name out. - name: item.into_inner().name, - }) - .from_err() - .and_then(|res| match res { - Ok(user) => Ok(HttpResponse::Ok().json(user)), - Err(_) => Ok(HttpResponse::InternalServerError().into()), - }) +fn add2( + item: web::Json, + pool: web::State, +) -> impl Future { + // run diesel blocking code + web::block(move || query(item.into_inner().name, pool)).then(|res| match res { + Ok(user) => Ok(HttpResponse::Ok().json(user)), + Err(_) => Ok(HttpResponse::InternalServerError().into()), + }) } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("diesel-example"); // Start 3 db executor actors let manager = ConnectionManager::::new("test.db"); @@ -138,32 +129,29 @@ fn main() { .build(manager) .expect("Failed to create pool."); - let addr = SyncArbiter::start(3, move || DbExecutor(pool.clone())); - // Start http server - server::new(move || { - App::with_state(AppState{db: addr.clone()}) + HttpServer::new(move || { + App::new() + .state(pool.clone()) // enable logger .middleware(middleware::Logger::default()) // This can be called with: // curl -S --header "Content-Type: application/json" --request POST --data '{"name":"xyz"}' http://127.0.0.1:8080/add // Use of the extractors makes some post conditions simpler such // as size limit protections and built in json validation. - .resource("/add2", |r| { - r.method(http::Method::POST) - .with_async_config(add2, |(json_cfg, )| { - json_cfg.0.limit(4096); // <- limit size of the payload - }) - }) + .service( + web::resource("/add2").route( + web::post() + .config(web::JsonConfig::default().limit(4096)) // <- limit size of the payload + .to_async(add2), + ), + ) // Manual parsing would allow custom error construction, use of // other parsers *beside* json (for example CBOR, protobuf, xml), and allows // an application to standardise on a single parser implementation. - .resource("/add", |r| r.method(http::Method::POST).with_async(index_add)) - .resource("/add/{name}", |r| r.method(http::Method::GET).with(add)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .service(web::resource("/add").route(web::post().to_async(index_add))) + .service(web::resource("/add/{name}").route(web::get().to_async(add))) + }) + .bind("127.0.0.1:8080")? + .run() } diff --git a/json/Cargo.toml b/json/Cargo.toml index c358f4ae..ff724d24 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -2,9 +2,12 @@ name = "json-example" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [dependencies] +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } + bytes = "0.4" futures = "0.1" env_logger = "*" @@ -13,6 +16,3 @@ serde = "1.0" serde_json = "1.0" serde_derive = "1.0" json = "*" - -actix = "0.7" -actix-web = "^0.7" diff --git a/json/src/main.rs b/json/src/main.rs index a93f761e..6c9d7a5c 100644 --- a/json/src/main.rs +++ b/json/src/main.rs @@ -1,22 +1,13 @@ -extern crate actix; -extern crate actix_web; -extern crate bytes; -extern crate env_logger; -extern crate futures; -extern crate serde_json; -#[macro_use] -extern crate serde_derive; #[macro_use] extern crate json; use actix_web::{ - error, http, middleware, server, App, AsyncResponder, Error, HttpMessage, - HttpRequest, HttpResponse, Json, + error, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer, }; - -use bytes::BytesMut; +use bytes::{Bytes, BytesMut}; use futures::{Future, Stream}; use json::JsonValue; +use serde_derive::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] struct MyObj { @@ -24,39 +15,34 @@ struct MyObj { number: i32, } -/// This handler uses `HttpRequest::json()` for loading json object. -fn index(req: &HttpRequest) -> Box> { - req.json() - .from_err() // convert all errors into `Error` - .and_then(|val: MyObj| { - println!("model: {:?}", val); - Ok(HttpResponse::Ok().json(val)) // <- send response - }) - .responder() -} - /// This handler uses json extractor -fn extract_item(item: Json) -> HttpResponse { +fn index(item: web::Json) -> HttpResponse { println!("model: {:?}", &item); HttpResponse::Ok().json(item.0) // <- send response } /// This handler uses json extractor with limit -fn extract_item_limit((item, _req): (Json, HttpRequest)) -> HttpResponse { - println!("model: {:?}", &item); - HttpResponse::Ok().json(item.0) // <- send response +fn extract_item(item: web::Json, req: HttpRequest) -> HttpResponse { + println!("request: {:?}", req); + println!("model: {:?}", item); + + HttpResponse::Ok().json(item.0) // <- send json response } const MAX_SIZE: usize = 262_144; // max payload size is 256k /// This handler manually load request payload and parse json object -fn index_manual(req: &HttpRequest) -> Box> { - // HttpRequest::payload() is stream of Bytes objects - req.payload() +fn index_manual

( + payload: web::Payload

, +) -> impl Future +where + P: Stream, +{ + // payload is a stream of Bytes objects + payload // `Future::from_err` acts like `?` in that it coerces the error type from // the future into the final error type .from_err() - // `fold` will asynchronously read each chunk of the request body and // call supplied closure, then it resolves to result of closure .fold(BytesMut::new(), move |mut body, chunk| { @@ -75,59 +61,56 @@ fn index_manual(req: &HttpRequest) -> Box(&body)?; Ok(HttpResponse::Ok().json(obj)) // <- send response }) - .responder() } /// This handler manually load request payload and parse json-rust -fn index_mjsonrust( - req: &HttpRequest, -) -> Box> { - req.payload() - .concat2() - .from_err() - .and_then(|body| { - // body is loaded, now we can deserialize json-rust - let result = json::parse(std::str::from_utf8(&body).unwrap()); // return Result - let injson: JsonValue = match result { - Ok(v) => v, - Err(e) => object!{"err" => e.to_string() }, - }; - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(injson.dump())) - }) - .responder() +fn index_mjsonrust

( + pl: web::Payload

, +) -> impl Future +where + P: Stream, +{ + pl.concat2().from_err().and_then(|body| { + // body is loaded, now we can deserialize json-rust + let result = json::parse(std::str::from_utf8(&body).unwrap()); // return Result + let injson: JsonValue = match result { + Ok(v) => v, + Err(e) => json::object! {"err" => e.to_string() }, + }; + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(injson.dump())) + }) } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("json-example"); - server::new(|| { + HttpServer::new(|| { App::new() // enable logger .middleware(middleware::Logger::default()) - .resource("/extractor", |r| { - r.method(http::Method::POST) - .with_config(extract_item, |(cfg,)| { - cfg.limit(4096); // <- limit size of the payload - }) - }) - .resource("/extractor2", |r| { - r.method(http::Method::POST) - .with_config(extract_item_limit, |((cfg, _),)| { - cfg.limit(4096); // <- limit size of the payload - }) - }) - .resource("/manual", |r| r.method(http::Method::POST).f(index_manual)) - .resource("/mjsonrust", |r| r.method(http::Method::POST).f(index_mjsonrust)) - .resource("/", |r| r.method(http::Method::POST).f(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .shutdown_timeout(1) - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .service( + web::resource("/extractor").route( + web::post() + .config(web::JsonConfig::default().limit(4096)) // <- limit size of the payload + .to(index), + ), + ) + .service( + web::resource("/extractor2").route( + web::post() + .config(web::JsonConfig::default().limit(4096)) // <- limit size of the payload + .to_async(extract_item), + ), + ) + .service(web::resource("/manual").route(web::post().to_async(index_manual))) + .service( + web::resource("/mjsonrust").route(web::post().to_async(index_mjsonrust)), + ) + .service(web::resource("/").route(web::post().to(index))) + }) + .bind("127.0.0.1:8080")? + .run() } diff --git a/r2d2/src/main.rs b/r2d2/src/main.rs index da83a8a6..9b1060d2 100644 --- a/r2d2/src/main.rs +++ b/r2d2/src/main.rs @@ -1,10 +1,7 @@ //! Actix web r2d2 example use std::io; -use actix_web::{ - blocking, extract::Path, middleware, web, App, Error, HttpResponse, HttpServer, - State, -}; +use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer}; use futures::Future; use r2d2::Pool; use r2d2_sqlite::SqliteConnectionManager; @@ -12,11 +9,11 @@ use uuid; /// Async request handler. Ddb pool is stored in application state. fn index( - path: Path, - db: State>, + path: web::Path, + db: web::State>, ) -> impl Future { // execute sync code in threadpool - blocking::run(move || { + web::block(move || { let conn = db.get().unwrap(); let uuid = format!("{}", uuid::Uuid::new_v4()); diff --git a/state/Cargo.toml b/state/Cargo.toml index edf0e382..7d8e0a02 100644 --- a/state/Cargo.toml +++ b/state/Cargo.toml @@ -2,11 +2,11 @@ name = "state" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [dependencies] -futures = "0.1" -env_logger = "0.5" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -actix = "0.7" -actix-web = "0.7" +futures = "0.1" +env_logger = "0.6" diff --git a/state/src/main.rs b/state/src/main.rs index be1bd465..f67e9290 100644 --- a/state/src/main.rs +++ b/state/src/main.rs @@ -1,7 +1,7 @@ #![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] -//! There are two level of statefulness in actix-web. Application has state -//! that is shared across all handlers within same Application. -//! And individual handler can have state. +//! Application may have multiple states that are shared across +//! all handlers within same Application. State could be added +//! with `App::state()` method, multiple different states could be added. //! //! > **Note**: http server accepts an application factory rather than an //! application > instance. Http server constructs an application instance for @@ -11,45 +11,34 @@ //! //! Check [user guide](https://actix.rs/book/actix-web/sec-2-application.html) for more info. -extern crate actix; -extern crate actix_web; -extern crate env_logger; +use std::io; +use std::sync::{Arc, Mutex}; -use std::sync::Arc; -use std::sync::Mutex; - -use actix_web::{middleware, server, App, HttpRequest, HttpResponse}; - -/// Application state -struct AppState { - counter: Arc>, -} +use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer}; /// simple handle -fn index(req: &HttpRequest) -> HttpResponse { +fn index(state: web::State>>, req: HttpRequest) -> HttpResponse { println!("{:?}", req); - *(req.state().counter.lock().unwrap()) += 1; + *(state.lock().unwrap()) += 1; - HttpResponse::Ok().body(format!("Num of requests: {}", req.state().counter.lock().unwrap())) + HttpResponse::Ok().body(format!("Num of requests: {}", state.lock().unwrap())) } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("ws-example"); let counter = Arc::new(Mutex::new(0)); + //move is necessary to give closure below ownership of counter - server::new(move || { - App::with_state(AppState{counter: counter.clone()}) // <- create app with shared state + HttpServer::new(move || { + App::new() + .state(counter.clone()) // <- create app with shared state // enable logger .middleware(middleware::Logger::default()) // register simple handler, handle all methods - .resource("/", |r| r.f(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .service(web::resource("/").to(index)) + }) + .bind("127.0.0.1:8080")? + .run() } From e2945b9b3949532d0002660cd6d25fdf0bcb4362 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 9 Mar 2019 18:03:09 -0800 Subject: [PATCH 11/23] update more examples and rustfmt --- Cargo.toml | 1 - actix_redis/src/main.rs | 81 +++--- actix_todo/src/api.rs | 6 +- actix_todo/src/model.rs | 3 +- async_ex1/Cargo.toml | 7 +- async_ex1/src/main.rs | 117 ++++---- cookie-auth-full/Cargo.toml | 14 - cookie-auth-full/src/auth.rs | 274 ------------------- cookie-auth-full/src/main.rs | 49 ---- cookie-auth/Cargo.toml | 3 +- cookie-auth/src/main.rs | 9 +- cookie-session/Cargo.toml | 9 +- cookie-session/src/main.rs | 42 +-- error_handling/Cargo.toml | 10 +- error_handling/src/main.rs | 145 ++++------ form/src/main.rs | 34 +-- hello-world/src/main.rs | 7 +- http-full-proxy/src/main.rs | 18 +- http-proxy/src/main.rs | 42 +-- http-proxy/src/server.rs | 11 +- juniper/src/main.rs | 19 +- middleware/src/main.rs | 11 +- multipart/src/main.rs | 18 +- protobuf/src/main.rs | 13 +- redis-session/src/main.rs | 14 +- rustls/src/main.rs | 17 +- simple-auth-server/src/app.rs | 6 +- simple-auth-server/src/auth_handler.rs | 22 +- simple-auth-server/src/auth_routes.rs | 12 +- simple-auth-server/src/email_service.rs | 21 +- simple-auth-server/src/errors.rs | 19 +- simple-auth-server/src/invitation_handler.rs | 2 - simple-auth-server/src/invitation_routes.rs | 7 +- simple-auth-server/src/main.rs | 24 +- simple-auth-server/src/models.rs | 10 +- simple-auth-server/src/register_handler.rs | 17 +- simple-auth-server/src/register_routes.rs | 17 +- simple-auth-server/src/schema.rs | 5 +- static_index/src/main.rs | 17 +- template_askama/src/main.rs | 12 +- template_tera/src/main.rs | 9 +- unix-socket/src/main.rs | 3 +- web-cors/backend/src/main.rs | 9 +- websocket-chat-broker/src/main.rs | 9 +- websocket-chat/src/main.rs | 33 +-- websocket-tcp-chat/src/codec.rs | 8 +- websocket-tcp-chat/src/main.rs | 27 +- websocket/src/main.rs | 23 +- 48 files changed, 485 insertions(+), 801 deletions(-) delete mode 100644 cookie-auth-full/Cargo.toml delete mode 100644 cookie-auth-full/src/auth.rs delete mode 100644 cookie-auth-full/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index ae0b605e..5c287311 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ members = [ "async_ex1", "basics", "cookie-auth", - "cookie-auth-full", "cookie-session", "diesel", "error_handling", diff --git a/actix_redis/src/main.rs b/actix_redis/src/main.rs index d9ccfa8e..e8072a21 100644 --- a/actix_redis/src/main.rs +++ b/actix_redis/src/main.rs @@ -3,30 +3,32 @@ extern crate actix_redis; extern crate actix_web; extern crate env_logger; extern crate futures; -#[macro_use] extern crate redis_async; +#[macro_use] +extern crate redis_async; extern crate serde; -#[macro_use] extern crate serde_derive; +#[macro_use] +extern crate serde_derive; - -use std::sync::Arc; use actix::prelude::*; -use actix_redis::{Command, RedisActor, Error as ARError}; -use actix_web::{middleware, server, App, HttpRequest, HttpResponse, Json, - AsyncResponder, http::Method, Error as AWError}; -use futures::future::{Future, join_all}; +use actix_redis::{Command, Error as ARError, RedisActor}; +use actix_web::{ + http::Method, middleware, server, App, AsyncResponder, Error as AWError, + HttpRequest, HttpResponse, Json, +}; +use futures::future::{join_all, Future}; use redis_async::resp::RespValue; - +use std::sync::Arc; #[derive(Deserialize)] pub struct CacheInfo { one: String, two: String, - three: String + three: String, } - -fn cache_stuff((info, req): (Json, HttpRequest)) - -> impl Future { +fn cache_stuff( + (info, req): (Json, HttpRequest), +) -> impl Future { let info = info.into_inner(); let redis = req.state().redis_addr.clone(); @@ -59,25 +61,33 @@ fn cache_stuff((info, req): (Json, HttpRequest)) .responder() } -fn del_stuff(req: HttpRequest) - -> impl Future { +fn del_stuff( + req: HttpRequest, +) -> impl Future { let redis = req.state().redis_addr.clone(); - redis.send(Command(resp_array!["DEL", "mydomain:one", "mydomain:two", "mydomain:three"])) - .map_err(AWError::from) - .and_then(|res: Result| - match &res { - Ok(RespValue::Integer(x)) if x==&3 => - Ok(HttpResponse::Ok().body("successfully deleted values")), - _ =>{println!("---->{:?}", res); - Ok(HttpResponse::InternalServerError().finish())} - }) + redis + .send(Command(resp_array![ + "DEL", + "mydomain:one", + "mydomain:two", + "mydomain:three" + ])) + .map_err(AWError::from) + .and_then(|res: Result| match &res { + Ok(RespValue::Integer(x)) if x == &3 => { + Ok(HttpResponse::Ok().body("successfully deleted values")) + } + _ => { + println!("---->{:?}", res); + Ok(HttpResponse::InternalServerError().finish()) + } + }) .responder() - } pub struct AppState { - pub redis_addr: Arc> + pub redis_addr: Arc>, } fn main() { @@ -87,20 +97,19 @@ fn main() { server::new(|| { let redis_addr = Arc::new(RedisActor::start("127.0.0.1:6379")); - let app_state = AppState{redis_addr}; + let app_state = AppState { redis_addr }; App::with_state(app_state) .middleware(middleware::Logger::default()) .resource("/stuff", |r| { - r.method(Method::POST) - .with_async(cache_stuff); - r.method(Method::DELETE) - .with_async(del_stuff)}) - - }).bind("0.0.0.0:8080") - .unwrap() - .workers(1) - .start(); + r.method(Method::POST).with_async(cache_stuff); + r.method(Method::DELETE).with_async(del_stuff) + }) + }) + .bind("0.0.0.0:8080") + .unwrap() + .workers(1) + .start(); let _ = sys.run(); } diff --git a/actix_todo/src/api.rs b/actix_todo/src/api.rs index fcb67a0c..73c58e30 100644 --- a/actix_todo/src/api.rs +++ b/actix_todo/src/api.rs @@ -32,7 +32,8 @@ pub fn index(req: HttpRequest) -> FutureResponse { session::clear_flash(&req); } - let rendered = req.state() + let rendered = req + .state() .template .render("index.html.tera", &context) .map_err(|e| { @@ -61,7 +62,8 @@ pub fn create( FlashMessage::error("Description cannot be empty"), )?; Ok(redirect_to("/")) - }).responder() + }) + .responder() } else { req.state() .db diff --git a/actix_todo/src/model.rs b/actix_todo/src/model.rs index 3f1afb13..60eb551c 100644 --- a/actix_todo/src/model.rs +++ b/actix_todo/src/model.rs @@ -3,7 +3,8 @@ use diesel::pg::PgConnection; use diesel::prelude::*; use schema::{ - tasks, tasks::dsl::{completed as task_completed, tasks as all_tasks}, + tasks, + tasks::dsl::{completed as task_completed, tasks as all_tasks}, }; #[derive(Debug, Insertable)] diff --git a/async_ex1/Cargo.toml b/async_ex1/Cargo.toml index 1c30e0f9..69985d71 100644 --- a/async_ex1/Cargo.toml +++ b/async_ex1/Cargo.toml @@ -2,10 +2,13 @@ name = "awc_examples" version = "0.1.0" authors = ["dowwie "] +edition = "2018" +workspace = ".." [dependencies] -actix = "0.7" -actix-web = { version="0.7.3", features=["rust-tls"] } +actix-rt = "0.2" +actix-http = { git="https://github.com/actix/actix-http.git", features=["ssl"] } +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0", features=["ssl"] } futures = "0.1" serde = "1.0.43" diff --git a/async_ex1/src/main.rs b/async_ex1/src/main.rs index a3d5a028..4e8c94dd 100644 --- a/async_ex1/src/main.rs +++ b/async_ex1/src/main.rs @@ -15,25 +15,17 @@ // There are 2 versions in this example, one that uses Boxed Futures and the // other that uses Impl Future, available since rustc v1.26. -extern crate actix; -extern crate actix_web; -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; #[macro_use] extern crate validator_derive; -extern crate env_logger; -extern crate futures; -extern crate validator; +#[macro_use] +extern crate serde_derive; -use actix_web::{ - client, http::Method, server, App, AsyncResponder, Error, HttpMessage, HttpResponse, - Json, -}; -use futures::{future::ok as fut_ok, Future}; use std::collections::HashMap; -use std::time::Duration; +use std::io; + +use actix_http::client; +use actix_web::{web, App, Error, HttpMessage, HttpResponse, HttpServer}; +use futures::future::{ok, Future}; use validator::Validate; #[derive(Debug, Validate, Deserialize, Serialize)] @@ -62,38 +54,39 @@ struct HttpBinResponse { /// post json to httpbin, get it back in the response body, return deserialized fn step_x_v1(data: SomeData) -> Box> { + let mut connector = client::Connector::default().service(); + Box::new( client::ClientRequest::post("https://httpbin.org/post") - .json(data).unwrap() - .send() - .conn_timeout(Duration::from_secs(10)) - .map_err(Error::from) // <- convert SendRequestError to an Error - .and_then( - |resp| resp.body() // <- this is MessageBody type, resolves to complete body - .from_err() // <- convert PayloadError to an Error + .json(data) + .unwrap() + .send(&mut connector) + .map_err(Error::from) // <- convert SendRequestError to an Error + .and_then(|mut resp| { + resp.body() // <- this is MessageBody type, resolves to complete body + .from_err() // <- convert PayloadError to an Error .and_then(|body| { - let resp: HttpBinResponse = serde_json::from_slice(&body).unwrap(); - fut_ok(resp.json) + let resp: HttpBinResponse = + serde_json::from_slice(&body).unwrap(); + ok(resp.json) }) - ), + }), ) } fn create_something_v1( - some_data: Json, + some_data: web::Json, ) -> Box> { - step_x_v1(some_data.into_inner()) - .and_then(|some_data_2| { - step_x_v1(some_data_2).and_then(|some_data_3| { - step_x_v1(some_data_3).and_then(|d| { - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(serde_json::to_string(&d).unwrap()) - .into()) - }) + Box::new(step_x_v1(some_data.into_inner()).and_then(|some_data_2| { + step_x_v1(some_data_2).and_then(|some_data_3| { + step_x_v1(some_data_3).and_then(|d| { + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(serde_json::to_string(&d).unwrap()) + .into()) }) }) - .responder() + })) } // --------------------------------------------------------------- @@ -102,23 +95,25 @@ fn create_something_v1( /// post json to httpbin, get it back in the response body, return deserialized fn step_x_v2(data: SomeData) -> impl Future { + let mut connector = client::Connector::default().service(); + client::ClientRequest::post("https://httpbin.org/post") - .json(data).unwrap() - .send() - .conn_timeout(Duration::from_secs(10)) - .map_err(Error::from) // <- convert SendRequestError to an Error - .and_then( - |resp| resp.body() // <- this is MessageBody type, resolves to complete body - .from_err() // <- convert PayloadError to an Error + .json(data) + .unwrap() + .send(&mut connector) + .map_err(Error::from) // <- convert SendRequestError to an Error + .and_then(|mut resp| { + resp.body() // <- this is MessageBody type, resolves to complete body + .from_err() // <- convert PayloadError to an Error .and_then(|body| { let resp: HttpBinResponse = serde_json::from_slice(&body).unwrap(); - fut_ok(resp.json) + ok(resp.json) }) - ) + }) } fn create_something_v2( - some_data: Json, + some_data: web::Json, ) -> impl Future { step_x_v2(some_data.into_inner()).and_then(|some_data_2| { step_x_v2(some_data_2).and_then(|some_data_3| { @@ -132,23 +127,21 @@ fn create_something_v2( }) } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("asyncio_example"); - server::new(move || { + HttpServer::new(|| { App::new() - .resource("/something_v1", |r| { - r.method(Method::POST).with(create_something_v1) - }) - .resource("/something_v2", |r| { - r.method(Method::POST).with_async(create_something_v2) - }) - }).bind("127.0.0.1:8088") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8088"); - let _ = sys.run(); + .service( + web::resource("/something_v1") + .route(web::post().to(create_something_v1)), + ) + .service( + web::resource("/something_v2") + .route(web::post().to_async(create_something_v2)), + ) + }) + .bind("127.0.0.1:8088")? + .run() } diff --git a/cookie-auth-full/Cargo.toml b/cookie-auth-full/Cargo.toml deleted file mode 100644 index 87e6df95..00000000 --- a/cookie-auth-full/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "cookie-auth-full" -version = "0.1.0" -authors = ["Nikolay Kim "] -workspace = "../" - -[dependencies] -actix = "0.7" -actix-web = "0.7" - -cookie = { version="0.11", features=["percent-encode", "secure"] } -futures = "0.1" -time = "0.1" -env_logger = "0.5" diff --git a/cookie-auth-full/src/auth.rs b/cookie-auth-full/src/auth.rs deleted file mode 100644 index 56ec54e4..00000000 --- a/cookie-auth-full/src/auth.rs +++ /dev/null @@ -1,274 +0,0 @@ -#![allow(dead_code)] -use std::rc::Rc; - -use cookie::{Cookie, CookieJar, Key}; -use futures::future::{err as FutErr, ok as FutOk, FutureResult}; -use futures::Future; -use time::Duration; - -use actix_web::http::header::{self, HeaderValue}; -use actix_web::middleware::{Middleware, Response, Started}; -use actix_web::{Error, HttpRequest, HttpResponse, Result}; - -/// Trait provides identity service for the request. -pub trait RequestIdentity { - /// Return the claimed identity of the user associated request or - /// ``None`` if no identity can be found associated with the request. - fn identity(&self) -> Option; - - /// Remember identity. - fn remember(&self, identity: String); - - /// This method is used to 'forget' the current identity on subsequent - /// requests. - fn forget(&self); -} - -impl RequestIdentity for HttpRequest { - fn identity(&self) -> Option { - if let Some(id) = self.extensions().get::() { - return id.0.identity().map(|s| s.to_owned()); - } - None - } - - fn remember(&self, identity: String) { - if let Some(id) = self.extensions_mut().get_mut::() { - return id.0.as_mut().remember(identity); - } - } - - fn forget(&self) { - if let Some(id) = self.extensions_mut().get_mut::() { - return id.0.forget(); - } - } -} - -/// An identity -pub trait Identity: 'static { - fn identity(&self) -> Option<&str>; - - fn remember(&mut self, key: String); - - fn forget(&mut self); - - /// Write session to storage backend. - fn write(&mut self, resp: HttpResponse) -> Result; -} - -/// Identity policy definition. -pub trait IdentityPolicy: Sized + 'static { - type Identity: Identity; - type Future: Future; - - /// Parse the session from request and load data from a service identity. - fn from_request(&self, request: &mut HttpRequest) -> Self::Future; -} - -/// Middleware that implements identity service -pub struct IdentityService { - backend: T, -} - -impl IdentityService { - /// Create new identity service with specified backend. - pub fn new(backend: T) -> Self { - IdentityService { backend } - } -} - -struct IdentityBox(Box); - -#[doc(hidden)] -unsafe impl Send for IdentityBox {} -#[doc(hidden)] -unsafe impl Sync for IdentityBox {} - -impl> Middleware for IdentityService { - fn start(&self, req: &HttpRequest) -> Result { - let mut req = req.clone(); - - let fut = self - .backend - .from_request(&mut req) - .then(move |res| match res { - Ok(id) => { - req.extensions_mut().insert(IdentityBox(Box::new(id))); - FutOk(None) - } - Err(err) => FutErr(err), - }); - Ok(Started::Future(Box::new(fut))) - } - - fn response(&self, req: &HttpRequest, resp: HttpResponse) -> Result { - if let Some(mut id) = req.extensions_mut().remove::() { - id.0.write(resp) - } else { - Ok(Response::Done(resp)) - } - } -} - -/// Identity that uses private cookies as identity storage -pub struct CookieIdentity { - changed: bool, - identity: Option, - inner: Rc, -} - -impl Identity for CookieIdentity { - fn identity(&self) -> Option<&str> { - self.identity.as_ref().map(|s| s.as_ref()) - } - - fn remember(&mut self, value: String) { - self.changed = true; - self.identity = Some(value); - } - - fn forget(&mut self) { - self.changed = true; - self.identity = None; - } - - fn write(&mut self, mut resp: HttpResponse) -> Result { - if self.changed { - let _ = self.inner.set_cookie(&mut resp, self.identity.take()); - } - Ok(Response::Done(resp)) - } -} - -struct CookieIdentityInner { - key: Key, - name: String, - path: String, - domain: Option, - secure: bool, - max_age: Option, -} - -impl CookieIdentityInner { - fn new(key: &[u8]) -> CookieIdentityInner { - CookieIdentityInner { - key: Key::from_master(key), - name: "actix-identity".to_owned(), - path: "/".to_owned(), - domain: None, - secure: true, - max_age: None, - } - } - - fn set_cookie(&self, resp: &mut HttpResponse, id: Option) -> Result<()> { - let some = id.is_some(); - { - let id = id.unwrap_or_else(|| String::new()); - let mut cookie = Cookie::new(self.name.clone(), id); - cookie.set_path(self.path.clone()); - cookie.set_secure(self.secure); - cookie.set_http_only(true); - - if let Some(ref domain) = self.domain { - cookie.set_domain(domain.clone()); - } - - if let Some(max_age) = self.max_age { - cookie.set_max_age(max_age); - } - - let mut jar = CookieJar::new(); - if some { - jar.private(&self.key).add(cookie); - } else { - jar.add_original(cookie.clone()); - jar.private(&self.key).remove(cookie); - } - - for cookie in jar.delta() { - let val = HeaderValue::from_str(&cookie.to_string())?; - resp.headers_mut().append(header::SET_COOKIE, val); - } - } - - Ok(()) - } - - fn load(&self, req: &mut HttpRequest) -> Option { - if let Ok(cookies) = req.cookies() { - for cookie in cookies.iter() { - if cookie.name() == self.name { - let mut jar = CookieJar::new(); - jar.add_original(cookie.clone()); - - let cookie_opt = jar.private(&self.key).get(&self.name); - if let Some(cookie) = cookie_opt { - return Some(cookie.value().into()); - } - } - } - } - None - } -} - -/// Use cookies for request identity. -pub struct CookieIdentityPolicy(Rc); - -impl CookieIdentityPolicy { - /// Construct new `CookieIdentityPolicy` instance. - /// - /// Panics if key length is less than 32 bytes. - pub fn new(key: &[u8]) -> CookieIdentityPolicy { - CookieIdentityPolicy(Rc::new(CookieIdentityInner::new(key))) - } - - /// Sets the `path` field in the session cookie being built. - pub fn path>(mut self, value: S) -> CookieIdentityPolicy { - Rc::get_mut(&mut self.0).unwrap().path = value.into(); - self - } - - /// Sets the `name` field in the session cookie being built. - pub fn name>(mut self, value: S) -> CookieIdentityPolicy { - Rc::get_mut(&mut self.0).unwrap().name = value.into(); - self - } - - /// Sets the `domain` field in the session cookie being built. - pub fn domain>(mut self, value: S) -> CookieIdentityPolicy { - Rc::get_mut(&mut self.0).unwrap().domain = Some(value.into()); - self - } - - /// Sets the `secure` field in the session cookie being built. - /// - /// If the `secure` field is set, a cookie will only be transmitted when the - /// connection is secure - i.e. `https` - pub fn secure(mut self, value: bool) -> CookieIdentityPolicy { - Rc::get_mut(&mut self.0).unwrap().secure = value; - self - } - - /// Sets the `max-age` field in the session cookie being built. - pub fn max_age(mut self, value: Duration) -> CookieIdentityPolicy { - Rc::get_mut(&mut self.0).unwrap().max_age = Some(value); - self - } -} - -impl IdentityPolicy for CookieIdentityPolicy { - type Identity = CookieIdentity; - type Future = FutureResult; - - fn from_request(&self, req: &mut HttpRequest) -> Self::Future { - let identity = self.0.load(req); - FutOk(CookieIdentity { - identity, - changed: false, - inner: Rc::clone(&self.0), - }) - } -} diff --git a/cookie-auth-full/src/main.rs b/cookie-auth-full/src/main.rs deleted file mode 100644 index f7a0c09c..00000000 --- a/cookie-auth-full/src/main.rs +++ /dev/null @@ -1,49 +0,0 @@ -extern crate actix; -extern crate actix_web; -extern crate cookie; -extern crate env_logger; -extern crate futures; -extern crate time; - -use actix_web::{middleware, server, App, HttpRequest, HttpResponse}; - -mod auth; -use auth::{CookieIdentityPolicy, IdentityService, RequestIdentity}; - -fn index(req: &HttpRequest) -> String { - format!("Hello {}", req.identity().unwrap_or("Anonymous".to_owned())) -} - -fn login(req: &HttpRequest) -> HttpResponse { - req.remember("user1".to_owned()); - HttpResponse::Found().header("location", "/").finish() -} - -fn logout(req: &HttpRequest) -> HttpResponse { - req.forget(); - HttpResponse::Found().header("location", "/").finish() -} - -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); - env_logger::init(); - let sys = actix::System::new("cookie-auth"); - - server::new(|| { - App::new() - .middleware(middleware::Logger::default()) - .middleware(IdentityService::new( - CookieIdentityPolicy::new(&[0; 32]) - .name("auth-example") - .secure(false), - )) - .resource("/login", |r| r.f(login)) - .resource("/logout", |r| r.f(logout)) - .resource("/", |r| r.f(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); -} diff --git a/cookie-auth/Cargo.toml b/cookie-auth/Cargo.toml index ceda654d..2e7858d3 100644 --- a/cookie-auth/Cargo.toml +++ b/cookie-auth/Cargo.toml @@ -5,6 +5,5 @@ authors = ["Nikolay Kim "] workspace = "../" [dependencies] -actix = "0.7" -actix-web = "0.7" +actix-web = { git="https://github.com/actix/actix-web.git" } env_logger = "0.5" diff --git a/cookie-auth/src/main.rs b/cookie-auth/src/main.rs index a7444793..82db1da3 100644 --- a/cookie-auth/src/main.rs +++ b/cookie-auth/src/main.rs @@ -2,9 +2,9 @@ extern crate actix; extern crate actix_web; extern crate env_logger; -use actix_web::{middleware, server, App, HttpRequest, HttpResponse}; use actix_web::middleware::identity::RequestIdentity; use actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService}; +use actix_web::{middleware, server, App, HttpRequest, HttpResponse}; fn index(req: &HttpRequest) -> String { format!("Hello {}", req.identity().unwrap_or("Anonymous".to_owned())) @@ -36,9 +36,10 @@ fn main() { .resource("/login", |r| r.f(login)) .resource("/logout", |r| r.f(logout)) .resource("/", |r| r.f(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + }) + .bind("127.0.0.1:8080") + .unwrap() + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/cookie-session/Cargo.toml b/cookie-session/Cargo.toml index 399a6172..2947b950 100644 --- a/cookie-session/Cargo.toml +++ b/cookie-session/Cargo.toml @@ -2,12 +2,13 @@ name = "cookie-session" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [dependencies] -actix = "0.7" -actix-web = "^0.7" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } futures = "0.1" time = "0.1" -env_logger = "0.5" +env_logger = "0.6" diff --git a/cookie-session/src/main.rs b/cookie-session/src/main.rs index 94f736f9..6e0df123 100644 --- a/cookie-session/src/main.rs +++ b/cookie-session/src/main.rs @@ -5,50 +5,38 @@ //! //! [User guide](https://actix.rs/book/actix-web/sec-9-middlewares.html#user-sessions) -extern crate actix; -extern crate actix_web; -extern crate env_logger; -extern crate futures; - -use actix_web::middleware::session::{self, RequestSession}; -use actix_web::{middleware, server, App, HttpRequest, Result}; -use std::env; +use actix_session::{CookieSession, Session}; +use actix_web::{middleware::Logger, web, App, HttpRequest, HttpServer, Result}; /// simple index handler with session -fn index(req: &HttpRequest) -> Result<&'static str> { +fn index(session: Session, req: HttpRequest) -> Result<&'static str> { println!("{:?}", req); // RequestSession trait is used for session access let mut counter = 1; - if let Some(count) = req.session().get::("counter")? { + if let Some(count) = session.get::("counter")? { println!("SESSION value: {}", count); counter = count + 1; - req.session().set("counter", counter)?; + session.set("counter", counter)?; } else { - req.session().set("counter", counter)?; + session.set("counter", counter)?; } Ok("welcome!") } -fn main() { - env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("session-example"); - server::new(|| { + HttpServer::new(|| { App::new() // enable logger - .middleware(middleware::Logger::default()) + .middleware(Logger::default()) // cookie session middleware - .middleware(session::SessionStorage::new( - session::CookieSessionBackend::signed(&[0; 32]).secure(false) - )) - .resource("/", |r| r.f(index)) - }).bind("127.0.0.1:8080") - .expect("Can not bind to 127.0.0.1:8080") - .start(); - - println!("Starting http server: 127.0.0.1:8080"); - let _ = sys.run(); + .middleware(CookieSession::signed(&[0; 32]).secure(false)) + .service(web::resource("/").to(index)) + }) + .bind("127.0.0.1:8080")? + .run() } diff --git a/error_handling/Cargo.toml b/error_handling/Cargo.toml index fe27b1c3..f1df6a48 100644 --- a/error_handling/Cargo.toml +++ b/error_handling/Cargo.toml @@ -2,11 +2,13 @@ name = "error_handling" version = "0.1.0" authors = ["dowwie "] +edition = "2018" +workspace = ".." [dependencies] -actix = "0.7.3" -actix-web = "0.7.3" -failure = "0.1.2" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } + +derive_more = "0.14.0" futures = "0.1.23" rand = "0.5.4" -env_logger = "0.5.12" +env_logger = "0.6" diff --git a/error_handling/src/main.rs b/error_handling/src/main.rs index 6a1788f0..676a8ce8 100644 --- a/error_handling/src/main.rs +++ b/error_handling/src/main.rs @@ -1,10 +1,10 @@ /* -The goal of this example is to show how to propagate a custom error type, derived -from the Fail trait, to a web handler that will evaluate the type of error that +The goal of this example is to show how to propagate a custom error type, +to a web handler that will evaluate the type of error that was raised and return an appropriate HTTPResponse. This example uses a 50/50 chance of returning 200 Ok, otherwise one of four possible -http errors will be chosen, each with an equal chance of being selected: +http errors will be chosen, each with an equal chance of being selected: 1. 403 Forbidden 2. 401 Unauthorized 3. 500 InternalServerError @@ -12,128 +12,91 @@ http errors will be chosen, each with an equal chance of being selected: */ - -extern crate actix; -extern crate actix_web; -extern crate env_logger; -#[macro_use] extern crate failure; -extern crate futures; -extern crate rand; - - -use actix_web::{ - http::Method, server, App, AsyncResponder, Error as ActixWebError, - HttpResponse, HttpRequest +use actix_web::{web, App, Error, HttpResponse, HttpServer, ResponseError}; +use derive_more::Display; // naming it clearly for illustration purposes +use futures::future::{err, ok, Future}; +use rand::{ + distributions::{Distribution, Standard}, + thread_rng, Rng, }; -use failure::Error as FailureError; // naming it clearly for illustration purposes -use futures::{ - future::{ - ok as fut_ok, - err as fut_err - }, - Future -}; -use rand::{thread_rng, Rng, distributions::{Distribution, Standard}}; - - -#[derive(Fail, Debug)] +#[derive(Debug, Display)] pub enum CustomError { - #[fail(display = "Custom Error 1")] + #[display(fmt = "Custom Error 1")] CustomOne, - #[fail(display = "Custom Error 2")] + #[display(fmt = "Custom Error 2")] CustomTwo, - #[fail(display = "Custom Error 3")] + #[display(fmt = "Custom Error 3")] CustomThree, - #[fail(display = "Custom Error 4")] - CustomFour + #[display(fmt = "Custom Error 4")] + CustomFour, } - impl Distribution for Standard { fn sample(&self, rng: &mut R) -> CustomError { match rng.gen_range(0, 4) { 0 => CustomError::CustomOne, 1 => CustomError::CustomTwo, 2 => CustomError::CustomThree, - _ => CustomError::CustomFour + _ => CustomError::CustomFour, } } } -/* +/// Actix web uses `ResponseError` for conversion of errors to a response impl ResponseError for CustomError { fn error_response(&self) -> HttpResponse { - HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR) + match self { + CustomError::CustomOne => { + println!("do some stuff related to CustomOne error"); + HttpResponse::Forbidden().finish() + } + + CustomError::CustomTwo => { + println!("do some stuff related to CustomTwo error"); + HttpResponse::Unauthorized().finish() + } + + CustomError::CustomThree => { + println!("do some stuff related to CustomThree error"); + HttpResponse::InternalServerError().finish() + } + + _ => { + println!("do some stuff related to CustomFour error"); + HttpResponse::BadRequest().finish() + } + } } } -*/ - /// randomly returns either () or one of the 4 CustomError variants -//fn do_something_random() -> impl Future, -// Error = ActixWebError> { fn do_something_random() -> impl Future { let mut rng = thread_rng(); // 20% chance that () will be returned by this function - if rng.gen_bool(2.0/10.0) { - return fut_ok(()) + if rng.gen_bool(2.0 / 10.0) { + ok(()) + } else { + err(rand::random::()) } - - let err: CustomError = rand::random(); - return fut_err(err) } - -fn do_something(_req: HttpRequest) - -> impl Future { - - do_something_random() - .then(|result| match result { - Ok(_) => Ok(HttpResponse::Ok() - .body("Nothing interesting happened. Try again.")), - - Err(err) => match err { - CustomError::CustomOne => { - println!("do some stuff related to CustomOne error"); - Ok(HttpResponse::Forbidden().finish()) - }, - - CustomError::CustomTwo => { - println!("do some stuff related to CustomTwo error"); - Ok(HttpResponse::Unauthorized().finish()) - }, - - CustomError::CustomThree => { - println!("do some stuff related to CustomThree error"); - Ok(HttpResponse::InternalServerError().finish()) - }, - - _ => { - println!("do some stuff related to CustomFour error"); - Ok(HttpResponse::BadRequest().finish()) - } - } +fn do_something() -> impl Future { + do_something_random().from_err().and_then(|_| { + HttpResponse::Ok().body("Nothing interesting happened. Try again.") }) - .responder() } - -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("error_handling_example"); - server::new(move || { - App::new() - .resource("/something", |r| - r.method(Method::GET) - .with_async(do_something)) - }).bind("127.0.0.1:8088") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8088"); - let _ = sys.run(); + HttpServer::new(move || { + App::new().service( + web::resource("/something").route(web::get().to_async(do_something)), + ) + }) + .bind("127.0.0.1:8088")? + .run() } diff --git a/form/src/main.rs b/form/src/main.rs index 615fff2e..01f416fb 100644 --- a/form/src/main.rs +++ b/form/src/main.rs @@ -18,22 +18,24 @@ fn main() { let _addr = server::new(|| { App::with_state(AppState { foo: "bar".to_string(), - }).middleware(middleware::Logger::default()) - .resource("/", |r| { - r.method(http::Method::GET).with(index); - }) - .resource("/post1", |r| { - r.method(http::Method::POST).with(handle_post_1) - }) - .resource("/post2", |r| { - r.method(http::Method::POST).with(handle_post_2) - }) - .resource("/post3", |r| { - r.method(http::Method::POST).with(handle_post_3) - }) - }).bind("127.0.0.1:8080") - .expect("Can not bind to 127.0.0.1:8080") - .start(); + }) + .middleware(middleware::Logger::default()) + .resource("/", |r| { + r.method(http::Method::GET).with(index); + }) + .resource("/post1", |r| { + r.method(http::Method::POST).with(handle_post_1) + }) + .resource("/post2", |r| { + r.method(http::Method::POST).with(handle_post_2) + }) + .resource("/post3", |r| { + r.method(http::Method::POST).with(handle_post_3) + }) + }) + .bind("127.0.0.1:8080") + .expect("Can not bind to 127.0.0.1:8080") + .start(); println!("Starting http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/hello-world/src/main.rs b/hello-world/src/main.rs index 90d93b7d..2d787836 100644 --- a/hello-world/src/main.rs +++ b/hello-world/src/main.rs @@ -19,9 +19,10 @@ fn main() { .middleware(middleware::Logger::default()) .resource("/index.html", |r| r.f(|_| "Hello world!")) .resource("/", |r| r.f(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + }) + .bind("127.0.0.1:8080") + .unwrap() + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/http-full-proxy/src/main.rs b/http-full-proxy/src/main.rs index 4d691870..05bfb394 100644 --- a/http-full-proxy/src/main.rs +++ b/http-full-proxy/src/main.rs @@ -87,25 +87,29 @@ fn main() { .value_name("LISTEN ADDR") .index(1) .required(true), - ).arg( + ) + .arg( Arg::with_name("listen_port") .takes_value(true) .value_name("LISTEN PORT") .index(2) .required(true), - ).arg( + ) + .arg( Arg::with_name("forward_addr") .takes_value(true) .value_name("FWD ADDR") .index(3) .required(true), - ).arg( + ) + .arg( Arg::with_name("forward_port") .takes_value(true) .value_name("FWD PORT") .index(4) .required(true), - ).get_matches(); + ) + .get_matches(); let listen_addr = matches.value_of("listen_addr").unwrap(); let listen_port = value_t!(matches, "listen_port", u16).unwrap_or_else(|e| e.exit()); @@ -121,13 +125,15 @@ fn main() { .unwrap() .next() .unwrap() - )).unwrap(); + )) + .unwrap(); server::new(move || { App::with_state(AppState::init(forward_url.clone())).default_resource(|r| { r.f(forward); }) - }).workers(32) + }) + .workers(32) .bind((listen_addr, listen_port)) .expect("Cannot bind listening port") .system_exit() diff --git a/http-proxy/src/main.rs b/http-proxy/src/main.rs index 3785ae6c..9d51aceb 100644 --- a/http-proxy/src/main.rs +++ b/http-proxy/src/main.rs @@ -12,15 +12,18 @@ use futures::{Future, Stream}; /// Stream client request response and then send body to a server response fn index(_req: &HttpRequest) -> Box> { client::ClientRequest::get("http://127.0.0.1:8081/") - .finish().unwrap() + .finish() + .unwrap() .send() - .map_err(Error::from) // <- convert SendRequestError to an Error - .and_then( - |resp| resp.body() // <- this is MessageBody type, resolves to complete body - .from_err() // <- convert PayloadError to an Error - .and_then(|body| { // <- we got complete body, now send as server response + .map_err(Error::from) // <- convert SendRequestError to an Error + .and_then(|resp| { + resp.body() // <- this is MessageBody type, resolves to complete body + .from_err() // <- convert PayloadError to an Error + .and_then(|body| { + // <- we got complete body, now send as server response Ok(HttpResponse::Ok().body(body)) - })) + }) + }) .responder() } @@ -28,14 +31,16 @@ fn index(_req: &HttpRequest) -> Box> fn streaming(_req: &HttpRequest) -> Box> { // send client request client::ClientRequest::get("https://www.rust-lang.org/en-US/") - .finish().unwrap() - .send() // <- connect to host and send request - .map_err(Error::from) // <- convert SendRequestError to an Error - .and_then(|resp| { // <- we received client response + .finish() + .unwrap() + .send() // <- connect to host and send request + .map_err(Error::from) // <- convert SendRequestError to an Error + .and_then(|resp| { + // <- we received client response Ok(HttpResponse::Ok() - // read one chunk from client response and send this chunk to a server response - // .from_err() converts PayloadError to an Error - .body(Body::Streaming(Box::new(resp.payload().from_err())))) + // read one chunk from client response and send this chunk to a server response + // .from_err() converts PayloadError to an Error + .body(Body::Streaming(Box::new(resp.payload().from_err())))) }) .responder() } @@ -50,10 +55,11 @@ fn main() { .middleware(middleware::Logger::default()) .resource("/streaming", |r| r.f(streaming)) .resource("/", |r| r.f(index)) - }).workers(1) - .bind("127.0.0.1:8080") - .unwrap() - .start(); + }) + .workers(1) + .bind("127.0.0.1:8080") + .unwrap() + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/http-proxy/src/server.rs b/http-proxy/src/server.rs index ca1dfb26..11584def 100644 --- a/http-proxy/src/server.rs +++ b/http-proxy/src/server.rs @@ -20,14 +20,15 @@ fn main() { server::new(|| { App::new() - // enable logger + // enable logger .middleware(middleware::Logger::default()) .resource("/index.html", |r| r.f(|_| "Hello world!")) .resource("/", |r| r.f(index)) - }).workers(1) - .bind("127.0.0.1:8081") - .unwrap() - .start(); + }) + .workers(1) + .bind("127.0.0.1:8081") + .unwrap() + .start(); println!("Started http server: 127.0.0.1:8081"); let _ = sys.run(); diff --git a/juniper/src/main.rs b/juniper/src/main.rs index d06cc5e7..468c093a 100644 --- a/juniper/src/main.rs +++ b/juniper/src/main.rs @@ -93,14 +93,17 @@ fn main() { // Start http server server::new(move || { - App::with_state(AppState{executor: addr.clone()}) - // enable logger - .middleware(middleware::Logger::default()) - .resource("/graphql", |r| r.method(http::Method::POST).with(graphql)) - .resource("/graphiql", |r| r.method(http::Method::GET).h(graphiql)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + App::with_state(AppState { + executor: addr.clone(), + }) + // enable logger + .middleware(middleware::Logger::default()) + .resource("/graphql", |r| r.method(http::Method::POST).with(graphql)) + .resource("/graphiql", |r| r.method(http::Method::GET).h(graphiql)) + }) + .bind("127.0.0.1:8080") + .unwrap() + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/middleware/src/main.rs b/middleware/src/main.rs index 539a3076..91ae9d0c 100644 --- a/middleware/src/main.rs +++ b/middleware/src/main.rs @@ -16,14 +16,17 @@ fn main() { .middleware(simple::SayHi) // .middleware(redirect::CheckLogin) .resource("/login", |r| { - r.f(|_| "You are on /login. Go to src/redirect.rs to change this behavior.") + r.f(|_| { + "You are on /login. Go to src/redirect.rs to change this behavior." + }) }) .resource("/", |r| { r.f(|_| "Hello, middleware! Check the console where the server is run.") }) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + }) + .bind("127.0.0.1:8080") + .unwrap() + .start(); let _ = sys.run(); } diff --git a/multipart/src/main.rs b/multipart/src/main.rs index 6cea2536..37c17bf6 100644 --- a/multipart/src/main.rs +++ b/multipart/src/main.rs @@ -101,14 +101,16 @@ fn main() { server::new(|| { App::with_state(AppState { counter: Cell::new(0), - }).middleware(middleware::Logger::default()) - .resource("/", |r| { - r.method(http::Method::GET).with(index); - r.method(http::Method::POST).with(upload); - }) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + }) + .middleware(middleware::Logger::default()) + .resource("/", |r| { + r.method(http::Method::GET).with(index); + r.method(http::Method::POST).with(upload); + }) + }) + .bind("127.0.0.1:8080") + .unwrap() + .start(); println!("Starting http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/protobuf/src/main.rs b/protobuf/src/main.rs index aaae1f18..83220301 100644 --- a/protobuf/src/main.rs +++ b/protobuf/src/main.rs @@ -28,10 +28,10 @@ pub struct MyObj { /// This handler uses `ProtoBufMessage` for loading protobuf object. fn index(req: &HttpRequest) -> Box> { protobuf::ProtoBufMessage::new(req) - .from_err() // convert all errors into `Error` + .from_err() // convert all errors into `Error` .and_then(|val: MyObj| { println!("model: {:?}", val); - Ok(HttpResponse::Ok().protobuf(val)?) // <- send response + Ok(HttpResponse::Ok().protobuf(val)?) // <- send response }) .responder() } @@ -45,10 +45,11 @@ fn main() { App::new() .middleware(middleware::Logger::default()) .resource("/", |r| r.method(http::Method::POST).f(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .shutdown_timeout(1) - .start(); + }) + .bind("127.0.0.1:8080") + .unwrap() + .shutdown_timeout(1) + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/redis-session/src/main.rs b/redis-session/src/main.rs index 3b68ab56..18a68e15 100644 --- a/redis-session/src/main.rs +++ b/redis-session/src/main.rs @@ -35,14 +35,16 @@ fn main() { // enable logger .middleware(middleware::Logger::default()) // redis session middleware - .middleware(SessionStorage::new( - RedisSessionBackend::new("127.0.0.1:6379", &[0; 32]) - )) + .middleware(SessionStorage::new(RedisSessionBackend::new( + "127.0.0.1:6379", + &[0; 32], + ))) // register simple route, handle all methods .resource("/", |r| r.f(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + }) + .bind("127.0.0.1:8080") + .unwrap() + .start(); let _ = sys.run(); } diff --git a/rustls/src/main.rs b/rustls/src/main.rs index 58220215..33bcb538 100644 --- a/rustls/src/main.rs +++ b/rustls/src/main.rs @@ -49,16 +49,19 @@ fn main() { // register simple handler, handle all methods .resource("/index.html", |r| r.f(index)) // with path parameters - .resource("/", |r| r.method(http::Method::GET).f(|_| { - HttpResponse::Found() - .header("LOCATION", "/index.html") - .finish() - })) + .resource("/", |r| { + r.method(http::Method::GET).f(|_| { + HttpResponse::Found() + .header("LOCATION", "/index.html") + .finish() + }) + }) .handler("/static", StaticFiles::new("static").unwrap()) - }).bind_with("127.0.0.1:8443", move || acceptor.clone()) + }) + .bind_with("127.0.0.1:8443", move || acceptor.clone()) .unwrap() .start(); println!("Started http server: 127.0.0.1:8443"); let _ = sys.run(); -} \ No newline at end of file +} diff --git a/simple-auth-server/src/app.rs b/simple-auth-server/src/app.rs index f56be1a2..05fdf2f7 100644 --- a/simple-auth-server/src/app.rs +++ b/simple-auth-server/src/app.rs @@ -14,8 +14,10 @@ pub struct AppState { /// creates and returns the app after mounting all routes/resources pub fn create_app(db: Addr) -> App { // 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()); + 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()) diff --git a/simple-auth-server/src/auth_handler.rs b/simple-auth-server/src/auth_handler.rs index cedfa90e..161a951f 100644 --- a/simple-auth-server/src/auth_handler.rs +++ b/simple-auth-server/src/auth_handler.rs @@ -1,9 +1,9 @@ use actix::{Handler, Message}; +use actix_web::{middleware::identity::RequestIdentity, FromRequest, HttpRequest}; +use bcrypt::verify; use diesel::prelude::*; use errors::ServiceError; -use models::{DbExecutor, User, SlimUser}; -use bcrypt::verify; -use actix_web::{FromRequest, HttpRequest, middleware::identity::RequestIdentity}; +use models::{DbExecutor, SlimUser, User}; use utils::decode_token; #[derive(Debug, Deserialize)] @@ -19,22 +19,24 @@ impl Message for AuthData { impl Handler for DbExecutor { type Result = Result; fn handle(&mut self, msg: AuthData, _: &mut Self::Context) -> Self::Result { - use schema::users::dsl::{users, email}; + use schema::users::dsl::{email, users}; let conn: &PgConnection = &self.0.get().unwrap(); - let mut items = users - .filter(email.eq(&msg.email)) - .load::(conn)?; + let mut items = users.filter(email.eq(&msg.email)).load::(conn)?; if let Some(user) = items.pop() { match verify(&msg.password, &user.password) { - Ok(matching) => if matching { + Ok(matching) => { + if matching { return Ok(user.into()); - }, + } + } Err(_) => (), } } - Err(ServiceError::BadRequest("Username and Password don't match".into())) + Err(ServiceError::BadRequest( + "Username and Password don't match".into(), + )) } } diff --git a/simple-auth-server/src/auth_routes.rs b/simple-auth-server/src/auth_routes.rs index 48ee15c0..90cafec4 100644 --- a/simple-auth-server/src/auth_routes.rs +++ b/simple-auth-server/src/auth_routes.rs @@ -1,13 +1,16 @@ -use actix_web::{AsyncResponder, FutureResponse, HttpResponse, HttpRequest, ResponseError, Json}; use actix_web::middleware::identity::RequestIdentity; +use actix_web::{ + AsyncResponder, FutureResponse, HttpRequest, HttpResponse, Json, ResponseError, +}; use futures::future::Future; use utils::create_token; use app::AppState; use auth_handler::{AuthData, LoggedUser}; -pub fn login((auth_data, req): (Json, HttpRequest)) - -> FutureResponse { +pub fn login( + (auth_data, req): (Json, HttpRequest), +) -> FutureResponse { req.state() .db .send(auth_data.into_inner()) @@ -19,7 +22,8 @@ pub fn login((auth_data, req): (Json, HttpRequest)) Ok(HttpResponse::Ok().into()) } Err(err) => Ok(err.error_response()), - }).responder() + }) + .responder() } pub fn logout(req: HttpRequest) -> HttpResponse { diff --git a/simple-auth-server/src/email_service.rs b/simple-auth-server/src/email_service.rs index f1db1172..d9854f49 100644 --- a/simple-auth-server/src/email_service.rs +++ b/simple-auth-server/src/email_service.rs @@ -9,8 +9,8 @@ fn get_api_key() -> String { pub fn send_invitation(invitation: &Invitation) { let tm = Transmission::new_eu(get_api_key()); - let sending_email = - std::env::var("SENDING_EMAIL_ADDRESS").expect("SENDING_EMAIL_ADDRESS must be set"); + let sending_email = std::env::var("SENDING_EMAIL_ADDRESS") + .expect("SENDING_EMAIL_ADDRESS must be set"); // new email message with sender name and email let mut email = Message::new(EmailAddress::new(sending_email, "Let's Organise")); @@ -39,7 +39,6 @@ pub fn send_invitation(invitation: &Invitation) { .to_string() ); - // complete the email message with details email .add_recipient(recipient) @@ -51,16 +50,14 @@ pub fn send_invitation(invitation: &Invitation) { // Note that we only print out the error response from email api match result { - Ok(res) => { - match res { - TransmissionResponse::ApiResponse(api_res) => { - println!("API Response: \n {:#?}", api_res); - } - TransmissionResponse::ApiError(errors) => { - println!("Response Errors: \n {:#?}", &errors); - } + Ok(res) => match res { + TransmissionResponse::ApiResponse(api_res) => { + println!("API Response: \n {:#?}", api_res); } - } + TransmissionResponse::ApiError(errors) => { + println!("Response Errors: \n {:#?}", &errors); + } + }, Err(error) => { println!("error \n {:#?}", error); } diff --git a/simple-auth-server/src/errors.rs b/simple-auth-server/src/errors.rs index b65aa4f7..0be63125 100644 --- a/simple-auth-server/src/errors.rs +++ b/simple-auth-server/src/errors.rs @@ -1,9 +1,8 @@ use actix_web::{error::ResponseError, HttpResponse}; -use std::convert::From; use diesel::result::{DatabaseErrorKind, Error}; +use std::convert::From; use uuid::ParseError; - #[derive(Fail, Debug)] pub enum ServiceError { #[fail(display = "Internal Server Error")] @@ -20,9 +19,14 @@ pub enum ServiceError { impl ResponseError for ServiceError { fn error_response(&self) -> HttpResponse { match *self { - ServiceError::InternalServerError => HttpResponse::InternalServerError().json("Internal Server Error, Please try later"), - ServiceError::BadRequest(ref message) => HttpResponse::BadRequest().json(message), - ServiceError::Unauthorized => HttpResponse::Unauthorized().json("Unauthorized") + ServiceError::InternalServerError => HttpResponse::InternalServerError() + .json("Internal Server Error, Please try later"), + ServiceError::BadRequest(ref message) => { + HttpResponse::BadRequest().json(message) + } + ServiceError::Unauthorized => { + HttpResponse::Unauthorized().json("Unauthorized") + } } } } @@ -42,12 +46,13 @@ impl From for ServiceError { match error { Error::DatabaseError(kind, info) => { if let DatabaseErrorKind::UniqueViolation = kind { - let message = info.details().unwrap_or_else(|| info.message()).to_string(); + let message = + info.details().unwrap_or_else(|| info.message()).to_string(); return ServiceError::BadRequest(message); } ServiceError::InternalServerError } - _ => ServiceError::InternalServerError + _ => ServiceError::InternalServerError, } } } diff --git a/simple-auth-server/src/invitation_handler.rs b/simple-auth-server/src/invitation_handler.rs index 425e4c0a..ac117f79 100644 --- a/simple-auth-server/src/invitation_handler.rs +++ b/simple-auth-server/src/invitation_handler.rs @@ -35,5 +35,3 @@ impl Handler for DbExecutor { Ok(inserted_invitation) } } - - diff --git a/simple-auth-server/src/invitation_routes.rs b/simple-auth-server/src/invitation_routes.rs index 9232c6d0..bd6a46c6 100644 --- a/simple-auth-server/src/invitation_routes.rs +++ b/simple-auth-server/src/invitation_routes.rs @@ -1,4 +1,6 @@ -use actix_web::{AsyncResponder, FutureResponse, HttpResponse, Json, ResponseError, State}; +use actix_web::{ + AsyncResponder, FutureResponse, HttpResponse, Json, ResponseError, State, +}; use futures::future::Future; use app::AppState; @@ -18,5 +20,6 @@ pub fn register_email( Ok(HttpResponse::Ok().into()) } Err(err) => Ok(err.error_response()), - }).responder() + }) + .responder() } diff --git a/simple-auth-server/src/main.rs b/simple-auth-server/src/main.rs index f5d096b2..5c1b3c27 100644 --- a/simple-auth-server/src/main.rs +++ b/simple-auth-server/src/main.rs @@ -1,18 +1,18 @@ // to avoid the warning from diesel macros #![allow(proc_macro_derive_resolution_fallback)] -extern crate bcrypt; extern crate actix; extern crate actix_web; -extern crate env_logger; -extern crate serde; +extern crate bcrypt; extern crate chrono; extern crate dotenv; +extern crate env_logger; extern crate futures; -extern crate r2d2; -extern crate uuid; extern crate jsonwebtoken as jwt; +extern crate r2d2; +extern crate serde; extern crate sparkpost; +extern crate uuid; #[macro_use] extern crate diesel; #[macro_use] @@ -21,26 +21,25 @@ extern crate serde_derive; extern crate failure; mod app; -mod models; -mod schema; -mod errors; mod auth_handler; mod auth_routes; +mod email_service; +mod errors; mod invitation_handler; mod invitation_routes; +mod models; mod register_handler; mod register_routes; +mod schema; mod utils; -mod email_service; -use models::DbExecutor; use actix::prelude::*; use actix_web::server; use diesel::{r2d2::ConnectionManager, PgConnection}; use dotenv::dotenv; +use models::DbExecutor; use std::env; - fn main() { dotenv().ok(); std::env::set_var("RUST_LOG", "simple-auth-server=debug,actix_web=info"); @@ -55,7 +54,8 @@ fn main() { .build(manager) .expect("Failed to create pool."); - let address: Addr = SyncArbiter::start(4, move || DbExecutor(pool.clone())); + let address: Addr = + SyncArbiter::start(4, move || DbExecutor(pool.clone())); server::new(move || app::create_app(address.clone())) .bind("127.0.0.1:3000") diff --git a/simple-auth-server/src/models.rs b/simple-auth-server/src/models.rs index fcafb9c5..651ad9f3 100644 --- a/simple-auth-server/src/models.rs +++ b/simple-auth-server/src/models.rs @@ -1,11 +1,11 @@ use actix::{Actor, SyncContext}; +use chrono::{Local, NaiveDateTime}; use diesel::pg::PgConnection; use diesel::r2d2::{ConnectionManager, Pool}; -use chrono::{NaiveDateTime, Local}; -use uuid::Uuid; use std::convert::From; +use uuid::Uuid; -use schema::{users, invitations}; +use schema::{invitations, users}; /// This is db executor actor. can be run in parallel pub struct DbExecutor(pub Pool>); @@ -51,8 +51,6 @@ pub struct SlimUser { impl From for SlimUser { fn from(user: User) -> Self { - SlimUser { - email: user.email - } + SlimUser { email: user.email } } } diff --git a/simple-auth-server/src/register_handler.rs b/simple-auth-server/src/register_handler.rs index 7cf98fd3..961061b0 100644 --- a/simple-auth-server/src/register_handler.rs +++ b/simple-auth-server/src/register_handler.rs @@ -2,9 +2,9 @@ use actix::{Handler, Message}; use chrono::Local; use diesel::prelude::*; use errors::ServiceError; -use models::{DbExecutor, Invitation, User, SlimUser}; -use uuid::Uuid; +use models::{DbExecutor, Invitation, SlimUser, User}; use utils::hash_password; +use uuid::Uuid; // UserData is used to extract data from a post request by the client #[derive(Debug, Deserialize)] @@ -23,11 +23,10 @@ impl Message for RegisterUser { type Result = Result; } - impl Handler for DbExecutor { type Result = Result; fn handle(&mut self, msg: RegisterUser, _: &mut Self::Context) -> Self::Result { - use schema::invitations::dsl::{invitations, id}; + use schema::invitations::dsl::{id, invitations}; use schema::users::dsl::users; let conn: &PgConnection = &self.0.get().unwrap(); @@ -35,7 +34,8 @@ impl Handler for DbExecutor { // return early with error that will be converted to ServiceError let invitation_id = Uuid::parse_str(&msg.invitation_id)?; - invitations.filter(id.eq(invitation_id)) + invitations + .filter(id.eq(invitation_id)) .load::(conn) .map_err(|_db_error| ServiceError::BadRequest("Invalid Invitation".into())) .and_then(|mut result| { @@ -45,9 +45,8 @@ impl Handler for DbExecutor { // try hashing the password, else return the error that will be converted to ServiceError let password: String = hash_password(&msg.password)?; let user = User::with_details(invitation.email, password); - let inserted_user: User = diesel::insert_into(users) - .values(&user) - .get_result(conn)?; + let inserted_user: User = + diesel::insert_into(users).values(&user).get_result(conn)?; return Ok(inserted_user.into()); } @@ -56,5 +55,3 @@ impl Handler for DbExecutor { }) } } - - diff --git a/simple-auth-server/src/register_routes.rs b/simple-auth-server/src/register_routes.rs index 5924ba50..79b9f9a2 100644 --- a/simple-auth-server/src/register_routes.rs +++ b/simple-auth-server/src/register_routes.rs @@ -1,22 +1,27 @@ -use actix_web::{AsyncResponder, FutureResponse, HttpResponse, ResponseError, State, Json, Path}; +use actix_web::{ + AsyncResponder, FutureResponse, HttpResponse, Json, Path, ResponseError, State, +}; use futures::future::Future; use app::AppState; use register_handler::{RegisterUser, UserData}; - -pub fn register_user((invitation_id, user_data, state): (Path, Json, State)) - -> FutureResponse { +pub fn register_user( + (invitation_id, user_data, state): (Path, Json, State), +) -> FutureResponse { let msg = RegisterUser { // into_inner() returns the inner string value from Path invitation_id: invitation_id.into_inner(), password: user_data.password.clone(), }; - state.db.send(msg) + state + .db + .send(msg) .from_err() .and_then(|db_response| match db_response { Ok(slim_user) => Ok(HttpResponse::Ok().json(slim_user)), Err(service_error) => Ok(service_error.error_response()), - }).responder() + }) + .responder() } diff --git a/simple-auth-server/src/schema.rs b/simple-auth-server/src/schema.rs index 646632db..95c37038 100644 --- a/simple-auth-server/src/schema.rs +++ b/simple-auth-server/src/schema.rs @@ -14,7 +14,4 @@ table! { } } -allow_tables_to_appear_in_same_query!( - invitations, - users, -); +allow_tables_to_appear_in_same_query!(invitations, users,); diff --git a/static_index/src/main.rs b/static_index/src/main.rs index 25c77c03..df6233dc 100644 --- a/static_index/src/main.rs +++ b/static_index/src/main.rs @@ -13,15 +13,18 @@ fn main() { server::new(|| { App::new() - // enable logger - .middleware(middleware::Logger::default()) - .handler( + // enable logger + .middleware(middleware::Logger::default()) + .handler( "/", - fs::StaticFiles::new("./static/").unwrap().index_file("index.html") + fs::StaticFiles::new("./static/") + .unwrap() + .index_file("index.html"), ) - }).bind("127.0.0.1:8080") - .expect("Can not start server on given IP/Port") - .start(); + }) + .bind("127.0.0.1:8080") + .expect("Can not start server on given IP/Port") + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/template_askama/src/main.rs b/template_askama/src/main.rs index 4a34abf1..27dc7617 100644 --- a/template_askama/src/main.rs +++ b/template_askama/src/main.rs @@ -24,8 +24,9 @@ fn index(query: Query>) -> Result { UserTemplate { name: name, text: "Welcome!", - }.render() - .unwrap() + } + .render() + .unwrap() } else { Index.render().unwrap() }; @@ -38,9 +39,10 @@ fn main() { // start http server server::new(move || { App::new().resource("/", |r| r.method(http::Method::GET).with(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + }) + .bind("127.0.0.1:8080") + .unwrap() + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/template_tera/src/main.rs b/template_tera/src/main.rs index e7e2c780..7cbd5579 100644 --- a/template_tera/src/main.rs +++ b/template_tera/src/main.rs @@ -44,13 +44,14 @@ fn main() { let tera = compile_templates!(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")); - App::with_state(AppState{template: tera}) + App::with_state(AppState { template: tera }) // enable logger .middleware(middleware::Logger::default()) .resource("/", |r| r.method(http::Method::GET).with(index)) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + }) + .bind("127.0.0.1:8080") + .unwrap() + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/unix-socket/src/main.rs b/unix-socket/src/main.rs index d999f8e9..6a3e3ed3 100644 --- a/unix-socket/src/main.rs +++ b/unix-socket/src/main.rs @@ -23,7 +23,8 @@ fn main() { .middleware(middleware::Logger::default()) .resource("/index.html", |r| r.f(|_| "Hello world!")) .resource("/", |r| r.f(index)) - }).start_incoming(listener.incoming(), false); + }) + .start_incoming(listener.incoming(), false); println!("Started http server: /tmp/actix-uds.socket"); let _ = sys.run(); diff --git a/web-cors/backend/src/main.rs b/web-cors/backend/src/main.rs index 8191ceeb..2fcec25b 100644 --- a/web-cors/backend/src/main.rs +++ b/web-cors/backend/src/main.rs @@ -39,10 +39,11 @@ fn main() { }) .register() }) - }).bind("127.0.0.1:8000") - .unwrap() - .shutdown_timeout(2) - .start(); + }) + .bind("127.0.0.1:8000") + .unwrap() + .shutdown_timeout(2) + .start(); let _ = sys.run(); } diff --git a/websocket-chat-broker/src/main.rs b/websocket-chat-broker/src/main.rs index 24ae4929..4ddc3bc7 100644 --- a/websocket-chat-broker/src/main.rs +++ b/websocket-chat-broker/src/main.rs @@ -52,7 +52,8 @@ impl WsChatSession { } fut::ok(()) - }).spawn(ctx); + }) + .spawn(ctx); } fn list_rooms(&mut self, ctx: &mut ws::WebsocketContext) { @@ -66,7 +67,8 @@ impl WsChatSession { } } fut::ok(()) - }).spawn(ctx); + }) + .spawn(ctx); } fn send_msg(&self, msg: &str) { @@ -158,7 +160,8 @@ fn main() { .unwrap() .index_file("index.html"), ) - }).bind("127.0.0.1:8080") + }) + .bind("127.0.0.1:8080") .unwrap() .start(); diff --git a/websocket-chat/src/main.rs b/websocket-chat/src/main.rs index 477b8e40..8849aba7 100644 --- a/websocket-chat/src/main.rs +++ b/websocket-chat/src/main.rs @@ -12,7 +12,7 @@ extern crate tokio_io; extern crate actix; extern crate actix_web; -use std::time::{Instant, Duration}; +use std::time::{Duration, Instant}; use actix::*; use actix_web::server::HttpServer; @@ -185,7 +185,7 @@ impl StreamHandler for WsChatSession { ws::Message::Binary(bin) => println!("Unexpected binary"), ws::Message::Close(_) => { ctx.stop(); - }, + } } } } @@ -202,9 +202,7 @@ impl WsChatSession { println!("Websocket Client heartbeat failed, disconnecting!"); // notify chat server - ctx.state() - .addr - .do_send(server::Disconnect { id: act.id }); + ctx.state().addr.do_send(server::Disconnect { id: act.id }); // stop actor ctx.stop(); @@ -233,19 +231,22 @@ fn main() { }; App::with_state(state) - // redirect to websocket.html - .resource("/", |r| r.method(http::Method::GET).f(|_| { - HttpResponse::Found() - .header("LOCATION", "/static/websocket.html") - .finish() - })) - // websocket + // redirect to websocket.html + .resource("/", |r| { + r.method(http::Method::GET).f(|_| { + HttpResponse::Found() + .header("LOCATION", "/static/websocket.html") + .finish() + }) + }) + // websocket .resource("/ws/", |r| r.route().f(chat_route)) - // static resources + // static resources .handler("/static/", fs::StaticFiles::new("static/").unwrap()) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + }) + .bind("127.0.0.1:8080") + .unwrap() + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/websocket-tcp-chat/src/codec.rs b/websocket-tcp-chat/src/codec.rs index 55cf0db3..8d362630 100644 --- a/websocket-tcp-chat/src/codec.rs +++ b/websocket-tcp-chat/src/codec.rs @@ -65,7 +65,9 @@ impl Encoder for ChatCodec { type Error = io::Error; fn encode( - &mut self, msg: ChatResponse, dst: &mut BytesMut, + &mut self, + msg: ChatResponse, + dst: &mut BytesMut, ) -> Result<(), Self::Error> { let msg = json::to_string(&msg).unwrap(); let msg_ref: &[u8] = msg.as_ref(); @@ -108,7 +110,9 @@ impl Encoder for ClientChatCodec { type Error = io::Error; fn encode( - &mut self, msg: ChatRequest, dst: &mut BytesMut, + &mut self, + msg: ChatRequest, + dst: &mut BytesMut, ) -> Result<(), Self::Error> { let msg = json::to_string(&msg).unwrap(); let msg_ref: &[u8] = msg.as_ref(); diff --git a/websocket-tcp-chat/src/main.rs b/websocket-tcp-chat/src/main.rs index 099ba8d4..dff734c8 100644 --- a/websocket-tcp-chat/src/main.rs +++ b/websocket-tcp-chat/src/main.rs @@ -19,7 +19,7 @@ extern crate actix_web; use actix::*; use actix_web::server::HttpServer; use actix_web::{fs, http, ws, App, Error, HttpRequest, HttpResponse}; -use std::time::{Instant, Duration}; +use std::time::{Duration, Instant}; mod codec; mod server; @@ -191,7 +191,7 @@ impl StreamHandler for WsChatSession { ws::Message::Binary(bin) => println!("Unexpected binary"), ws::Message::Close(_) => { ctx.stop(); - }, + } } } } @@ -208,9 +208,7 @@ impl WsChatSession { println!("Websocket Client heartbeat failed, disconnecting!"); // notify chat server - ctx.state() - .addr - .do_send(server::Disconnect { id: act.id }); + ctx.state().addr.do_send(server::Disconnect { id: act.id }); // stop actor ctx.stop(); @@ -247,18 +245,21 @@ fn main() { App::with_state(state) // redirect to websocket.html - .resource("/", |r| r.method(http::Method::GET).f(|_| { - HttpResponse::Found() - .header("LOCATION", "/static/websocket.html") - .finish() - })) + .resource("/", |r| { + r.method(http::Method::GET).f(|_| { + HttpResponse::Found() + .header("LOCATION", "/static/websocket.html") + .finish() + }) + }) // websocket .resource("/ws/", |r| r.route().f(chat_route)) // static resources .handler("/static/", fs::StaticFiles::new("static/").unwrap()) - }).bind("127.0.0.1:8080") - .unwrap() - .start(); + }) + .bind("127.0.0.1:8080") + .unwrap() + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); diff --git a/websocket/src/main.rs b/websocket/src/main.rs index 84aa4646..0b9a5716 100644 --- a/websocket/src/main.rs +++ b/websocket/src/main.rs @@ -8,7 +8,7 @@ extern crate actix; extern crate actix_web; extern crate env_logger; -use std::time::{Instant, Duration}; +use std::time::{Duration, Instant}; use actix::prelude::*; use actix_web::{ @@ -96,19 +96,24 @@ fn main() { env_logger::init(); let sys = actix::System::new("ws-example"); - server::new( - || App::new() + server::new(|| { + App::new() // enable logger .middleware(middleware::Logger::default()) // websocket route .resource("/ws/", |r| r.method(http::Method::GET).f(ws_index)) // static files - .handler("/", fs::StaticFiles::new("static/") - .unwrap() - .index_file("index.html"))) - // start http server on 127.0.0.1:8080 - .bind("127.0.0.1:8080").unwrap() - .start(); + .handler( + "/", + fs::StaticFiles::new("static/") + .unwrap() + .index_file("index.html"), + ) + }) + // start http server on 127.0.0.1:8080 + .bind("127.0.0.1:8080") + .unwrap() + .start(); println!("Started http server: 127.0.0.1:8080"); let _ = sys.run(); From b6929b47b125df85ec77b121d00c48bb38c92e54 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 9 Mar 2019 21:08:08 -0800 Subject: [PATCH 12/23] post cookie-auth and form examples --- cookie-auth/Cargo.toml | 7 ++-- cookie-auth/src/main.rs | 41 +++++++++------------- form/Cargo.toml | 5 +-- form/src/main.rs | 76 ++++++++++++++++------------------------- 4 files changed, 52 insertions(+), 77 deletions(-) diff --git a/cookie-auth/Cargo.toml b/cookie-auth/Cargo.toml index 2e7858d3..81fd8eb9 100644 --- a/cookie-auth/Cargo.toml +++ b/cookie-auth/Cargo.toml @@ -2,8 +2,9 @@ name = "cookie-auth" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +edition = "2018" +workspace = ".." [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git" } -env_logger = "0.5" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +env_logger = "0.6" diff --git a/cookie-auth/src/main.rs b/cookie-auth/src/main.rs index 82db1da3..01ddde23 100644 --- a/cookie-auth/src/main.rs +++ b/cookie-auth/src/main.rs @@ -1,31 +1,26 @@ -extern crate actix; -extern crate actix_web; -extern crate env_logger; - -use actix_web::middleware::identity::RequestIdentity; +use actix_web::middleware::identity::Identity; use actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService}; -use actix_web::{middleware, server, App, HttpRequest, HttpResponse}; +use actix_web::{middleware, web, App, HttpResponse, HttpServer}; -fn index(req: &HttpRequest) -> String { - format!("Hello {}", req.identity().unwrap_or("Anonymous".to_owned())) +fn index(id: Identity) -> String { + format!("Hello {}", id.identity().unwrap_or("Anonymous".to_owned())) } -fn login(req: &HttpRequest) -> HttpResponse { - req.remember("user1".to_owned()); +fn login(id: Identity) -> HttpResponse { + id.remember("user1".to_owned()); HttpResponse::Found().header("location", "/").finish() } -fn logout(req: &HttpRequest) -> HttpResponse { - req.forget(); +fn logout(id: Identity) -> HttpResponse { + id.forget(); HttpResponse::Found().header("location", "/").finish() } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("cookie-auth"); - server::new(|| { + HttpServer::new(|| { App::new() .middleware(middleware::Logger::default()) .middleware(IdentityService::new( @@ -33,14 +28,10 @@ fn main() { .name("auth-example") .secure(false), )) - .resource("/login", |r| r.f(login)) - .resource("/logout", |r| r.f(logout)) - .resource("/", |r| r.f(index)) + .service(web::resource("/login").route(web::post().to(login))) + .service(web::resource("/logout").to(logout)) + .service(web::resource("/").route(web::get().to(index))) }) - .bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } diff --git a/form/Cargo.toml b/form/Cargo.toml index 42c314ff..1fd56d4e 100644 --- a/form/Cargo.toml +++ b/form/Cargo.toml @@ -2,10 +2,11 @@ name = "form-example" version = "0.1.0" authors = ["Gorm Casper "] +edition = "2018" +workspace = ".." [dependencies] -actix = "0.7" -actix-web = "0.7" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } serde = "1.0" serde_derive = "1.0" diff --git a/form/src/main.rs b/form/src/main.rs index 01f416fb..c0c38690 100644 --- a/form/src/main.rs +++ b/form/src/main.rs @@ -1,48 +1,32 @@ -extern crate actix; -extern crate actix_web; - #[macro_use] extern crate serde_derive; use actix_web::{ - http, middleware, server, App, Form, HttpRequest, HttpResponse, Result, State, + middleware, web, App, HttpRequest, HttpResponse, HttpServer, Responder, Result, }; struct AppState { foo: String, } -fn main() { - let sys = actix::System::new("form-example"); - - let _addr = server::new(|| { - App::with_state(AppState { - foo: "bar".to_string(), - }) - .middleware(middleware::Logger::default()) - .resource("/", |r| { - r.method(http::Method::GET).with(index); - }) - .resource("/post1", |r| { - r.method(http::Method::POST).with(handle_post_1) - }) - .resource("/post2", |r| { - r.method(http::Method::POST).with(handle_post_2) - }) - .resource("/post3", |r| { - r.method(http::Method::POST).with(handle_post_3) - }) +fn main() -> std::io::Result<()> { + HttpServer::new(|| { + App::new() + .state(AppState { + foo: "bar".to_string(), + }) + .middleware(middleware::Logger::default()) + .service(web::resource("/").route(web::get().to(index))) + .service(web::resource("/post1").route(web::post().to(handle_post_1))) + .service(web::resource("/post2").route(web::post().to(handle_post_2))) + .service(web::resource("/post3").route(web::post().to(handle_post_3))) }) - .bind("127.0.0.1:8080") - .expect("Can not bind to 127.0.0.1:8080") - .start(); - - println!("Starting http server: 127.0.0.1:8080"); - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } -fn index(_req: HttpRequest) -> Result { - Ok(HttpResponse::build(http::StatusCode::OK) +fn index() -> Result { + Ok(HttpResponse::Ok() .content_type("text/html; charset=utf-8") .body(include_str!("../static/form.html"))) } @@ -53,30 +37,28 @@ pub struct MyParams { } /// Simple handle POST request -fn handle_post_1(params: Form) -> Result { - Ok(HttpResponse::build(http::StatusCode::OK) +fn handle_post_1(params: web::Form) -> Result { + Ok(HttpResponse::Ok() .content_type("text/plain") .body(format!("Your name is {}", params.name))) } /// State and POST Params fn handle_post_2( - (state, params): (State, Form), -) -> Result { - Ok(HttpResponse::build(http::StatusCode::OK) - .content_type("text/plain") - .body(format!( - "Your name is {}, and in AppState I have foo: {}", - params.name, state.foo - ))) + state: web::State, + params: web::Form, +) -> HttpResponse { + HttpResponse::Ok().content_type("text/plain").body(format!( + "Your name is {}, and in AppState I have foo: {}", + params.name, state.foo + )) } /// Request and POST Params -fn handle_post_3( - (req, params): (HttpRequest, Form), -) -> Result { +fn handle_post_3(req: HttpRequest, params: web::Form) -> impl Responder { println!("Handling POST request: {:?}", req); - Ok(HttpResponse::build(http::StatusCode::OK) + + HttpResponse::Ok() .content_type("text/plain") - .body(format!("Your name is {}", params.name))) + .body(format!("Your name is {}", params.name)) } From 52c12f264a24c905ab9699590c225347f3e2a57d Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 9 Mar 2019 22:38:15 -0800 Subject: [PATCH 13/23] port more examples --- hello-world/Cargo.toml | 9 +++---- hello-world/src/main.rs | 28 +++++++------------- rustfmt.toml | 3 --- static_index/Cargo.toml | 7 ++--- static_index/src/main.rs | 32 +++++++---------------- template_askama/Cargo.toml | 9 +++---- template_askama/src/main.rs | 22 +++++----------- template_tera/Cargo.toml | 8 +++--- template_tera/src/main.rs | 52 +++++++++++++------------------------ 9 files changed, 61 insertions(+), 109 deletions(-) diff --git a/hello-world/Cargo.toml b/hello-world/Cargo.toml index 7126813c..cb47b1e0 100644 --- a/hello-world/Cargo.toml +++ b/hello-world/Cargo.toml @@ -2,10 +2,9 @@ name = "hello-world" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [dependencies] -env_logger = "0.5" - -actix = "0.7" -actix-web = "^0.7" +env_logger = "0.6" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } diff --git a/hello-world/src/main.rs b/hello-world/src/main.rs index 2d787836..3bb9064a 100644 --- a/hello-world/src/main.rs +++ b/hello-world/src/main.rs @@ -1,29 +1,21 @@ -extern crate actix; -extern crate actix_web; -extern crate env_logger; +use actix_web::{middleware, web, App, HttpRequest, HttpServer}; -use actix_web::{middleware, server, App, HttpRequest}; - -fn index(_req: &HttpRequest) -> &'static str { +fn index(req: HttpRequest) -> &'static str { + println!("REQ: {:?}", req); "Hello world!" } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("hello-world"); - server::new(|| { + HttpServer::new(|| { App::new() // enable logger .middleware(middleware::Logger::default()) - .resource("/index.html", |r| r.f(|_| "Hello world!")) - .resource("/", |r| r.f(index)) + .service(web::resource("/index.html").to(|| "Hello world!")) + .service(web::resource("/").to(index)) }) - .bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } diff --git a/rustfmt.toml b/rustfmt.toml index 4fff285e..94bd11d5 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,5 +1,2 @@ max_width = 89 reorder_imports = true -#wrap_comments = true -fn_args_density = "Compressed" -#use_small_heuristics = false diff --git a/static_index/Cargo.toml b/static_index/Cargo.toml index 6f427322..ee3d5377 100644 --- a/static_index/Cargo.toml +++ b/static_index/Cargo.toml @@ -2,11 +2,12 @@ name = "static_index" version = "0.1.0" authors = ["Jose Marinez "] -workspace = "../" +workspace = ".." +edition = "2018" [dependencies] futures = "0.1" env_logger = "0.5" -actix = "0.7" -actix-web = "0.7" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-files = { git="https://github.com/actix/actix-web.git", branch = "1.0" } diff --git a/static_index/src/main.rs b/static_index/src/main.rs index df6233dc..e4c4fa83 100644 --- a/static_index/src/main.rs +++ b/static_index/src/main.rs @@ -1,31 +1,19 @@ -extern crate actix; -extern crate actix_web; -extern crate env_logger; +use actix_files as fs; +use actix_web::{middleware, App, HttpServer}; -use actix_web::{fs, middleware, server, App}; - -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); - ::std::env::set_var("RUST_BACKTRACE", "1"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("static_index"); - - server::new(|| { + HttpServer::new(|| { App::new() // enable logger .middleware(middleware::Logger::default()) - .handler( - "/", - fs::StaticFiles::new("./static/") - .unwrap() - .index_file("index.html"), + .service( + // static files + fs::Files::new("/", "./static/").index_file("index.html"), ) }) - .bind("127.0.0.1:8080") - .expect("Can not start server on given IP/Port") - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } diff --git a/template_askama/Cargo.toml b/template_askama/Cargo.toml index 5eba342c..d3297425 100644 --- a/template_askama/Cargo.toml +++ b/template_askama/Cargo.toml @@ -2,14 +2,13 @@ name = "template-askama" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [dependencies] -env_logger = "0.5" +env_logger = "0.6" askama = "0.6" - -actix = "0.7" -actix-web = "0.7" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } [build-dependencies] askama = "0.6" diff --git a/template_askama/src/main.rs b/template_askama/src/main.rs index 27dc7617..b27e94af 100644 --- a/template_askama/src/main.rs +++ b/template_askama/src/main.rs @@ -1,11 +1,9 @@ -extern crate actix; -extern crate actix_web; #[macro_use] extern crate askama; use std::collections::HashMap; -use actix_web::{http, server, App, HttpResponse, Query, Result}; +use actix_web::{web, App, HttpResponse, HttpServer, Result}; use askama::Template; #[derive(Template)] @@ -19,7 +17,7 @@ struct UserTemplate<'a> { #[template(path = "index.html")] struct Index; -fn index(query: Query>) -> Result { +fn index(query: web::Query>) -> Result { let s = if let Some(name) = query.get("name") { UserTemplate { name: name, @@ -33,17 +31,11 @@ fn index(query: Query>) -> Result { Ok(HttpResponse::Ok().content_type("text/html").body(s)) } -fn main() { - let sys = actix::System::new("template-askama"); - +fn main() -> std::io::Result<()> { // start http server - server::new(move || { - App::new().resource("/", |r| r.method(http::Method::GET).with(index)) + HttpServer::new(move || { + App::new().service(web::resource("/").route(web::get()).to(index)) }) - .bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } diff --git a/template_tera/Cargo.toml b/template_tera/Cargo.toml index 9e55bf4a..2c01582d 100644 --- a/template_tera/Cargo.toml +++ b/template_tera/Cargo.toml @@ -2,10 +2,10 @@ name = "template-tera" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [dependencies] -env_logger = "0.5" +env_logger = "0.6" tera = "*" -actix = "0.7" -actix-web = "0.7" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } diff --git a/template_tera/src/main.rs b/template_tera/src/main.rs index 7cbd5579..b442e82a 100644 --- a/template_tera/src/main.rs +++ b/template_tera/src/main.rs @@ -1,58 +1,42 @@ -extern crate actix; -extern crate actix_web; -extern crate env_logger; #[macro_use] extern crate tera; use std::collections::HashMap; -use actix_web::{ - error, http, middleware, server, App, Error, HttpResponse, Query, State, -}; - -struct AppState { - template: tera::Tera, // <- store tera template in application state -} +use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer}; +// store tera template in application state fn index( - (state, query): (State, Query>), + tmpl: web::State, + query: web::Query>, ) -> Result { let s = if let Some(name) = query.get("name") { - // <- submitted form + // submitted form let mut ctx = tera::Context::new(); - ctx.add("name", &name.to_owned()); - ctx.add("text", &"Welcome!".to_owned()); - state - .template - .render("user.html", &ctx) + ctx.insert("name", &name.to_owned()); + ctx.insert("text", &"Welcome!".to_owned()); + tmpl.render("user.html", &ctx) .map_err(|_| error::ErrorInternalServerError("Template error"))? } else { - state - .template - .render("index.html", &tera::Context::new()) + tmpl.render("index.html", &tera::Context::new()) .map_err(|_| error::ErrorInternalServerError("Template error"))? }; Ok(HttpResponse::Ok().content_type("text/html").body(s)) } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("tera-example"); - server::new(|| { + HttpServer::new(|| { let tera = compile_templates!(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")); - App::with_state(AppState { template: tera }) - // enable logger - .middleware(middleware::Logger::default()) - .resource("/", |r| r.method(http::Method::GET).with(index)) + App::new() + .state(tera) + .middleware(middleware::Logger::default()) // enable logger + .service(web::resource("/").route(web::get().to(index))) }) - .bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } From 17744bbfe4dd3f9df42fcbd6fdbc38ed8e99b757 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 10 Mar 2019 18:23:44 -0700 Subject: [PATCH 14/23] upgrade actix_todo --- actix_todo/Cargo.toml | 7 +- actix_todo/src/api.rs | 184 ++++++++++++++++++-------------------- actix_todo/src/db.rs | 97 ++++---------------- actix_todo/src/main.rs | 56 ++++-------- actix_todo/src/model.rs | 2 +- actix_todo/src/session.rs | 15 ++-- 6 files changed, 137 insertions(+), 224 deletions(-) diff --git a/actix_todo/Cargo.toml b/actix_todo/Cargo.toml index eb17097e..09b9a010 100644 --- a/actix_todo/Cargo.toml +++ b/actix_todo/Cargo.toml @@ -2,10 +2,13 @@ authors = ["Dan Munckton "] name = "actix-todo" version = "0.1.0" +workspace = ".." +edition = "2018" [dependencies] -actix = "0.7.3" -actix-web = "0.7.4" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-files = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } dotenv = "0.13.0" env_logger = "0.5.10" futures = "0.1.22" diff --git a/actix_todo/src/api.rs b/actix_todo/src/api.rs index 73c58e30..069e5db8 100644 --- a/actix_todo/src/api.rs +++ b/actix_todo/src/api.rs @@ -1,42 +1,34 @@ -use actix::prelude::Addr; -use actix_web::middleware::Response; -use actix_web::{ - error, fs::NamedFile, http, AsyncResponder, Form, FutureResponse, HttpRequest, - HttpResponse, Path, Responder, Result, -}; -use futures::{future, Future}; +use actix_files::NamedFile; +use actix_session::Session; +use actix_web::middleware::ErrorHandlerResponse; +use actix_web::{dev, error, http, web, Error, HttpResponse, Responder, Result}; +use futures::future::{err, Either, Future, IntoFuture}; use tera::{Context, Tera}; -use db::{AllTasks, CreateTask, DbExecutor, DeleteTask, ToggleTask}; -use session::{self, FlashMessage}; +use crate::db; +use crate::session::{self, FlashMessage}; -pub struct AppState { - pub template: Tera, - pub db: Addr, -} - -pub fn index(req: HttpRequest) -> FutureResponse { - req.state() - .db - .send(AllTasks) +pub fn index( + pool: web::State, + tmpl: web::State, + session: Session, +) -> impl Future { + web::block(move || db::get_all_tasks(&pool)) .from_err() - .and_then(move |res| match res { + .then(move |res| match res { Ok(tasks) => { let mut context = Context::new(); - context.add("tasks", &tasks); + context.insert("tasks", &tasks); //Session is set during operations on other endpoints //that can redirect to index - if let Some(flash) = session::get_flash(&req)? { - context.add("msg", &(flash.kind, flash.message)); - session::clear_flash(&req); + if let Some(flash) = session::get_flash(&session)? { + context.insert("msg", &(flash.kind, flash.message)); + session::clear_flash(&session); } - let rendered = req - .state() - .template - .render("index.html.tera", &context) - .map_err(|e| { + let rendered = + tmpl.render("index.html.tera", &context).map_err(|e| { error::ErrorInternalServerError(e.description().to_owned()) })?; @@ -44,7 +36,6 @@ pub fn index(req: HttpRequest) -> FutureResponse { } Err(e) => Err(e), }) - .responder() } #[derive(Deserialize)] @@ -53,35 +44,34 @@ pub struct CreateForm { } pub fn create( - (req, params): (HttpRequest, Form), -) -> FutureResponse { + params: web::Form, + pool: web::State, + session: Session, +) -> impl Future { if params.description.is_empty() { - future::lazy(move || { + Either::A( session::set_flash( - &req, + &session, FlashMessage::error("Description cannot be empty"), - )?; - Ok(redirect_to("/")) - }) - .responder() + ) + .map(|_| redirect_to("/")) + .into_future(), + ) } else { - req.state() - .db - .send(CreateTask { - description: params.description.clone(), - }) - .from_err() - .and_then(move |res| match res { - Ok(_) => { - session::set_flash( - &req, - FlashMessage::success("Task successfully added"), - )?; - Ok(redirect_to("/")) - } - Err(e) => Err(e), - }) - .responder() + Either::B( + web::block(move || db::create_task(params.into_inner().description, &pool)) + .from_err() + .then(move |res| match res { + Ok(_) => { + session::set_flash( + &session, + FlashMessage::success("Task successfully added"), + )?; + Ok(redirect_to("/")) + } + Err(e) => Err(e), + }), + ) } } @@ -96,49 +86,50 @@ pub struct UpdateForm { } pub fn update( - (req, params, form): (HttpRequest, Path, Form), -) -> FutureResponse { + db: web::State, + params: web::Path, + form: web::Form, + session: Session, +) -> impl Future { match form._method.as_ref() { - "put" => toggle(req, params), - "delete" => delete(req, params), + "put" => Either::A(Either::A(toggle(db, params))), + "delete" => Either::A(Either::B(delete(db, params, session))), unsupported_method => { let msg = format!("Unsupported HTTP method: {}", unsupported_method); - future::err(error::ErrorBadRequest(msg)).responder() + Either::B(err(error::ErrorBadRequest(msg))) } } } fn toggle( - req: HttpRequest, - params: Path, -) -> FutureResponse { - req.state() - .db - .send(ToggleTask { id: params.id }) + pool: web::State, + params: web::Path, +) -> impl Future { + web::block(move || db::toggle_task(params.id, &pool)) .from_err() - .and_then(move |res| match res { + .then(move |res| match res { Ok(_) => Ok(redirect_to("/")), Err(e) => Err(e), }) - .responder() } fn delete( - req: HttpRequest, - params: Path, -) -> FutureResponse { - req.state() - .db - .send(DeleteTask { id: params.id }) + pool: web::State, + params: web::Path, + session: Session, +) -> impl Future { + web::block(move || db::delete_task(params.id, &pool)) .from_err() - .and_then(move |res| match res { + .then(move |res| match res { Ok(_) => { - session::set_flash(&req, FlashMessage::success("Task was deleted."))?; + session::set_flash( + &session, + FlashMessage::success("Task was deleted."), + )?; Ok(redirect_to("/")) } Err(e) => Err(e), }) - .responder() } fn redirect_to(location: &str) -> HttpResponse { @@ -147,32 +138,31 @@ fn redirect_to(location: &str) -> HttpResponse { .finish() } -pub fn bad_request( - req: &HttpRequest, - resp: HttpResponse, -) -> Result { +pub fn bad_request(res: dev::ServiceResponse) -> Result> { let new_resp = NamedFile::open("static/errors/400.html")? - .set_status_code(resp.status()) - .respond_to(req)?; - Ok(Response::Done(new_resp)) + .set_status_code(res.status()) + .respond_to(res.request())?; + Ok(ErrorHandlerResponse::Response( + res.into_response(new_resp.into_body()), + )) } -pub fn not_found( - req: &HttpRequest, - resp: HttpResponse, -) -> Result { +pub fn not_found(res: dev::ServiceResponse) -> Result> { let new_resp = NamedFile::open("static/errors/404.html")? - .set_status_code(resp.status()) - .respond_to(req)?; - Ok(Response::Done(new_resp)) + .set_status_code(res.status()) + .respond_to(res.request())?; + Ok(ErrorHandlerResponse::Response( + res.into_response(new_resp.into_body()), + )) } -pub fn internal_server_error( - req: &HttpRequest, - resp: HttpResponse, -) -> Result { +pub fn internal_server_error( + res: dev::ServiceResponse, +) -> Result> { let new_resp = NamedFile::open("static/errors/500.html")? - .set_status_code(resp.status()) - .respond_to(req)?; - Ok(Response::Done(new_resp)) + .set_status_code(res.status()) + .respond_to(res.request())?; + Ok(ErrorHandlerResponse::Response( + res.into_response(new_resp.into_body()), + )) } diff --git a/actix_todo/src/db.rs b/actix_todo/src/db.rs index 534ae648..579b0b5d 100644 --- a/actix_todo/src/db.rs +++ b/actix_todo/src/db.rs @@ -1,13 +1,11 @@ use std::ops::Deref; -use actix::prelude::{Actor, Handler, Message, SyncContext}; -use actix_web::{error, Error}; use diesel::pg::PgConnection; use diesel::r2d2::{ConnectionManager, Pool, PoolError, PooledConnection}; -use model::{NewTask, Task}; +use crate::model::{NewTask, Task}; -type PgPool = Pool>; +pub type PgPool = Pool>; type PgPooledConnection = PooledConnection>; pub fn init_pool(database_url: &str) -> Result { @@ -15,86 +13,29 @@ pub fn init_pool(database_url: &str) -> Result { Pool::builder().build(manager) } -pub struct DbExecutor(pub PgPool); - -impl DbExecutor { - pub fn get_conn(&self) -> Result { - self.0.get().map_err(|e| error::ErrorInternalServerError(e)) - } +fn get_conn(pool: &PgPool) -> Result { + pool.get().map_err(|_| "can get connection") } -impl Actor for DbExecutor { - type Context = SyncContext; +pub fn get_all_tasks(pool: &PgPool) -> Result, &'static str> { + Task::all(get_conn(pool)?.deref()).map_err(|_| "Error inserting task") } -pub struct AllTasks; - -impl Message for AllTasks { - type Result = Result, Error>; +pub fn create_task(todo: String, pool: &PgPool) -> Result<(), &'static str> { + let new_task = NewTask { description: todo }; + Task::insert(new_task, get_conn(pool)?.deref()) + .map(|_| ()) + .map_err(|_| "Error inserting task") } -impl Handler for DbExecutor { - type Result = Result, Error>; - - fn handle(&mut self, _: AllTasks, _: &mut Self::Context) -> Self::Result { - Task::all(self.get_conn()?.deref()) - .map_err(|_| error::ErrorInternalServerError("Error inserting task")) - } +pub fn toggle_task(id: i32, pool: &PgPool) -> Result<(), &'static str> { + Task::toggle_with_id(id, get_conn(pool)?.deref()) + .map(|_| ()) + .map_err(|_| "Error inserting task") } -pub struct CreateTask { - pub description: String, -} - -impl Message for CreateTask { - type Result = Result<(), Error>; -} - -impl Handler for DbExecutor { - type Result = Result<(), Error>; - - fn handle(&mut self, todo: CreateTask, _: &mut Self::Context) -> Self::Result { - let new_task = NewTask { - description: todo.description, - }; - Task::insert(new_task, self.get_conn()?.deref()) - .map(|_| ()) - .map_err(|_| error::ErrorInternalServerError("Error inserting task")) - } -} - -pub struct ToggleTask { - pub id: i32, -} - -impl Message for ToggleTask { - type Result = Result<(), Error>; -} - -impl Handler for DbExecutor { - type Result = Result<(), Error>; - - fn handle(&mut self, task: ToggleTask, _: &mut Self::Context) -> Self::Result { - Task::toggle_with_id(task.id, self.get_conn()?.deref()) - .map(|_| ()) - .map_err(|_| error::ErrorInternalServerError("Error inserting task")) - } -} - -pub struct DeleteTask { - pub id: i32, -} - -impl Message for DeleteTask { - type Result = Result<(), Error>; -} - -impl Handler for DbExecutor { - type Result = Result<(), Error>; - - fn handle(&mut self, task: DeleteTask, _: &mut Self::Context) -> Self::Result { - Task::delete_with_id(task.id, self.get_conn()?.deref()) - .map(|_| ()) - .map_err(|_| error::ErrorInternalServerError("Error inserting task")) - } +pub fn delete_task(id: i32, pool: &PgPool) -> Result<(), &'static str> { + Task::delete_with_id(id, get_conn(pool)?.deref()) + .map(|_| ()) + .map_err(|_| "Error inserting task") } diff --git a/actix_todo/src/main.rs b/actix_todo/src/main.rs index f2de26af..9c9664aa 100644 --- a/actix_todo/src/main.rs +++ b/actix_todo/src/main.rs @@ -1,8 +1,3 @@ -extern crate actix; -extern crate actix_web; -extern crate dotenv; -extern crate env_logger; -extern crate futures; #[macro_use] extern crate diesel; #[macro_use] @@ -12,12 +7,13 @@ extern crate serde_derive; #[macro_use] extern crate tera; -use actix::prelude::SyncArbiter; -use actix_web::middleware::session::{CookieSessionBackend, SessionStorage}; +use std::{env, io}; + +use actix_files as fs; +use actix_session::CookieSession; use actix_web::middleware::{ErrorHandlers, Logger}; -use actix_web::{dev::Resource, fs, http, server, App}; +use actix_web::{http, web, App, HttpServer}; use dotenv::dotenv; -use std::env; use tera::Tera; mod api; @@ -27,29 +23,22 @@ mod schema; mod session; static SESSION_SIGNING_KEY: &[u8] = &[0; 32]; -const NUM_DB_THREADS: usize = 3; -fn main() { +fn main() -> io::Result<()> { dotenv().ok(); - std::env::set_var("RUST_LOG", "actix_todo=debug,actix_web=info"); + env::set_var("RUST_LOG", "actix_todo=debug,actix_web=info"); env_logger::init(); - // Start the Actix system - let system = actix::System::new("todo-app"); - let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); let pool = db::init_pool(&database_url).expect("Failed to create pool"); - let addr = SyncArbiter::start(NUM_DB_THREADS, move || db::DbExecutor(pool.clone())); let app = move || { debug!("Constructing the App"); let templates: Tera = compile_templates!("templates/**/*"); - let session_store = SessionStorage::new( - CookieSessionBackend::signed(SESSION_SIGNING_KEY).secure(false), - ); + let session_store = CookieSession::signed(SESSION_SIGNING_KEY).secure(false); let error_handlers = ErrorHandlers::new() .handler( @@ -59,29 +48,20 @@ fn main() { .handler(http::StatusCode::BAD_REQUEST, api::bad_request) .handler(http::StatusCode::NOT_FOUND, api::not_found); - let static_files = fs::StaticFiles::new("static/") - .expect("failed constructing static files handler"); - - let state = api::AppState { - template: templates, - db: addr.clone(), - }; - - App::with_state(state) + App::new() + .state(templates) + .state(pool.clone()) .middleware(Logger::default()) .middleware(session_store) .middleware(error_handlers) - .route("/", http::Method::GET, api::index) - .route("/todo", http::Method::POST, api::create) - .resource("/todo/{id}", |r: &mut Resource<_>| { - r.post().with(api::update) - }) - .handler("/static", static_files) + .service(web::resource("/").route(web::get().to_async(api::index))) + .service(web::resource("/todo").route(web::post().to_async(api::create))) + .service( + web::resource("/todo/{id}").route(web::post().to_async(api::update)), + ) + .service(fs::Files::new("/static", "static/")) }; debug!("Starting server"); - server::new(app).bind("localhost:8088").unwrap().start(); - - // Run actix system, this method actually starts all async processes - let _ = system.run(); + HttpServer::new(app).bind("localhost:8088")?.run() } diff --git a/actix_todo/src/model.rs b/actix_todo/src/model.rs index 60eb551c..4b80f4a8 100644 --- a/actix_todo/src/model.rs +++ b/actix_todo/src/model.rs @@ -2,7 +2,7 @@ use diesel; use diesel::pg::PgConnection; use diesel::prelude::*; -use schema::{ +use crate::schema::{ tasks, tasks::dsl::{completed as task_completed, tasks as all_tasks}, }; diff --git a/actix_todo/src/session.rs b/actix_todo/src/session.rs index c4c6aadb..d1cfc7a4 100644 --- a/actix_todo/src/session.rs +++ b/actix_todo/src/session.rs @@ -1,19 +1,18 @@ +use actix_session::Session; use actix_web::error::Result; -use actix_web::middleware::session::RequestSession; -use actix_web::HttpRequest; const FLASH_KEY: &str = "flash"; -pub fn set_flash(request: &HttpRequest, flash: FlashMessage) -> Result<()> { - request.session().set(FLASH_KEY, flash) +pub fn set_flash(session: &Session, flash: FlashMessage) -> Result<()> { + session.set(FLASH_KEY, flash) } -pub fn get_flash(req: &HttpRequest) -> Result> { - req.session().get::(FLASH_KEY) +pub fn get_flash(session: &Session) -> Result> { + session.get::(FLASH_KEY) } -pub fn clear_flash(req: &HttpRequest) { - req.session().remove(FLASH_KEY); +pub fn clear_flash(session: &Session) { + session.remove(FLASH_KEY); } #[derive(Deserialize, Serialize)] From 0b46125f5d21b0467300348fed7bc82d0e4dc577 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 10 Mar 2019 18:39:54 -0700 Subject: [PATCH 15/23] use new location for blocking --- async_db/src/db.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/async_db/src/db.rs b/async_db/src/db.rs index 9b700237..e23adba2 100644 --- a/async_db/src/db.rs +++ b/async_db/src/db.rs @@ -1,4 +1,4 @@ -use actix_web::{blocking, Error as AWError}; +use actix_web::{web, Error as AWError}; use failure::Error; use futures::Future; use r2d2; @@ -27,7 +27,7 @@ pub fn execute( query: Queries, ) -> impl Future, Error = AWError> { let pool = pool.clone(); - blocking::run(move || match query { + web::block(move || match query { Queries::GetTopTenHottestYears => get_hottest_years(pool.get()?), Queries::GetTopTenColdestYears => get_coldest_years(pool.get()?), Queries::GetTopTenHottestMonths => get_hottest_months(pool.get()?), From 14eed91fcd73aa65247e145ed394d86989a93ee3 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 10 Mar 2019 19:19:50 -0700 Subject: [PATCH 16/23] update juniper and middleware examples --- basics/src/main.rs | 1 - juniper/Cargo.toml | 11 ++-- juniper/src/main.rs | 115 +++++++++++-------------------------- middleware/Cargo.toml | 8 ++- middleware/src/main.rs | 37 ++++++------ middleware/src/redirect.rs | 74 ++++++++++++++++++------ middleware/src/simple.rs | 76 ++++++++++++++++++------ 7 files changed, 170 insertions(+), 152 deletions(-) diff --git a/basics/src/main.rs b/basics/src/main.rs index 55f25bb0..58eae45c 100644 --- a/basics/src/main.rs +++ b/basics/src/main.rs @@ -77,7 +77,6 @@ fn with_param(req: HttpRequest, path: web::Path<(String,)>) -> HttpResponse { fn main() -> io::Result<()> { env::set_var("RUST_LOG", "actix_web=debug"); - env::set_var("RUST_BACKTRACE", "1"); env_logger::init(); let sys = actix_rt::System::new("basic-example"); diff --git a/juniper/Cargo.toml b/juniper/Cargo.toml index d19b3527..e1295d2f 100644 --- a/juniper/Cargo.toml +++ b/juniper/Cargo.toml @@ -2,17 +2,14 @@ name = "juniper-example" version = "0.1.0" authors = ["pyros2097 "] -workspace = "../" +workspace = ".." +edition = "2018" [dependencies] -env_logger = "0.5" - -actix = "0.7" -actix-web = "0.7" - +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +env_logger = "0.6" futures = "0.1" serde = "1.0" serde_json = "1.0" serde_derive = "1.0" - juniper = "0.9.2" diff --git a/juniper/src/main.rs b/juniper/src/main.rs index 468c093a..34967eb1 100644 --- a/juniper/src/main.rs +++ b/juniper/src/main.rs @@ -1,110 +1,59 @@ //! Actix web juniper example //! //! A simple example integrating juniper in actix-web -extern crate serde; -extern crate serde_json; -#[macro_use] -extern crate serde_derive; +use std::io; +use std::sync::Arc; + #[macro_use] extern crate juniper; -extern crate actix; -extern crate actix_web; -extern crate env_logger; -extern crate futures; -use actix::prelude::*; -use actix_web::{ - http, middleware, server, App, AsyncResponder, Error, FutureResponse, HttpRequest, - HttpResponse, Json, State, -}; +use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer}; use futures::future::Future; use juniper::http::graphiql::graphiql_source; use juniper::http::GraphQLRequest; mod schema; -use schema::create_schema; -use schema::Schema; +use crate::schema::{create_schema, Schema}; -struct AppState { - executor: Addr, -} - -#[derive(Serialize, Deserialize)] -pub struct GraphQLData(GraphQLRequest); - -impl Message for GraphQLData { - type Result = Result; -} - -pub struct GraphQLExecutor { - schema: std::sync::Arc, -} - -impl GraphQLExecutor { - fn new(schema: std::sync::Arc) -> GraphQLExecutor { - GraphQLExecutor { schema: schema } - } -} - -impl Actor for GraphQLExecutor { - type Context = SyncContext; -} - -impl Handler for GraphQLExecutor { - type Result = Result; - - fn handle(&mut self, msg: GraphQLData, _: &mut Self::Context) -> Self::Result { - let res = msg.0.execute(&self.schema, &()); - let res_text = serde_json::to_string(&res)?; - Ok(res_text) - } -} - -fn graphiql(_req: &HttpRequest) -> Result { +fn graphiql() -> HttpResponse { let html = graphiql_source("http://127.0.0.1:8080/graphql"); - Ok(HttpResponse::Ok() + HttpResponse::Ok() .content_type("text/html; charset=utf-8") - .body(html)) + .body(html) } fn graphql( - (st, data): (State, Json), -) -> FutureResponse { - st.executor - .send(data.0) - .from_err() - .and_then(|res| match res { - Ok(user) => Ok(HttpResponse::Ok() - .content_type("application/json") - .body(user)), - Err(_) => Ok(HttpResponse::InternalServerError().into()), - }) - .responder() + st: web::State>, + data: web::Json, +) -> impl Future { + web::block(move || { + let res = data.execute(&st, &()); + Ok::<_, serde_json::error::Error>(serde_json::to_string(&res)?) + }) + .map_err(Error::from) + .and_then(|user| { + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(user)) + }) } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("juniper-example"); + // Create Juniper schema let schema = std::sync::Arc::new(create_schema()); - let addr = SyncArbiter::start(3, move || GraphQLExecutor::new(schema.clone())); // Start http server - server::new(move || { - App::with_state(AppState { - executor: addr.clone(), - }) - // enable logger - .middleware(middleware::Logger::default()) - .resource("/graphql", |r| r.method(http::Method::POST).with(graphql)) - .resource("/graphiql", |r| r.method(http::Method::GET).h(graphiql)) + HttpServer::new(move || { + App::new() + .state(schema.clone()) + .middleware(middleware::Logger::default()) + .service(web::resource("/graphql").route(web::post().to_async(graphql))) + .service(web::resource("/graphiql").route(web::get().to(graphiql))) }) - .bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } diff --git a/middleware/Cargo.toml b/middleware/Cargo.toml index b14354f4..2d533c8e 100644 --- a/middleware/Cargo.toml +++ b/middleware/Cargo.toml @@ -2,7 +2,11 @@ name = "middleware-example" version = "0.1.0" authors = ["Gorm Casper "] +edition = "2018" +workspace = ".." [dependencies] -actix = "0.7" -actix-web = "0.7" +actix-service = "0.3.3" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +futures = "0.1.25" +env_logger = "0.6" \ No newline at end of file diff --git a/middleware/src/main.rs b/middleware/src/main.rs index 91ae9d0c..6e1ec82e 100644 --- a/middleware/src/main.rs +++ b/middleware/src/main.rs @@ -1,32 +1,27 @@ -extern crate actix; -extern crate actix_web; - -use actix_web::{server, App}; +use actix_web::{web, App, HttpServer}; #[allow(dead_code)] mod redirect; #[allow(dead_code)] mod simple; -fn main() { - let sys = actix::System::new("middleware-example"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=debug"); + env_logger::init(); - let _addr = server::new(|| { + HttpServer::new(|| { App::new() + .middleware(redirect::CheckLogin) .middleware(simple::SayHi) - // .middleware(redirect::CheckLogin) - .resource("/login", |r| { - r.f(|_| { - "You are on /login. Go to src/redirect.rs to change this behavior." - }) - }) - .resource("/", |r| { - r.f(|_| "Hello, middleware! Check the console where the server is run.") - }) + .service(web::resource("/login").to(|| { + "You are on /login. Go to src/redirect.rs to change this behavior." + })) + .service( + web::resource("/").to(|| { + "Hello, middleware! Check the console where the server is run." + }), + ) }) - .bind("127.0.0.1:8080") - .unwrap() - .start(); - - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } diff --git a/middleware/src/redirect.rs b/middleware/src/redirect.rs index a0d5de6c..3ffd3a87 100644 --- a/middleware/src/redirect.rs +++ b/middleware/src/redirect.rs @@ -1,28 +1,64 @@ -extern crate actix_web; - -use actix_web::middleware::{Middleware, Started}; -use actix_web::{http, HttpRequest, HttpResponse, Result}; +use actix_service::{Service, Transform}; +use actix_web::dev::{ServiceRequest, ServiceResponse}; +use actix_web::{http, HttpResponse}; +use futures::future::{ok, Either, FutureResult}; +use futures::Poll; pub struct CheckLogin; -impl Middleware for CheckLogin { - // We only need to hook into the `start` for this middleware. - fn start(&self, req: &HttpRequest) -> Result { +impl Transform for CheckLogin +where + S: Service, Response = ServiceResponse>, + S::Future: 'static, +{ + type Request = ServiceRequest

; + type Response = ServiceResponse; + type Error = S::Error; + type InitError = (); + type Transform = CheckLoginMiddleware; + type Future = FutureResult; + + fn new_transform(&self, service: S) -> Self::Future { + ok(CheckLoginMiddleware { service }) + } +} +pub struct CheckLoginMiddleware { + service: S, +} + +impl Service for CheckLoginMiddleware +where + S: Service, Response = ServiceResponse>, + S::Future: 'static, +{ + type Request = ServiceRequest

; + type Response = ServiceResponse; + type Error = S::Error; + type Future = Either>; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + self.service.poll_ready() + } + + fn call(&mut self, req: ServiceRequest

) -> Self::Future { + // We only need to hook into the `start` for this middleware. + let is_logged_in = false; // Change this to see the change in outcome in the browser if is_logged_in { - return Ok(Started::Done); + Either::A(self.service.call(req)) + } else { + // Don't forward to /login if we are already on /login + if req.path() == "/login" { + Either::A(self.service.call(req)) + } else { + Either::B(ok(req.into_response( + HttpResponse::Found() + .header(http::header::LOCATION, "/login") + .finish() + .into_body(), + ))) + } } - - // Don't forward to /login if we are already on /login - if req.path() == "/login" { - return Ok(Started::Done); - } - - Ok(Started::Response( - HttpResponse::Found() - .header(http::header::LOCATION, "/login") - .finish(), - )) } } diff --git a/middleware/src/simple.rs b/middleware/src/simple.rs index 254f263d..68f6e143 100644 --- a/middleware/src/simple.rs +++ b/middleware/src/simple.rs @@ -1,25 +1,63 @@ -extern crate actix_web; +use actix_service::{Service, Transform}; +use actix_web::dev::{ServiceRequest, ServiceResponse}; +use futures::future::{ok, FutureResult}; +use futures::{Future, Poll}; -use actix_web::middleware::{Finished, Middleware, Response, Started}; -use actix_web::{HttpRequest, HttpResponse, Result}; - -// Middleware can get called at three stages during the request/response handling. Below is a -// struct that implements all three of them. +// There are two step in middleware processing. +// 1. Middleware initialization, middleware factory get called with +// next service in chain as parameter. +// 2. Middleware's call method get called with normal request. pub struct SayHi; -impl Middleware for SayHi { - fn start(&self, req: &HttpRequest) -> Result { - println!("Hi from start. You requested: {}", req.path()); - Ok(Started::Done) - } +// Middleware factory is `Transform` trait from actix-service crate +// `S` - type of the next service +// `P` - type of request's payload +// `B` - type of response's body +impl Transform for SayHi +where + S: Service, Response = ServiceResponse>, + S::Future: 'static, + S::Error: 'static, + B: 'static, +{ + type Request = ServiceRequest

; + type Response = ServiceResponse; + type Error = S::Error; + type InitError = (); + type Transform = SayHiMiddleware; + type Future = FutureResult; - fn response(&self, _req: &HttpRequest, resp: HttpResponse) -> Result { - println!("Hi from response"); - Ok(Response::Done(resp)) - } - - fn finish(&self, _req: &HttpRequest, _resp: &HttpResponse) -> Finished { - println!("Hi from finish"); - Finished::Done + fn new_transform(&self, service: S) -> Self::Future { + ok(SayHiMiddleware { service }) + } +} + +pub struct SayHiMiddleware { + service: S, +} + +impl Service for SayHiMiddleware +where + S: Service, Response = ServiceResponse>, + S::Future: 'static, + S::Error: 'static, + B: 'static, +{ + type Request = ServiceRequest

; + type Response = ServiceResponse; + type Error = S::Error; + type Future = Box>; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + self.service.poll_ready() + } + + fn call(&mut self, req: ServiceRequest

) -> Self::Future { + println!("Hi from start. You requested: {}", req.path()); + + Box::new(self.service.call(req).and_then(|res| { + println!("Hi from response"); + Ok(res) + })) } } From 7ed8d19b66a348e680d1e274602dd3f21b086029 Mon Sep 17 00:00:00 2001 From: Juan Aguilar Santillana Date: Tue, 12 Mar 2019 21:15:53 +0100 Subject: [PATCH 17/23] Add template yarte --- .travis.yml | 1 + Cargo.toml | 1 + template_yarte/Cargo.toml | 17 ++++++++++++++ template_yarte/README.md | 11 ++++++++++ template_yarte/build.rs | 5 +++++ template_yarte/src/lib.rs | 21 ++++++++++++++++++ template_yarte/src/main.rs | 19 ++++++++++++++++ .../templates/deep/more/deep/welcome.hbs | 1 + template_yarte/templates/index.hbs | 22 +++++++++++++++++++ template_yarte/yarte.toml | 14 ++++++++++++ 10 files changed, 112 insertions(+) create mode 100644 template_yarte/Cargo.toml create mode 100644 template_yarte/README.md create mode 100644 template_yarte/build.rs create mode 100644 template_yarte/src/lib.rs create mode 100644 template_yarte/src/main.rs create mode 100644 template_yarte/templates/deep/more/deep/welcome.hbs create mode 100644 template_yarte/templates/index.hbs create mode 100644 template_yarte/yarte.toml diff --git a/.travis.yml b/.travis.yml index 66f91d8b..4c82f956 100644 --- a/.travis.yml +++ b/.travis.yml @@ -60,6 +60,7 @@ script: cd static_index && cargo check && cd .. cd template_askama && cargo check && cd .. cd template_tera && cargo check && cd .. + cd template_yarte && cargo check && cd .. cd tls && cargo check && cd .. cd rustls && cargo check && cd .. cd unix-socket && cargo check && cd .. diff --git a/Cargo.toml b/Cargo.toml index 5c287311..7422c22d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ members = [ "static_index", "template_askama", "template_tera", + "template_yarte", "tls", "rustls", "unix-socket", diff --git a/template_yarte/Cargo.toml b/template_yarte/Cargo.toml new file mode 100644 index 00000000..4a7f8cbb --- /dev/null +++ b/template_yarte/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "example" +version = "0.0.1" +authors = ["Rust-iendo Barcelona "] +publish = false +edition = "2018" + +workspace = ".." + +[dependencies] +env_logger = "0.6" + +yarte = "0.1" +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } + +[build-dependencies] +yarte = "0.1" diff --git a/template_yarte/README.md b/template_yarte/README.md new file mode 100644 index 00000000..df534a7c --- /dev/null +++ b/template_yarte/README.md @@ -0,0 +1,11 @@ +# yarte + +Example of composition with partials and `with-actix-web` feature + +See the generated code on stdout when run at debug +```bash +cargo run +``` +> open `localhost:8080` + +More at [mdbook](https://yarte.netlify.com/) and [repository](https://gitlab.com/r-iendo/yarte) diff --git a/template_yarte/build.rs b/template_yarte/build.rs new file mode 100644 index 00000000..da256d18 --- /dev/null +++ b/template_yarte/build.rs @@ -0,0 +1,5 @@ +use yarte::recompile; + +fn main() { + recompile::when_changed(); +} diff --git a/template_yarte/src/lib.rs b/template_yarte/src/lib.rs new file mode 100644 index 00000000..83f1f848 --- /dev/null +++ b/template_yarte/src/lib.rs @@ -0,0 +1,21 @@ +use actix_web::{error::ErrorInternalServerError, web::Query, HttpResponse, Result}; +use yarte::Template; + +use std::collections::HashMap; + +#[derive(Template)] +#[template(path = "index.hbs")] +struct IndexTemplate { + query: Query>, +} + +pub fn index(query: Query>) -> Result { + IndexTemplate { query } + .call() + .map(|s| { + HttpResponse::Ok() + .content_type(IndexTemplate::mime()) + .body(s) + }) + .map_err(|_| ErrorInternalServerError("Template parsing error")) +} diff --git a/template_yarte/src/main.rs b/template_yarte/src/main.rs new file mode 100644 index 00000000..6a4a896e --- /dev/null +++ b/template_yarte/src/main.rs @@ -0,0 +1,19 @@ +use actix_web::{middleware, web, App, HttpServer}; + +#[path = "lib.rs"] +mod template; + +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); + env_logger::init(); + + // start http server + HttpServer::new(|| { + App::new() + // enable logger + .middleware(middleware::Logger::default()) + .service(web::resource("/").to(template::index)) + }) + .bind("127.0.0.1:8080")? + .run() +} diff --git a/template_yarte/templates/deep/more/deep/welcome.hbs b/template_yarte/templates/deep/more/deep/welcome.hbs new file mode 100644 index 00000000..5cb2a971 --- /dev/null +++ b/template_yarte/templates/deep/more/deep/welcome.hbs @@ -0,0 +1 @@ +<{{ tag }}>Welcome! diff --git a/template_yarte/templates/index.hbs b/template_yarte/templates/index.hbs new file mode 100644 index 00000000..503bb845 --- /dev/null +++ b/template_yarte/templates/index.hbs @@ -0,0 +1,22 @@ + + + + + Actix web + + +{{~#if let Some(name) = query.get("name") ~}} +

Hi, {{ name }}!

+ {{~> alias/welcome tag='p' ~}} +{{~ else ~}} + {{~> alias/welcome tag="h1" ~}} +

+

What is your name?

+
+
+

+
+

+{{~/if~}} + + diff --git a/template_yarte/yarte.toml b/template_yarte/yarte.toml new file mode 100644 index 00000000..19a63673 --- /dev/null +++ b/template_yarte/yarte.toml @@ -0,0 +1,14 @@ +# root dir of templates +[main] +dir = "templates" +debug = "code" + +# Alias for partials. In call, change the start of partial path with one of this, if exist. +[partials] +alias = "./deep/more/deep" + +[debug] +# prettyprint themes, put anything for options +theme = "zenburn" +number_line = true +grid = true From b31c8e3308a29cc76f124b42e3d0d7123a2a6b35 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 16 Mar 2019 20:23:09 -0700 Subject: [PATCH 18/23] rename web::State to web::Data --- actix_todo/src/api.rs | 12 ++++++------ async_db/src/main.rs | 4 ++-- diesel/src/main.rs | 8 ++++---- form/src/main.rs | 2 +- juniper/src/main.rs | 2 +- r2d2/src/main.rs | 2 +- state/src/main.rs | 14 +++++++------- template_tera/src/main.rs | 2 +- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/actix_todo/src/api.rs b/actix_todo/src/api.rs index 069e5db8..833e2b2d 100644 --- a/actix_todo/src/api.rs +++ b/actix_todo/src/api.rs @@ -9,8 +9,8 @@ use crate::db; use crate::session::{self, FlashMessage}; pub fn index( - pool: web::State, - tmpl: web::State, + pool: web::Data, + tmpl: web::Data, session: Session, ) -> impl Future { web::block(move || db::get_all_tasks(&pool)) @@ -45,7 +45,7 @@ pub struct CreateForm { pub fn create( params: web::Form, - pool: web::State, + pool: web::Data, session: Session, ) -> impl Future { if params.description.is_empty() { @@ -86,7 +86,7 @@ pub struct UpdateForm { } pub fn update( - db: web::State, + db: web::Data, params: web::Path, form: web::Form, session: Session, @@ -102,7 +102,7 @@ pub fn update( } fn toggle( - pool: web::State, + pool: web::Data, params: web::Path, ) -> impl Future { web::block(move || db::toggle_task(params.id, &pool)) @@ -114,7 +114,7 @@ fn toggle( } fn delete( - pool: web::State, + pool: web::Data, params: web::Path, session: Session, ) -> impl Future { diff --git a/async_db/src/main.rs b/async_db/src/main.rs index e9583999..e5648b23 100644 --- a/async_db/src/main.rs +++ b/async_db/src/main.rs @@ -21,7 +21,7 @@ use db::{Pool, Queries, WeatherAgg}; /// Version 1: Calls 4 queries in sequential order, as an asynchronous handler fn asyncio_weather( - db: web::State, + db: web::Data, ) -> impl Future { let mut result: Vec> = vec![]; @@ -52,7 +52,7 @@ fn asyncio_weather( /// Version 2: Calls 4 queries in parallel, as an asynchronous handler /// Returning Error types turn into None values in the response fn parallel_weather( - db: web::State, + db: web::Data, ) -> impl Future { let fut_result = vec![ Box::new(db::execute(&db, Queries::GetTopTenHottestYears)), diff --git a/diesel/src/main.rs b/diesel/src/main.rs index 8ff8ce68..044db371 100644 --- a/diesel/src/main.rs +++ b/diesel/src/main.rs @@ -24,7 +24,7 @@ type Pool = r2d2::Pool>; /// Diesel query fn query( nm: String, - pool: web::State, + pool: web::Data, ) -> Result { use self::schema::users::dsl::*; @@ -44,7 +44,7 @@ fn query( /// Async request handler fn add( name: web::Path, - pool: web::State, + pool: web::Data, ) -> impl Future { // run diesel blocking code web::block(move || query(name.into_inner(), pool)).then(|res| match res { @@ -63,7 +63,7 @@ const MAX_SIZE: usize = 262_144; // max payload size is 256k /// This handler manually load request payload and parse json object fn index_add

( pl: web::Payload

, - pool: web::State, + pool: web::Data, ) -> impl Future where P: Stream, @@ -110,7 +110,7 @@ where fn add2( item: web::Json, - pool: web::State, + pool: web::Data, ) -> impl Future { // run diesel blocking code web::block(move || query(item.into_inner().name, pool)).then(|res| match res { diff --git a/form/src/main.rs b/form/src/main.rs index c0c38690..3219ccba 100644 --- a/form/src/main.rs +++ b/form/src/main.rs @@ -45,7 +45,7 @@ fn handle_post_1(params: web::Form) -> Result { /// State and POST Params fn handle_post_2( - state: web::State, + state: web::Data, params: web::Form, ) -> HttpResponse { HttpResponse::Ok().content_type("text/plain").body(format!( diff --git a/juniper/src/main.rs b/juniper/src/main.rs index 34967eb1..433688e0 100644 --- a/juniper/src/main.rs +++ b/juniper/src/main.rs @@ -24,7 +24,7 @@ fn graphiql() -> HttpResponse { } fn graphql( - st: web::State>, + st: web::Data>, data: web::Json, ) -> impl Future { web::block(move || { diff --git a/r2d2/src/main.rs b/r2d2/src/main.rs index 9b1060d2..7b7f91b3 100644 --- a/r2d2/src/main.rs +++ b/r2d2/src/main.rs @@ -10,7 +10,7 @@ use uuid; /// Async request handler. Ddb pool is stored in application state. fn index( path: web::Path, - db: web::State>, + db: web::Data>, ) -> impl Future { // execute sync code in threadpool web::block(move || { diff --git a/state/src/main.rs b/state/src/main.rs index f67e9290..642d34ef 100644 --- a/state/src/main.rs +++ b/state/src/main.rs @@ -1,12 +1,12 @@ #![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] -//! Application may have multiple states that are shared across -//! all handlers within same Application. State could be added -//! with `App::state()` method, multiple different states could be added. +//! Application may have multiple data objects that are shared across +//! all handlers within same Application. Data could be added +//! with `App::data()` method, multiple different data objects could be added. //! //! > **Note**: http server accepts an application factory rather than an //! application > instance. Http server constructs an application instance for -//! each thread, > thus application state -//! > must be constructed multiple times. If you want to share state between +//! each thread, > thus application data +//! > must be constructed multiple times. If you want to share data between //! different > threads, a shared object should be used, e.g. `Arc`. //! //! Check [user guide](https://actix.rs/book/actix-web/sec-2-application.html) for more info. @@ -17,7 +17,7 @@ use std::sync::{Arc, Mutex}; use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer}; /// simple handle -fn index(state: web::State>>, req: HttpRequest) -> HttpResponse { +fn index(state: web::Data>>, req: HttpRequest) -> HttpResponse { println!("{:?}", req); *(state.lock().unwrap()) += 1; @@ -33,7 +33,7 @@ fn main() -> io::Result<()> { //move is necessary to give closure below ownership of counter HttpServer::new(move || { App::new() - .state(counter.clone()) // <- create app with shared state + .data(counter.clone()) // <- create app with shared state // enable logger .middleware(middleware::Logger::default()) // register simple handler, handle all methods diff --git a/template_tera/src/main.rs b/template_tera/src/main.rs index b442e82a..37c9d93b 100644 --- a/template_tera/src/main.rs +++ b/template_tera/src/main.rs @@ -7,7 +7,7 @@ use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer}; // store tera template in application state fn index( - tmpl: web::State, + tmpl: web::Data, query: web::Query>, ) -> Result { let s = if let Some(name) = query.get("name") { From 1779f963d9c77b46a09dd2b6ae720b89760ff09b Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 18 Mar 2019 05:31:32 -0700 Subject: [PATCH 19/23] migrate websocket example --- websocket/Cargo.toml | 19 ++++++++++-------- websocket/src/main.rs | 45 +++++++++++++++++++------------------------ 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/websocket/Cargo.toml b/websocket/Cargo.toml index 4ed656ec..a3f662c0 100644 --- a/websocket/Cargo.toml +++ b/websocket/Cargo.toml @@ -2,19 +2,22 @@ name = "websocket" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +edition = "2018" +workspace = ".." [[bin]] name = "websocket-server" path = "src/main.rs" -[[bin]] -name = "websocket-client" -path = "src/client.rs" +#[[bin]] +#name = "websocket-client" +#path = "src/client.rs" [dependencies] -env_logger = "*" +actix = { git="https://github.com/actix/actix.git" } +actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web-actors = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-files = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +env_logger = "0.6" futures = "0.1" - -actix = "0.7" -actix-web = "0.7" +bytes = "0.4" \ No newline at end of file diff --git a/websocket/src/main.rs b/websocket/src/main.rs index 0b9a5716..25aac6ab 100644 --- a/websocket/src/main.rs +++ b/websocket/src/main.rs @@ -3,17 +3,16 @@ //! or [python console client](https://github.com/actix/examples/blob/master/websocket/websocket-client.py) //! could be used for testing. -#![allow(unused_variables)] -extern crate actix; -extern crate actix_web; -extern crate env_logger; - use std::time::{Duration, Instant}; use actix::prelude::*; +use actix_files as fs; use actix_web::{ - fs, http, middleware, server, ws, App, Error, HttpRequest, HttpResponse, + error, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer, }; +use actix_web_actors::ws; +use bytes::Bytes; +use futures::Stream; /// How often heartbeat pings are sent const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); @@ -21,8 +20,14 @@ const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); const CLIENT_TIMEOUT: Duration = Duration::from_secs(10); /// do websocket handshake and start `MyWebSocket` actor -fn ws_index(r: &HttpRequest) -> Result { - ws::start(r, MyWebSocket::new()) +fn ws_index(r: HttpRequest, stream: web::Payload) -> Result +where + S: Stream + 'static, +{ + println!("{:?}", r); + let res = ws::start(MyWebSocket::new(), &r, stream); + println!("{:?}", res.as_ref().unwrap()); + res } /// websocket connection is long running connection, it easier @@ -91,30 +96,20 @@ impl MyWebSocket { } } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info"); env_logger::init(); - let sys = actix::System::new("ws-example"); - server::new(|| { + HttpServer::new(|| { App::new() // enable logger .middleware(middleware::Logger::default()) // websocket route - .resource("/ws/", |r| r.method(http::Method::GET).f(ws_index)) + .service(web::resource("/ws/").route(web::get().to(ws_index))) // static files - .handler( - "/", - fs::StaticFiles::new("static/") - .unwrap() - .index_file("index.html"), - ) + .service(fs::Files::new("/", "static/").index_file("index.html")) }) // start http server on 127.0.0.1:8080 - .bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } From 53fc2221efc0c4c2b4fd3d480e01d8ff1cac5174 Mon Sep 17 00:00:00 2001 From: Juan Aguilar Date: Tue, 26 Mar 2019 04:29:00 +0100 Subject: [PATCH 20/23] Update to master (#90) --- .travis.yml | 2 -- actix_todo/Cargo.toml | 6 +++--- actix_todo/src/api.rs | 2 +- actix_todo/src/main.rs | 12 ++++++------ async_db/Cargo.toml | 2 +- async_db/src/main.rs | 4 ++-- async_ex1/Cargo.toml | 2 +- async_ex1/src/main.rs | 38 +++++++++++++++++++++++--------------- basics/Cargo.toml | 6 +++--- basics/src/main.rs | 4 ++-- cookie-auth/Cargo.toml | 2 +- cookie-auth/src/main.rs | 4 ++-- cookie-session/Cargo.toml | 4 ++-- cookie-session/src/main.rs | 4 ++-- diesel/Cargo.toml | 2 +- diesel/src/main.rs | 28 ++++++++++++++++++---------- error_handling/Cargo.toml | 2 +- form/Cargo.toml | 2 +- form/src/main.rs | 4 ++-- hello-world/Cargo.toml | 2 +- hello-world/src/main.rs | 2 +- json/Cargo.toml | 2 +- json/src/main.rs | 24 ++++++++---------------- juniper/Cargo.toml | 2 +- juniper/src/main.rs | 4 ++-- middleware/Cargo.toml | 2 +- middleware/src/main.rs | 4 ++-- r2d2/Cargo.toml | 2 +- r2d2/src/main.rs | 4 ++-- state/Cargo.toml | 2 +- state/src/main.rs | 2 +- static_index/Cargo.toml | 4 ++-- static_index/src/main.rs | 2 +- template_askama/Cargo.toml | 2 +- template_tera/Cargo.toml | 2 +- template_tera/src/main.rs | 4 ++-- template_yarte/Cargo.toml | 2 +- template_yarte/src/lib.rs | 20 -------------------- template_yarte/src/main.rs | 34 +++++++++++++++++++++++++++++----- template_yarte/yarte.toml | 7 ------- tls/Cargo.toml | 2 +- tls/src/main.rs | 2 +- websocket/Cargo.toml | 6 +++--- websocket/src/main.rs | 13 +++---------- 44 files changed, 139 insertions(+), 143 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4c82f956..8050c10d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,6 @@ script: cd actix_todo && cargo check && cd .. cd basics && cargo check && cd .. cd cookie-auth && cargo check && cd .. - cd cookie-auth-full && cargo check && cd .. cd cookie-session && cargo check && cd .. cd diesel && cargo check && cd .. cd error_handling && cargo check && cd .. @@ -55,7 +54,6 @@ script: cd protobuf && cargo check && cd .. cd r2d2 && cargo check && cd .. cd redis-session && cargo check && cd .. - cd simple-auth-sarver && cargo check && cd .. cd state && cargo check && cd .. cd static_index && cargo check && cd .. cd template_askama && cargo check && cd .. diff --git a/actix_todo/Cargo.toml b/actix_todo/Cargo.toml index 09b9a010..736178d1 100644 --- a/actix_todo/Cargo.toml +++ b/actix_todo/Cargo.toml @@ -6,9 +6,9 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -actix-files = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } +actix-files = { git="https://github.com/actix/actix-web.git" } +actix-session = { git="https://github.com/actix/actix-web.git" } dotenv = "0.13.0" env_logger = "0.5.10" futures = "0.1.22" diff --git a/actix_todo/src/api.rs b/actix_todo/src/api.rs index 833e2b2d..cb3e15ae 100644 --- a/actix_todo/src/api.rs +++ b/actix_todo/src/api.rs @@ -1,6 +1,6 @@ use actix_files::NamedFile; use actix_session::Session; -use actix_web::middleware::ErrorHandlerResponse; +use actix_web::middleware::errhandlers::ErrorHandlerResponse; use actix_web::{dev, error, http, web, Error, HttpResponse, Responder, Result}; use futures::future::{err, Either, Future, IntoFuture}; use tera::{Context, Tera}; diff --git a/actix_todo/src/main.rs b/actix_todo/src/main.rs index 9c9664aa..aca105ec 100644 --- a/actix_todo/src/main.rs +++ b/actix_todo/src/main.rs @@ -11,7 +11,7 @@ use std::{env, io}; use actix_files as fs; use actix_session::CookieSession; -use actix_web::middleware::{ErrorHandlers, Logger}; +use actix_web::middleware::{errhandlers::ErrorHandlers, Logger}; use actix_web::{http, web, App, HttpServer}; use dotenv::dotenv; use tera::Tera; @@ -49,11 +49,11 @@ fn main() -> io::Result<()> { .handler(http::StatusCode::NOT_FOUND, api::not_found); App::new() - .state(templates) - .state(pool.clone()) - .middleware(Logger::default()) - .middleware(session_store) - .middleware(error_handlers) + .data(templates) + .data(pool.clone()) + .wrap(Logger::default()) + .wrap(session_store) + .wrap(error_handlers) .service(web::resource("/").route(web::get().to_async(api::index))) .service(web::resource("/todo").route(web::post().to_async(api::create))) .service( diff --git a/async_db/Cargo.toml b/async_db/Cargo.toml index 9dee0d2f..3161c19d 100644 --- a/async_db/Cargo.toml +++ b/async_db/Cargo.toml @@ -7,7 +7,7 @@ workspace = ".." [dependencies] actix-rt = "0.2" -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } dotenv = "0.10" env_logger = "0.5" diff --git a/async_db/src/main.rs b/async_db/src/main.rs index e5648b23..b2293fed 100644 --- a/async_db/src/main.rs +++ b/async_db/src/main.rs @@ -78,8 +78,8 @@ fn main() -> io::Result<()> { // Start http server HttpServer::new(move || { App::new() - .state(pool.clone()) - .middleware(middleware::Logger::default()) + .data(pool.clone()) + .wrap(middleware::Logger::default()) .service( web::resource("/asyncio_weather") .route(web::get().to_async(asyncio_weather)), diff --git a/async_ex1/Cargo.toml b/async_ex1/Cargo.toml index 69985d71..01a79760 100644 --- a/async_ex1/Cargo.toml +++ b/async_ex1/Cargo.toml @@ -8,7 +8,7 @@ workspace = ".." [dependencies] actix-rt = "0.2" actix-http = { git="https://github.com/actix/actix-http.git", features=["ssl"] } -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0", features=["ssl"] } +actix-web = { git="https://github.com/actix/actix-web.git", features=["ssl"] } futures = "0.1" serde = "1.0.43" diff --git a/async_ex1/src/main.rs b/async_ex1/src/main.rs index 4e8c94dd..8781ce9c 100644 --- a/async_ex1/src/main.rs +++ b/async_ex1/src/main.rs @@ -24,8 +24,9 @@ use std::collections::HashMap; use std::io; use actix_http::client; -use actix_web::{web, App, Error, HttpMessage, HttpResponse, HttpServer}; -use futures::future::{ok, Future}; +use actix_web::web::BytesMut; +use actix_web::{web, App, Error, HttpResponse, HttpServer}; +use futures::{Future, Stream}; use validator::Validate; #[derive(Debug, Validate, Deserialize, Serialize)] @@ -54,7 +55,7 @@ struct HttpBinResponse { /// post json to httpbin, get it back in the response body, return deserialized fn step_x_v1(data: SomeData) -> Box> { - let mut connector = client::Connector::default().service(); + let mut connector = client::Connector::new().service(); Box::new( client::ClientRequest::post("https://httpbin.org/post") @@ -62,13 +63,17 @@ fn step_x_v1(data: SomeData) -> Box> { .unwrap() .send(&mut connector) .map_err(Error::from) // <- convert SendRequestError to an Error - .and_then(|mut resp| { - resp.body() // <- this is MessageBody type, resolves to complete body + .and_then(|resp| { + resp // <- this is MessageBody type, resolves to complete body .from_err() // <- convert PayloadError to an Error - .and_then(|body| { - let resp: HttpBinResponse = + .fold(BytesMut::new(), |mut acc, chunk| { + acc.extend_from_slice(&chunk); + Ok::<_, Error>(acc) + }) + .map(|body| { + let body: HttpBinResponse = serde_json::from_slice(&body).unwrap(); - ok(resp.json) + body.json }) }), ) @@ -95,19 +100,22 @@ fn create_something_v1( /// post json to httpbin, get it back in the response body, return deserialized fn step_x_v2(data: SomeData) -> impl Future { - let mut connector = client::Connector::default().service(); + let mut connector = client::Connector::new().service(); client::ClientRequest::post("https://httpbin.org/post") .json(data) .unwrap() .send(&mut connector) .map_err(Error::from) // <- convert SendRequestError to an Error - .and_then(|mut resp| { - resp.body() // <- this is MessageBody type, resolves to complete body - .from_err() // <- convert PayloadError to an Error - .and_then(|body| { - let resp: HttpBinResponse = serde_json::from_slice(&body).unwrap(); - ok(resp.json) + .and_then(|resp| { + resp.from_err() + .fold(BytesMut::new(), |mut acc, chunk| { + acc.extend_from_slice(&chunk); + Ok::<_, Error>(acc) + }) + .map(|body| { + let body: HttpBinResponse = serde_json::from_slice(&body).unwrap(); + body.json }) }) } diff --git a/basics/Cargo.toml b/basics/Cargo.toml index 71a98837..0147e333 100644 --- a/basics/Cargo.toml +++ b/basics/Cargo.toml @@ -7,9 +7,9 @@ edition = "2018" [dependencies] actix-rt = "0.2" -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -actix-files = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } +actix-files = { git="https://github.com/actix/actix-web.git" } +actix-session = { git="https://github.com/actix/actix-web.git" } futures = "0.1.25" env_logger = "0.5" diff --git a/basics/src/main.rs b/basics/src/main.rs index 58eae45c..7ab8a725 100644 --- a/basics/src/main.rs +++ b/basics/src/main.rs @@ -83,9 +83,9 @@ fn main() -> io::Result<()> { HttpServer::new(|| { App::new() // enable logger - .middleware(middleware::Logger::default()) + .wrap(middleware::Logger::default()) // cookie session middleware - .middleware(CookieSession::signed(&[0; 32]).secure(false)) + .wrap(CookieSession::signed(&[0; 32]).secure(false)) // register favicon .service(favicon) // register simple route, handle all methods diff --git a/cookie-auth/Cargo.toml b/cookie-auth/Cargo.toml index 81fd8eb9..efeb709c 100644 --- a/cookie-auth/Cargo.toml +++ b/cookie-auth/Cargo.toml @@ -6,5 +6,5 @@ edition = "2018" workspace = ".." [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } env_logger = "0.6" diff --git a/cookie-auth/src/main.rs b/cookie-auth/src/main.rs index 01ddde23..9d1f8577 100644 --- a/cookie-auth/src/main.rs +++ b/cookie-auth/src/main.rs @@ -22,8 +22,8 @@ fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() - .middleware(middleware::Logger::default()) - .middleware(IdentityService::new( + .wrap(middleware::Logger::default()) + .wrap(IdentityService::new( CookieIdentityPolicy::new(&[0; 32]) .name("auth-example") .secure(false), diff --git a/cookie-session/Cargo.toml b/cookie-session/Cargo.toml index 2947b950..d7bee4dd 100644 --- a/cookie-session/Cargo.toml +++ b/cookie-session/Cargo.toml @@ -6,8 +6,8 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -actix-session = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } +actix-session = { git="https://github.com/actix/actix-web.git" } futures = "0.1" time = "0.1" diff --git a/cookie-session/src/main.rs b/cookie-session/src/main.rs index 6e0df123..497f01da 100644 --- a/cookie-session/src/main.rs +++ b/cookie-session/src/main.rs @@ -32,9 +32,9 @@ fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() // enable logger - .middleware(Logger::default()) + .wrap(Logger::default()) // cookie session middleware - .middleware(CookieSession::signed(&[0; 32]).secure(false)) + .wrap(CookieSession::signed(&[0; 32]).secure(false)) .service(web::resource("/").to(index)) }) .bind("127.0.0.1:8080")? diff --git a/diesel/Cargo.toml b/diesel/Cargo.toml index af94c957..4089a877 100644 --- a/diesel/Cargo.toml +++ b/diesel/Cargo.toml @@ -6,7 +6,7 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } bytes = "0.4" env_logger = "0.6" diff --git a/diesel/src/main.rs b/diesel/src/main.rs index 044db371..fdf3cbc4 100644 --- a/diesel/src/main.rs +++ b/diesel/src/main.rs @@ -10,7 +10,7 @@ extern crate diesel; extern crate serde_derive; use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer}; -use bytes::{Bytes, BytesMut}; +use bytes::BytesMut; use diesel::prelude::*; use diesel::r2d2::{self, ConnectionManager}; use futures::future::{err, Either}; @@ -61,13 +61,10 @@ struct MyUser { const MAX_SIZE: usize = 262_144; // max payload size is 256k /// This handler manually load request payload and parse json object -fn index_add

( - pl: web::Payload

, +fn index_add( + pl: web::Payload, pool: web::Data, -) -> impl Future -where - P: Stream, -{ +) -> impl Future { pl // `Future::from_err` acts like `?` in that it coerces the error type from // the future into the final error type @@ -132,9 +129,9 @@ fn main() -> std::io::Result<()> { // Start http server HttpServer::new(move || { App::new() - .state(pool.clone()) + .data(pool.clone()) // enable logger - .middleware(middleware::Logger::default()) + .wrap(middleware::Logger::default()) // This can be called with: // curl -S --header "Content-Type: application/json" --request POST --data '{"name":"xyz"}' http://127.0.0.1:8080/add // Use of the extractors makes some post conditions simpler such @@ -142,7 +139,18 @@ fn main() -> std::io::Result<()> { .service( web::resource("/add2").route( web::post() - .config(web::JsonConfig::default().limit(4096)) // <- limit size of the payload + .data( + web::JsonConfig::default() + .limit(4096) // <- limit size of the payload + .error_handler(|err, _| { + // <- create custom error response + error::InternalError::from_response( + err, + HttpResponse::Conflict().finish(), + ) + .into() + }), + ) .to_async(add2), ), ) diff --git a/error_handling/Cargo.toml b/error_handling/Cargo.toml index f1df6a48..c4cb0973 100644 --- a/error_handling/Cargo.toml +++ b/error_handling/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" workspace = ".." [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } derive_more = "0.14.0" futures = "0.1.23" diff --git a/form/Cargo.toml b/form/Cargo.toml index 1fd56d4e..a849fed4 100644 --- a/form/Cargo.toml +++ b/form/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" workspace = ".." [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } serde = "1.0" serde_derive = "1.0" diff --git a/form/src/main.rs b/form/src/main.rs index 3219ccba..ebdddf0a 100644 --- a/form/src/main.rs +++ b/form/src/main.rs @@ -12,10 +12,10 @@ struct AppState { fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() - .state(AppState { + .data(AppState { foo: "bar".to_string(), }) - .middleware(middleware::Logger::default()) + .wrap(middleware::Logger::default()) .service(web::resource("/").route(web::get().to(index))) .service(web::resource("/post1").route(web::post().to(handle_post_1))) .service(web::resource("/post2").route(web::post().to(handle_post_2))) diff --git a/hello-world/Cargo.toml b/hello-world/Cargo.toml index cb47b1e0..d3d38429 100644 --- a/hello-world/Cargo.toml +++ b/hello-world/Cargo.toml @@ -7,4 +7,4 @@ edition = "2018" [dependencies] env_logger = "0.6" -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } diff --git a/hello-world/src/main.rs b/hello-world/src/main.rs index 3bb9064a..ac294063 100644 --- a/hello-world/src/main.rs +++ b/hello-world/src/main.rs @@ -12,7 +12,7 @@ fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() // enable logger - .middleware(middleware::Logger::default()) + .wrap(middleware::Logger::default()) .service(web::resource("/index.html").to(|| "Hello world!")) .service(web::resource("/").to(index)) }) diff --git a/json/Cargo.toml b/json/Cargo.toml index ff724d24..c5d09827 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -6,7 +6,7 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } bytes = "0.4" futures = "0.1" diff --git a/json/src/main.rs b/json/src/main.rs index 6c9d7a5c..9b0d9a57 100644 --- a/json/src/main.rs +++ b/json/src/main.rs @@ -4,7 +4,7 @@ extern crate json; use actix_web::{ error, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer, }; -use bytes::{Bytes, BytesMut}; +use bytes::BytesMut; use futures::{Future, Stream}; use json::JsonValue; use serde_derive::{Deserialize, Serialize}; @@ -32,12 +32,9 @@ fn extract_item(item: web::Json, req: HttpRequest) -> HttpResponse { const MAX_SIZE: usize = 262_144; // max payload size is 256k /// This handler manually load request payload and parse json object -fn index_manual

( - payload: web::Payload

, -) -> impl Future -where - P: Stream, -{ +fn index_manual( + payload: web::Payload, +) -> impl Future { // payload is a stream of Bytes objects payload // `Future::from_err` acts like `?` in that it coerces the error type from @@ -64,12 +61,7 @@ where } /// This handler manually load request payload and parse json-rust -fn index_mjsonrust

( - pl: web::Payload

, -) -> impl Future -where - P: Stream, -{ +fn index_mjsonrust(pl: web::Payload) -> impl Future { pl.concat2().from_err().and_then(|body| { // body is loaded, now we can deserialize json-rust let result = json::parse(std::str::from_utf8(&body).unwrap()); // return Result @@ -90,18 +82,18 @@ fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() // enable logger - .middleware(middleware::Logger::default()) + .wrap(middleware::Logger::default()) .service( web::resource("/extractor").route( web::post() - .config(web::JsonConfig::default().limit(4096)) // <- limit size of the payload + .data(web::JsonConfig::default().limit(4096)) // <- limit size of the payload .to(index), ), ) .service( web::resource("/extractor2").route( web::post() - .config(web::JsonConfig::default().limit(4096)) // <- limit size of the payload + .data(web::JsonConfig::default().limit(4096)) // <- limit size of the payload .to_async(extract_item), ), ) diff --git a/juniper/Cargo.toml b/juniper/Cargo.toml index e1295d2f..07ac6365 100644 --- a/juniper/Cargo.toml +++ b/juniper/Cargo.toml @@ -6,7 +6,7 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } env_logger = "0.6" futures = "0.1" serde = "1.0" diff --git a/juniper/src/main.rs b/juniper/src/main.rs index 433688e0..2615d34e 100644 --- a/juniper/src/main.rs +++ b/juniper/src/main.rs @@ -49,8 +49,8 @@ fn main() -> io::Result<()> { // Start http server HttpServer::new(move || { App::new() - .state(schema.clone()) - .middleware(middleware::Logger::default()) + .data(schema.clone()) + .wrap(middleware::Logger::default()) .service(web::resource("/graphql").route(web::post().to_async(graphql))) .service(web::resource("/graphiql").route(web::get().to(graphiql))) }) diff --git a/middleware/Cargo.toml b/middleware/Cargo.toml index 2d533c8e..7905b56c 100644 --- a/middleware/Cargo.toml +++ b/middleware/Cargo.toml @@ -7,6 +7,6 @@ workspace = ".." [dependencies] actix-service = "0.3.3" -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } futures = "0.1.25" env_logger = "0.6" \ No newline at end of file diff --git a/middleware/src/main.rs b/middleware/src/main.rs index 6e1ec82e..0496db27 100644 --- a/middleware/src/main.rs +++ b/middleware/src/main.rs @@ -11,8 +11,8 @@ fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() - .middleware(redirect::CheckLogin) - .middleware(simple::SayHi) + .wrap(redirect::CheckLogin) + .wrap(simple::SayHi) .service(web::resource("/login").to(|| { "You are on /login. Go to src/redirect.rs to change this behavior." })) diff --git a/r2d2/Cargo.toml b/r2d2/Cargo.toml index 7046f298..a0b5e037 100644 --- a/r2d2/Cargo.toml +++ b/r2d2/Cargo.toml @@ -7,7 +7,7 @@ workspace = "../" [dependencies] actix-rt = "0.2" -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } futures = "0.1" env_logger = "0.6" diff --git a/r2d2/src/main.rs b/r2d2/src/main.rs index 7b7f91b3..c323784c 100644 --- a/r2d2/src/main.rs +++ b/r2d2/src/main.rs @@ -45,8 +45,8 @@ fn main() -> io::Result<()> { // start http server HttpServer::new(move || { App::new() - .state(pool.clone()) // <- store db pool in app state - .middleware(middleware::Logger::default()) + .data(pool.clone()) // <- store db pool in app state + .wrap(middleware::Logger::default()) .route("/{name}", web::get().to_async(index)) }) .bind("127.0.0.1:8080")? diff --git a/state/Cargo.toml b/state/Cargo.toml index 7d8e0a02..39bf08a7 100644 --- a/state/Cargo.toml +++ b/state/Cargo.toml @@ -6,7 +6,7 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } futures = "0.1" env_logger = "0.6" diff --git a/state/src/main.rs b/state/src/main.rs index 642d34ef..3ebb38a9 100644 --- a/state/src/main.rs +++ b/state/src/main.rs @@ -35,7 +35,7 @@ fn main() -> io::Result<()> { App::new() .data(counter.clone()) // <- create app with shared state // enable logger - .middleware(middleware::Logger::default()) + .wrap(middleware::Logger::default()) // register simple handler, handle all methods .service(web::resource("/").to(index)) }) diff --git a/static_index/Cargo.toml b/static_index/Cargo.toml index ee3d5377..2dcdba30 100644 --- a/static_index/Cargo.toml +++ b/static_index/Cargo.toml @@ -9,5 +9,5 @@ edition = "2018" futures = "0.1" env_logger = "0.5" -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -actix-files = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } +actix-files = { git="https://github.com/actix/actix-web.git" } diff --git a/static_index/src/main.rs b/static_index/src/main.rs index e4c4fa83..ced7b689 100644 --- a/static_index/src/main.rs +++ b/static_index/src/main.rs @@ -8,7 +8,7 @@ fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() // enable logger - .middleware(middleware::Logger::default()) + .wrap(middleware::Logger::default()) .service( // static files fs::Files::new("/", "./static/").index_file("index.html"), diff --git a/template_askama/Cargo.toml b/template_askama/Cargo.toml index d3297425..242087ac 100644 --- a/template_askama/Cargo.toml +++ b/template_askama/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" [dependencies] env_logger = "0.6" askama = "0.6" -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } [build-dependencies] askama = "0.6" diff --git a/template_tera/Cargo.toml b/template_tera/Cargo.toml index 2c01582d..ff35ad15 100644 --- a/template_tera/Cargo.toml +++ b/template_tera/Cargo.toml @@ -8,4 +8,4 @@ edition = "2018" [dependencies] env_logger = "0.6" tera = "*" -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } diff --git a/template_tera/src/main.rs b/template_tera/src/main.rs index 37c9d93b..a5942140 100644 --- a/template_tera/src/main.rs +++ b/template_tera/src/main.rs @@ -33,8 +33,8 @@ fn main() -> std::io::Result<()> { compile_templates!(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")); App::new() - .state(tera) - .middleware(middleware::Logger::default()) // enable logger + .data(tera) + .wrap(middleware::Logger::default()) // enable logger .service(web::resource("/").route(web::get().to(index))) }) .bind("127.0.0.1:8080")? diff --git a/template_yarte/Cargo.toml b/template_yarte/Cargo.toml index 4a7f8cbb..47a03b22 100644 --- a/template_yarte/Cargo.toml +++ b/template_yarte/Cargo.toml @@ -11,7 +11,7 @@ workspace = ".." env_logger = "0.6" yarte = "0.1" -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } [build-dependencies] yarte = "0.1" diff --git a/template_yarte/src/lib.rs b/template_yarte/src/lib.rs index 83f1f848..8b137891 100644 --- a/template_yarte/src/lib.rs +++ b/template_yarte/src/lib.rs @@ -1,21 +1 @@ -use actix_web::{error::ErrorInternalServerError, web::Query, HttpResponse, Result}; -use yarte::Template; -use std::collections::HashMap; - -#[derive(Template)] -#[template(path = "index.hbs")] -struct IndexTemplate { - query: Query>, -} - -pub fn index(query: Query>) -> Result { - IndexTemplate { query } - .call() - .map(|s| { - HttpResponse::Ok() - .content_type(IndexTemplate::mime()) - .body(s) - }) - .map_err(|_| ErrorInternalServerError("Template parsing error")) -} diff --git a/template_yarte/src/main.rs b/template_yarte/src/main.rs index 6a4a896e..cd4434b7 100644 --- a/template_yarte/src/main.rs +++ b/template_yarte/src/main.rs @@ -1,7 +1,31 @@ -use actix_web::{middleware, web, App, HttpServer}; +#[macro_use] +extern crate actix_web; -#[path = "lib.rs"] -mod template; +use std::collections::HashMap; + +use actix_web::{ + error::ErrorInternalServerError, middleware, web::Query, App, HttpResponse, + HttpServer, Result, +}; +use yarte::Template; + +#[derive(Template)] +#[template(path = "index.hbs")] +struct IndexTemplate { + query: Query>, +} + +#[get("/")] +pub fn index(query: Query>) -> Result { + IndexTemplate { query } + .call() + .map(|s| { + HttpResponse::Ok() + .content_type(IndexTemplate::mime()) + .body(s) + }) + .map_err(|_| ErrorInternalServerError("Template parsing error")) +} fn main() -> std::io::Result<()> { std::env::set_var("RUST_LOG", "actix_web=info"); @@ -11,8 +35,8 @@ fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() // enable logger - .middleware(middleware::Logger::default()) - .service(web::resource("/").to(template::index)) + .wrap(middleware::Logger::default()) + .service(index) }) .bind("127.0.0.1:8080")? .run() diff --git a/template_yarte/yarte.toml b/template_yarte/yarte.toml index 19a63673..bcf89202 100644 --- a/template_yarte/yarte.toml +++ b/template_yarte/yarte.toml @@ -1,14 +1,7 @@ # root dir of templates [main] dir = "templates" -debug = "code" # Alias for partials. In call, change the start of partial path with one of this, if exist. [partials] alias = "./deep/more/deep" - -[debug] -# prettyprint themes, put anything for options -theme = "zenburn" -number_line = true -grid = true diff --git a/tls/Cargo.toml b/tls/Cargo.toml index b18ff5a7..0442f206 100644 --- a/tls/Cargo.toml +++ b/tls/Cargo.toml @@ -14,4 +14,4 @@ env_logger = "0.5" openssl = { version="0.10" } actix-rt = "0.2" -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0", features=["ssl"] } +actix-web = { git="https://github.com/actix/actix-web.git", features=["ssl"] } diff --git a/tls/src/main.rs b/tls/src/main.rs index f8c8961c..7e95309a 100644 --- a/tls/src/main.rs +++ b/tls/src/main.rs @@ -27,7 +27,7 @@ fn main() -> io::Result<()> { HttpServer::new(|| { App::new() // enable logger - .middleware(middleware::Logger::default()) + .wrap(middleware::Logger::default()) // register simple handler, handle all methods .service(web::resource("/index.html").to(index)) // with path parameters diff --git a/websocket/Cargo.toml b/websocket/Cargo.toml index a3f662c0..a68b058f 100644 --- a/websocket/Cargo.toml +++ b/websocket/Cargo.toml @@ -15,9 +15,9 @@ path = "src/main.rs" [dependencies] actix = { git="https://github.com/actix/actix.git" } -actix-web = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -actix-web-actors = { git="https://github.com/actix/actix-web.git", branch = "1.0" } -actix-files = { git="https://github.com/actix/actix-web.git", branch = "1.0" } +actix-web = { git="https://github.com/actix/actix-web.git" } +actix-web-actors = { git="https://github.com/actix/actix-web.git" } +actix-files = { git="https://github.com/actix/actix-web.git" } env_logger = "0.6" futures = "0.1" bytes = "0.4" \ No newline at end of file diff --git a/websocket/src/main.rs b/websocket/src/main.rs index 25aac6ab..67d57918 100644 --- a/websocket/src/main.rs +++ b/websocket/src/main.rs @@ -7,12 +7,8 @@ use std::time::{Duration, Instant}; use actix::prelude::*; use actix_files as fs; -use actix_web::{ - error, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer, -}; +use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer}; use actix_web_actors::ws; -use bytes::Bytes; -use futures::Stream; /// How often heartbeat pings are sent const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); @@ -20,10 +16,7 @@ const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); const CLIENT_TIMEOUT: Duration = Duration::from_secs(10); /// do websocket handshake and start `MyWebSocket` actor -fn ws_index(r: HttpRequest, stream: web::Payload) -> Result -where - S: Stream + 'static, -{ +fn ws_index(r: HttpRequest, stream: web::Payload) -> Result { println!("{:?}", r); let res = ws::start(MyWebSocket::new(), &r, stream); println!("{:?}", res.as_ref().unwrap()); @@ -103,7 +96,7 @@ fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() // enable logger - .middleware(middleware::Logger::default()) + .wrap(middleware::Logger::default()) // websocket route .service(web::resource("/ws/").route(web::get().to(ws_index))) // static files From 48b8e7c335df9f0f195a5c7b0d7393e7f3c6b6fa Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 26 Mar 2019 23:33:13 -0700 Subject: [PATCH 21/23] migrate http proxy examples --- async_db/Cargo.toml | 3 +- async_db/src/db.rs | 9 +-- async_ex1/Cargo.toml | 1 - async_ex1/src/main.rs | 59 ++++++++++-------- http-full-proxy/Cargo.toml | 7 ++- http-full-proxy/src/main.rs | 119 +++++++++++++----------------------- http-proxy/Cargo.toml | 9 +-- http-proxy/src/main.rs | 56 +++++++---------- http-proxy/src/server.rs | 39 ++++-------- 9 files changed, 125 insertions(+), 177 deletions(-) diff --git a/async_db/Cargo.toml b/async_db/Cargo.toml index 3161c19d..7848d1b7 100644 --- a/async_db/Cargo.toml +++ b/async_db/Cargo.toml @@ -15,7 +15,8 @@ failure = "0.1.1" futures = "0.1" num_cpus = "1.10.0" r2d2 = "0.8.2" -r2d2_sqlite = "0.5.0" +r2d2_sqlite = "0.8.0" +rusqlite = "0.16" serde = "1.0" serde_json = "1.0" serde_derive = "1.0" diff --git a/async_db/src/db.rs b/async_db/src/db.rs index e23adba2..4ca80daf 100644 --- a/async_db/src/db.rs +++ b/async_db/src/db.rs @@ -3,6 +3,7 @@ use failure::Error; use futures::Future; use r2d2; use r2d2_sqlite; +use rusqlite::NO_PARAMS; use serde_derive::{Deserialize, Serialize}; use std::{thread::sleep, time::Duration}; @@ -47,7 +48,7 @@ fn get_hottest_years(conn: Connection) -> Result, Error> { let mut prep_stmt = conn.prepare(stmt)?; let annuals = prep_stmt - .query_map(&[], |row| WeatherAgg::AnnualAgg { + .query_map(NO_PARAMS, |row| WeatherAgg::AnnualAgg { year: row.get(0), total: row.get(1), }) @@ -73,7 +74,7 @@ fn get_coldest_years(conn: Connection) -> Result, Error> { let mut prep_stmt = conn.prepare(stmt)?; let annuals = prep_stmt - .query_map(&[], |row| WeatherAgg::AnnualAgg { + .query_map(NO_PARAMS, |row| WeatherAgg::AnnualAgg { year: row.get(0), total: row.get(1), }) @@ -99,7 +100,7 @@ fn get_hottest_months(conn: Connection) -> Result, Error> { let mut prep_stmt = conn.prepare(stmt)?; let annuals = prep_stmt - .query_map(&[], |row| WeatherAgg::MonthAgg { + .query_map(NO_PARAMS, |row| WeatherAgg::MonthAgg { year: row.get(0), month: row.get(1), total: row.get(2), @@ -125,7 +126,7 @@ fn get_coldest_months(conn: Connection) -> Result, Error> { let mut prep_stmt = conn.prepare(stmt)?; let annuals = prep_stmt - .query_map(&[], |row| WeatherAgg::MonthAgg { + .query_map(NO_PARAMS, |row| WeatherAgg::MonthAgg { year: row.get(0), month: row.get(1), total: row.get(2), diff --git a/async_ex1/Cargo.toml b/async_ex1/Cargo.toml index 01a79760..f89f97b5 100644 --- a/async_ex1/Cargo.toml +++ b/async_ex1/Cargo.toml @@ -7,7 +7,6 @@ workspace = ".." [dependencies] actix-rt = "0.2" -actix-http = { git="https://github.com/actix/actix-http.git", features=["ssl"] } actix-web = { git="https://github.com/actix/actix-web.git", features=["ssl"] } futures = "0.1" diff --git a/async_ex1/src/main.rs b/async_ex1/src/main.rs index 8781ce9c..a9eb054b 100644 --- a/async_ex1/src/main.rs +++ b/async_ex1/src/main.rs @@ -23,7 +23,7 @@ extern crate serde_derive; use std::collections::HashMap; use std::io; -use actix_http::client; +use actix_web::client::Client; use actix_web::web::BytesMut; use actix_web::{web, App, Error, HttpResponse, HttpServer}; use futures::{Future, Stream}; @@ -54,14 +54,14 @@ struct HttpBinResponse { // ----------------------------------------------------------------------- /// post json to httpbin, get it back in the response body, return deserialized -fn step_x_v1(data: SomeData) -> Box> { - let mut connector = client::Connector::new().service(); - +fn step_x_v1( + data: SomeData, + client: &Client, +) -> Box> { Box::new( - client::ClientRequest::post("https://httpbin.org/post") - .json(data) - .unwrap() - .send(&mut connector) + client + .post("https://httpbin.org/post") + .send_json(data) .map_err(Error::from) // <- convert SendRequestError to an Error .and_then(|resp| { resp // <- this is MessageBody type, resolves to complete body @@ -81,17 +81,20 @@ fn step_x_v1(data: SomeData) -> Box> { fn create_something_v1( some_data: web::Json, + client: web::Data, ) -> Box> { - Box::new(step_x_v1(some_data.into_inner()).and_then(|some_data_2| { - step_x_v1(some_data_2).and_then(|some_data_3| { - step_x_v1(some_data_3).and_then(|d| { - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(serde_json::to_string(&d).unwrap()) - .into()) + Box::new( + step_x_v1(some_data.into_inner(), &client).and_then(move |some_data_2| { + step_x_v1(some_data_2, &client).and_then(move |some_data_3| { + step_x_v1(some_data_3, &client).and_then(|d| { + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(serde_json::to_string(&d).unwrap()) + .into()) + }) }) - }) - })) + }), + ) } // --------------------------------------------------------------- @@ -99,13 +102,13 @@ fn create_something_v1( // --------------------------------------------------------------- /// post json to httpbin, get it back in the response body, return deserialized -fn step_x_v2(data: SomeData) -> impl Future { - let mut connector = client::Connector::new().service(); - - client::ClientRequest::post("https://httpbin.org/post") - .json(data) - .unwrap() - .send(&mut connector) +fn step_x_v2( + data: SomeData, + client: &Client, +) -> impl Future { + client + .post("https://httpbin.org/post") + .send_json(data) .map_err(Error::from) // <- convert SendRequestError to an Error .and_then(|resp| { resp.from_err() @@ -122,10 +125,11 @@ fn step_x_v2(data: SomeData) -> impl Future { fn create_something_v2( some_data: web::Json, + client: web::Data, ) -> impl Future { - step_x_v2(some_data.into_inner()).and_then(|some_data_2| { - step_x_v2(some_data_2).and_then(|some_data_3| { - step_x_v2(some_data_3).and_then(|d| { + step_x_v2(some_data.into_inner(), &client).and_then(move |some_data_2| { + step_x_v2(some_data_2, &client).and_then(move |some_data_3| { + step_x_v2(some_data_3, &client).and_then(|d| { Ok(HttpResponse::Ok() .content_type("application/json") .body(serde_json::to_string(&d).unwrap()) @@ -141,6 +145,7 @@ fn main() -> io::Result<()> { HttpServer::new(|| { App::new() + .data(Client::default()) .service( web::resource("/something_v1") .route(web::post().to(create_something_v1)), diff --git a/http-full-proxy/Cargo.toml b/http-full-proxy/Cargo.toml index f9363344..b7686cfe 100644 --- a/http-full-proxy/Cargo.toml +++ b/http-full-proxy/Cargo.toml @@ -2,10 +2,13 @@ name = "http-full-proxy" version = "0.1.0" authors = ["Rotem Yaari"] +workspace = ".." +edition = "2018" [dependencies] -actix = "0.7.5" -actix-web = "0.7.13" +actix-rt = "0.2" +actix-web = { git="https://github.com/actix/actix-web.git" } + clap = "2.32.0" futures = "0.1.25" failure = "0.1.3" diff --git a/http-full-proxy/src/main.rs b/http-full-proxy/src/main.rs index 05bfb394..f350769e 100644 --- a/http-full-proxy/src/main.rs +++ b/http-full-proxy/src/main.rs @@ -1,85 +1,53 @@ -#![deny(warnings)] -extern crate actix; -extern crate actix_web; -extern crate clap; -extern crate failure; -extern crate futures; -extern crate url; - -use actix_web::{ - client, http, server, App, AsyncResponder, Error, HttpMessage, HttpRequest, - HttpResponse, -}; +use actix_web::client::Client; +use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer}; use clap::{value_t, Arg}; -use futures::{future, Future}; +use futures::Future; use std::net::ToSocketAddrs; use url::Url; -struct AppState { - forward_url: Url, -} - -impl AppState { - pub fn init(forward_url: Url) -> AppState { - AppState { forward_url } - } -} - fn forward( - req: &HttpRequest, -) -> Box> { - let mut new_url = req.state().forward_url.clone(); + req: HttpRequest, + payload: web::Payload, + url: web::Data, + client: web::Data, +) -> impl Future { + let mut new_url = url.get_ref().clone(); new_url.set_path(req.uri().path()); new_url.set_query(req.uri().query()); - let mut forwarded_req = client::ClientRequest::build_from(req) - .no_default_headers() - .uri(new_url) - .streaming(req.payload()) - .unwrap(); + let forwarded_req = client + .request_from(new_url.as_str(), &req) + .no_default_headers(); - if let Some(addr) = req.peer_addr() { - match forwarded_req.headers_mut().entry("x-forwarded-for") { - Ok(http::header::Entry::Vacant(entry)) => { - let addr = format!("{}", addr.ip()); - entry.insert(addr.parse().unwrap()); - } - Ok(http::header::Entry::Occupied(mut entry)) => { - let addr = format!("{}, {}", entry.get().to_str().unwrap(), addr.ip()); - entry.insert(addr.parse().unwrap()); - } - _ => unreachable!(), - } - } + // if let Some(addr) = req.peer_addr() { + // match forwarded_req.headers_mut().entry("x-forwarded-for") { + // Ok(http::header::Entry::Vacant(entry)) => { + // let addr = format!("{}", addr.ip()); + // entry.insert(addr.parse().unwrap()); + // } + // Ok(http::header::Entry::Occupied(mut entry)) => { + // let addr = format!("{}, {}", entry.get().to_str().unwrap(), addr.ip()); + // entry.insert(addr.parse().unwrap()); + // } + // _ => unreachable!(), + // } + // } forwarded_req - .send() + .send_stream(payload) .map_err(Error::from) - .and_then(construct_response) - .responder() + .map(|res| { + let mut client_resp = HttpResponse::build(res.status()); + for (header_name, header_value) in + res.headers().iter().filter(|(h, _)| *h != "connection") + { + client_resp.header(header_name.clone(), header_value.clone()); + } + client_resp.streaming(res) + }) } -fn construct_response( - resp: client::ClientResponse, -) -> Box> { - let mut client_resp = HttpResponse::build(resp.status()); - for (header_name, header_value) in - resp.headers().iter().filter(|(h, _)| *h != "connection") - { - client_resp.header(header_name.clone(), header_value.clone()); - } - if resp.chunked().unwrap_or(false) { - Box::new(future::ok(client_resp.streaming(resp.payload()))) - } else { - Box::new( - resp.body() - .from_err() - .and_then(move |body| Ok(client_resp.body(body))), - ) - } -} - -fn main() { +fn main() -> std::io::Result<()> { let matches = clap::App::new("HTTP Proxy") .arg( Arg::with_name("listen_addr") @@ -128,14 +96,13 @@ fn main() { )) .unwrap(); - server::new(move || { - App::with_state(AppState::init(forward_url.clone())).default_resource(|r| { - r.f(forward); - }) + HttpServer::new(move || { + App::new() + .data(forward_url.clone()) + .wrap(middleware::Logger::default()) + .default_resource(|r| r.to_async(forward)) }) - .workers(32) - .bind((listen_addr, listen_port)) - .expect("Cannot bind listening port") + .bind((listen_addr, listen_port))? .system_exit() - .run(); + .run() } diff --git a/http-proxy/Cargo.toml b/http-proxy/Cargo.toml index b06a5946..ca1176d4 100644 --- a/http-proxy/Cargo.toml +++ b/http-proxy/Cargo.toml @@ -2,7 +2,8 @@ name = "http-proxy" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +edition = "2018" +workspace = ".." [[bin]] name = "proxy" @@ -13,8 +14,8 @@ name = "proxy-example-server" path = "src/server.rs" [dependencies] +actix-rt = "0.2" +actix-web = { git="https://github.com/actix/actix-web.git" } + env_logger = "0.5" futures = "0.1" - -actix = "0.7" -actix-web = "^0.7" diff --git a/http-proxy/src/main.rs b/http-proxy/src/main.rs index 9d51aceb..080c848d 100644 --- a/http-proxy/src/main.rs +++ b/http-proxy/src/main.rs @@ -1,19 +1,11 @@ -extern crate actix; -extern crate actix_web; -extern crate env_logger; -extern crate futures; - -use actix_web::{ - client, middleware, server, App, AsyncResponder, Body, Error, HttpMessage, - HttpRequest, HttpResponse, -}; -use futures::{Future, Stream}; +use actix_web::client::Client; +use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer}; +use futures::Future; /// Stream client request response and then send body to a server response -fn index(_req: &HttpRequest) -> Box> { - client::ClientRequest::get("http://127.0.0.1:8081/") - .finish() - .unwrap() +fn index(client: web::Data) -> impl Future { + client + .get("http://127.0.0.1:8081/") .send() .map_err(Error::from) // <- convert SendRequestError to an Error .and_then(|resp| { @@ -24,15 +16,15 @@ fn index(_req: &HttpRequest) -> Box> Ok(HttpResponse::Ok().body(body)) }) }) - .responder() } /// streaming client request to a streaming server response -fn streaming(_req: &HttpRequest) -> Box> { +fn streaming( + client: web::Data, +) -> impl Future> { // send client request - client::ClientRequest::get("https://www.rust-lang.org/en-US/") - .finish() - .unwrap() + client + .get("https://www.rust-lang.org/en-US/") .send() // <- connect to host and send request .map_err(Error::from) // <- convert SendRequestError to an Error .and_then(|resp| { @@ -40,27 +32,21 @@ fn streaming(_req: &HttpRequest) -> Box std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_server=info,actix_web=trace"); env_logger::init(); - let sys = actix::System::new("http-proxy"); - server::new(|| { + HttpServer::new(|| { App::new() - .middleware(middleware::Logger::default()) - .resource("/streaming", |r| r.f(streaming)) - .resource("/", |r| r.f(index)) + .data(Client::new()) + .wrap(middleware::Logger::default()) + .service(web::resource("/streaming").to_async(streaming)) + .service(web::resource("/").to_async(index)) }) - .workers(1) - .bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } diff --git a/http-proxy/src/server.rs b/http-proxy/src/server.rs index 11584def..a8e7559e 100644 --- a/http-proxy/src/server.rs +++ b/http-proxy/src/server.rs @@ -1,35 +1,20 @@ -extern crate actix; -extern crate actix_web; -extern crate env_logger; -extern crate futures; +use actix_web::{middleware, web, App, HttpResponse, HttpServer, Responder}; -use actix_web::*; -use futures::Future; - -fn index(req: &HttpRequest) -> FutureResponse { - req.body() - .from_err() - .map(|bytes| HttpResponse::Ok().body(bytes)) - .responder() +fn index(body: web::Bytes) -> impl Responder { + HttpResponse::Ok().body(body) } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=error"); - let _ = env_logger::init(); - let sys = actix::System::new("ws-example"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_server=info,actix_web=trace"); + env_logger::init(); - server::new(|| { + HttpServer::new(|| { App::new() // enable logger - .middleware(middleware::Logger::default()) - .resource("/index.html", |r| r.f(|_| "Hello world!")) - .resource("/", |r| r.f(index)) + .wrap(middleware::Logger::default()) + .service(web::resource("/index.html").to(|| "Hello world!")) + .service(web::resource("/").to(index)) }) - .workers(1) - .bind("127.0.0.1:8081") - .unwrap() - .start(); - - println!("Started http server: 127.0.0.1:8081"); - let _ = sys.run(); + .bind("127.0.0.1:8081")? + .run() } From e4f71e8fd521c726c3c1d25f0fdbcce305ddc340 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 29 Mar 2019 13:43:03 -0700 Subject: [PATCH 22/23] update deps --- actix_redis/Cargo.toml | 10 +- actix_redis/src/main.rs | 82 ++++++--------- actix_todo/Cargo.toml | 6 +- async_db/Cargo.toml | 2 +- async_ex1/Cargo.toml | 2 +- basics/Cargo.toml | 6 +- cookie-auth/Cargo.toml | 2 +- cookie-session/Cargo.toml | 4 +- diesel/Cargo.toml | 2 +- error_handling/Cargo.toml | 2 +- form/Cargo.toml | 2 +- hello-world/Cargo.toml | 2 +- http-full-proxy/Cargo.toml | 2 +- http-proxy/Cargo.toml | 2 +- json/Cargo.toml | 2 +- juniper/Cargo.toml | 2 +- middleware/Cargo.toml | 2 +- multipart/Cargo.toml | 11 +- multipart/src/main.rs | 103 ++++++++----------- r2d2/Cargo.toml | 4 +- redis-session/Cargo.toml | 12 ++- redis-session/src/main.rs | 42 +++----- simple-auth-server/Cargo.toml | 12 ++- simple-auth-server/src/app.rs | 56 ---------- simple-auth-server/src/auth_handler.rs | 25 +++-- simple-auth-server/src/auth_routes.rs | 34 +++--- simple-auth-server/src/email_service.rs | 2 +- simple-auth-server/src/errors.rs | 9 +- simple-auth-server/src/invitation_handler.rs | 7 +- simple-auth-server/src/invitation_routes.rs | 21 ++-- simple-auth-server/src/main.rs | 97 +++++++++++------ simple-auth-server/src/models.rs | 2 +- simple-auth-server/src/register_handler.rs | 11 +- simple-auth-server/src/register_routes.rs | 22 ++-- simple-auth-server/src/utils.rs | 13 ++- state/Cargo.toml | 5 +- static_index/Cargo.toml | 4 +- template_askama/Cargo.toml | 2 +- template_askama/src/main.rs | 3 - template_tera/Cargo.toml | 4 +- template_yarte/Cargo.toml | 4 +- tls/Cargo.toml | 7 +- web-cors/backend/Cargo.toml | 9 +- web-cors/backend/src/main.rs | 44 +++----- web-cors/backend/src/user.rs | 8 +- websocket/Cargo.toml | 8 +- websocket/src/client.rs | 9 +- 47 files changed, 307 insertions(+), 415 deletions(-) delete mode 100644 simple-auth-server/src/app.rs diff --git a/actix_redis/Cargo.toml b/actix_redis/Cargo.toml index a716e624..b8014247 100644 --- a/actix_redis/Cargo.toml +++ b/actix_redis/Cargo.toml @@ -2,13 +2,15 @@ name = "actix_redis" version = "0.1.0" authors = ["dowwie "] +edition = "2018" +workspace = ".." [dependencies] -actix = "0.7.3" -actix-web = "0.7.3" -actix-redis = "0.5.1" +actix = "0.8.0-alpha.2" +actix-web = "1.0.0-alpha.1" +actix-redis = { git="https://github.com/actix/actix-redis.git" } futures = "0.1.23" redis-async = "0.4.0" serde = "1.0.71" serde_derive = "1.0.71" -env_logger = "0.5.12" +env_logger = "0.6" diff --git a/actix_redis/src/main.rs b/actix_redis/src/main.rs index e8072a21..a9ed3c4c 100644 --- a/actix_redis/src/main.rs +++ b/actix_redis/src/main.rs @@ -1,23 +1,13 @@ -extern crate actix; -extern crate actix_redis; -extern crate actix_web; -extern crate env_logger; -extern crate futures; #[macro_use] extern crate redis_async; -extern crate serde; #[macro_use] extern crate serde_derive; use actix::prelude::*; use actix_redis::{Command, Error as ARError, RedisActor}; -use actix_web::{ - http::Method, middleware, server, App, AsyncResponder, Error as AWError, - HttpRequest, HttpResponse, Json, -}; +use actix_web::{middleware, web, App, Error as AWError, HttpResponse, HttpServer}; use futures::future::{join_all, Future}; use redis_async::resp::RespValue; -use std::sync::Arc; #[derive(Deserialize)] pub struct CacheInfo { @@ -27,10 +17,10 @@ pub struct CacheInfo { } fn cache_stuff( - (info, req): (Json, HttpRequest), + info: web::Json, + redis: web::Data>, ) -> impl Future { 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 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()); info_set - .map_err(AWError::from) - .and_then(|res: Vec>| - // successful operations return "OK", so confirm that all returned as so - if !res.iter().all(|res| match res { - Ok(RespValue::SimpleString(x)) if x=="OK" => true, - _ => false - }) { - Ok(HttpResponse::InternalServerError().finish()) - } else { - Ok(HttpResponse::Ok().body("successfully cached values")) - } - ) - .responder() + .map_err(AWError::from) + .and_then(|res: Vec>| + // successful operations return "OK", so confirm that all returned as so + if !res.iter().all(|res| match res { + Ok(RespValue::SimpleString(x)) if x=="OK" => true, + _ => false + }) { + Ok(HttpResponse::InternalServerError().finish()) + } else { + Ok(HttpResponse::Ok().body("successfully cached values")) + } + ) } fn del_stuff( - req: HttpRequest, + redis: web::Data>, ) -> impl Future { - let redis = req.state().redis_addr.clone(); - redis .send(Command(resp_array![ "DEL", @@ -83,33 +70,24 @@ fn del_stuff( Ok(HttpResponse::InternalServerError().finish()) } }) - .responder() } -pub struct AppState { - pub redis_addr: Arc>, -} - -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info"); env_logger::init(); - let sys = actix::System::new("actix_redis_ex"); - server::new(|| { - let redis_addr = Arc::new(RedisActor::start("127.0.0.1:6379")); - let app_state = AppState { redis_addr }; + HttpServer::new(|| { + let redis_addr = RedisActor::start("127.0.0.1:6379"); - App::with_state(app_state) - .middleware(middleware::Logger::default()) - .resource("/stuff", |r| { - r.method(Method::POST).with_async(cache_stuff); - r.method(Method::DELETE).with_async(del_stuff) - }) + App::new() + .data(redis_addr) + .wrap(middleware::Logger::default()) + .service( + web::resource("/stuff") + .route(web::post().to_async(cache_stuff)) + .route(web::delete().to_async(del_stuff)), + ) }) - .bind("0.0.0.0:8080") - .unwrap() - .workers(1) - .start(); - - let _ = sys.run(); + .bind("0.0.0.0:8080")? + .run() } diff --git a/actix_todo/Cargo.toml b/actix_todo/Cargo.toml index 736178d1..17a35307 100644 --- a/actix_todo/Cargo.toml +++ b/actix_todo/Cargo.toml @@ -6,9 +6,9 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git" } -actix-files = { git="https://github.com/actix/actix-web.git" } -actix-session = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" +actix-files = "0.1.0-alpha.1" +actix-session = "0.1.0-alpha.1" dotenv = "0.13.0" env_logger = "0.5.10" futures = "0.1.22" diff --git a/async_db/Cargo.toml b/async_db/Cargo.toml index 7848d1b7..2d322de3 100644 --- a/async_db/Cargo.toml +++ b/async_db/Cargo.toml @@ -7,7 +7,7 @@ workspace = ".." [dependencies] actix-rt = "0.2" -actix-web = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" dotenv = "0.10" env_logger = "0.5" diff --git a/async_ex1/Cargo.toml b/async_ex1/Cargo.toml index f89f97b5..1be43ae9 100644 --- a/async_ex1/Cargo.toml +++ b/async_ex1/Cargo.toml @@ -7,7 +7,7 @@ workspace = ".." [dependencies] 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" serde = "1.0.43" diff --git a/basics/Cargo.toml b/basics/Cargo.toml index 0147e333..4eb17bcc 100644 --- a/basics/Cargo.toml +++ b/basics/Cargo.toml @@ -7,9 +7,9 @@ edition = "2018" [dependencies] actix-rt = "0.2" -actix-web = { git="https://github.com/actix/actix-web.git" } -actix-files = { git="https://github.com/actix/actix-web.git" } -actix-session = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" +actix-files = "0.1.0-alpha.1" +actix-session = "0.1.0-alpha.1" futures = "0.1.25" env_logger = "0.5" diff --git a/cookie-auth/Cargo.toml b/cookie-auth/Cargo.toml index efeb709c..d728e3ed 100644 --- a/cookie-auth/Cargo.toml +++ b/cookie-auth/Cargo.toml @@ -6,5 +6,5 @@ edition = "2018" workspace = ".." [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" env_logger = "0.6" diff --git a/cookie-session/Cargo.toml b/cookie-session/Cargo.toml index d7bee4dd..ce876957 100644 --- a/cookie-session/Cargo.toml +++ b/cookie-session/Cargo.toml @@ -6,8 +6,8 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git" } -actix-session = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" +actix-session = "0.1.0-alpha.1" futures = "0.1" time = "0.1" diff --git a/diesel/Cargo.toml b/diesel/Cargo.toml index 4089a877..d8dfb918 100644 --- a/diesel/Cargo.toml +++ b/diesel/Cargo.toml @@ -6,7 +6,7 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" bytes = "0.4" env_logger = "0.6" diff --git a/error_handling/Cargo.toml b/error_handling/Cargo.toml index c4cb0973..7e05407c 100644 --- a/error_handling/Cargo.toml +++ b/error_handling/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" workspace = ".." [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" derive_more = "0.14.0" futures = "0.1.23" diff --git a/form/Cargo.toml b/form/Cargo.toml index a849fed4..150b9417 100644 --- a/form/Cargo.toml +++ b/form/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" workspace = ".." [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" serde = "1.0" serde_derive = "1.0" diff --git a/hello-world/Cargo.toml b/hello-world/Cargo.toml index d3d38429..502b1410 100644 --- a/hello-world/Cargo.toml +++ b/hello-world/Cargo.toml @@ -6,5 +6,5 @@ workspace = ".." edition = "2018" [dependencies] +actix-web = "1.0.0-alpha.1" env_logger = "0.6" -actix-web = { git="https://github.com/actix/actix-web.git" } diff --git a/http-full-proxy/Cargo.toml b/http-full-proxy/Cargo.toml index b7686cfe..f906fdd2 100644 --- a/http-full-proxy/Cargo.toml +++ b/http-full-proxy/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] 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" futures = "0.1.25" diff --git a/http-proxy/Cargo.toml b/http-proxy/Cargo.toml index ca1176d4..487d4580 100644 --- a/http-proxy/Cargo.toml +++ b/http-proxy/Cargo.toml @@ -15,7 +15,7 @@ path = "src/server.rs" [dependencies] 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" futures = "0.1" diff --git a/json/Cargo.toml b/json/Cargo.toml index c5d09827..82b525c8 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -6,7 +6,7 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" bytes = "0.4" futures = "0.1" diff --git a/juniper/Cargo.toml b/juniper/Cargo.toml index 07ac6365..ff47263a 100644 --- a/juniper/Cargo.toml +++ b/juniper/Cargo.toml @@ -6,7 +6,7 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" env_logger = "0.6" futures = "0.1" serde = "1.0" diff --git a/middleware/Cargo.toml b/middleware/Cargo.toml index 7905b56c..c5657087 100644 --- a/middleware/Cargo.toml +++ b/middleware/Cargo.toml @@ -7,6 +7,6 @@ workspace = ".." [dependencies] 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" env_logger = "0.6" \ No newline at end of file diff --git a/multipart/Cargo.toml b/multipart/Cargo.toml index 771e28f7..994c80fc 100644 --- a/multipart/Cargo.toml +++ b/multipart/Cargo.toml @@ -2,15 +2,16 @@ name = "multipart-example" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [[bin]] name = "multipart" path = "src/main.rs" [dependencies] -env_logger = "*" -futures = "0.1" +#actix-web = "1.0.0-alpha.1" +actix-web = { git="https://github.com/actix/actix-web.git" } -actix = "0.7" -actix-web = "0.7" +env_logger = "0.6" +futures = "0.1.25" diff --git a/multipart/src/main.rs b/multipart/src/main.rs index 37c17bf6..40f22d38 100644 --- a/multipart/src/main.rs +++ b/multipart/src/main.rs @@ -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::fs; use std::io::Write; -use actix_web::{ - dev, error, http, middleware, multipart, server, App, Error, FutureResponse, - HttpMessage, HttpRequest, HttpResponse, -}; - -use futures::future; +use actix_web::{error, middleware, web, App, Error, HttpResponse, HttpServer}; +use futures::future::{err, Either}; use futures::{Future, Stream}; pub struct AppState { pub counter: Cell, } -pub fn save_file( - field: multipart::Field, -) -> Box> { +pub fn save_file(field: web::MultipartField) -> impl Future { let file_path_string = "upload.png"; let mut file = match fs::File::create(file_path_string) { 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 .fold(0i64, move |acc, bytes| { - let rt = file - .write_all(bytes.as_ref()) + file.write_all(bytes.as_ref()) .map(|_| acc + bytes.len() as i64) .map_err(|e| { println!("file.write_all failed: {:?}", e); error::MultipartError::Payload(error::PayloadError::Io(e)) - }); - future::result(rt) + }) }) .map_err(|e| { println!("save_file failed, {:?}", e); @@ -48,13 +34,11 @@ pub fn save_file( } pub fn handle_multipart_item( - item: multipart::MultipartItem, + item: web::MultipartItem, ) -> Box> { match item { - multipart::MultipartItem::Field(field) => { - Box::new(save_file(field).into_stream()) - } - multipart::MultipartItem::Nested(mp) => Box::new( + web::MultipartItem::Field(field) => Box::new(save_file(field).into_stream()), + web::MultipartItem::Nested(mp) => Box::new( mp.map_err(error::ErrorInternalServerError) .map(handle_multipart_item) .flatten(), @@ -62,24 +46,26 @@ pub fn handle_multipart_item( } } -pub fn upload(req: HttpRequest) -> FutureResponse { - req.state().counter.set(req.state().counter.get() + 1); - println!("{:?}", req.state().counter.get()); - Box::new( - req.multipart() - .map_err(error::ErrorInternalServerError) - .map(handle_multipart_item) - .flatten() - .collect() - .map(|sizes| HttpResponse::Ok().json(sizes)) - .map_err(|e| { - println!("failed: {}", e); - e - }), - ) +pub fn upload( + multipart: web::Multipart, + counter: web::Data>, +) -> impl Future { + counter.set(counter.get() + 1); + println!("{:?}", counter.get()); + + multipart + .map_err(error::ErrorInternalServerError) + .map(handle_multipart_item) + .flatten() + .collect() + .map(|sizes| HttpResponse::Ok().json(sizes)) + .map_err(|e| { + println!("failed: {}", e); + e + }) } -fn index(_req: HttpRequest) -> Result { +fn index() -> HttpResponse { let html = r#" Upload Test @@ -90,28 +76,23 @@ fn index(_req: HttpRequest) -> Result { "#; - Ok(HttpResponse::Ok().body(html)) + HttpResponse::Ok().body(html) } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info"); env_logger::init(); - let sys = actix::System::new("multipart-example"); - server::new(|| { - App::with_state(AppState { - counter: Cell::new(0), - }) - .middleware(middleware::Logger::default()) - .resource("/", |r| { - r.method(http::Method::GET).with(index); - r.method(http::Method::POST).with(upload); - }) + HttpServer::new(|| { + App::new() + .data(Cell::new(0usize)) + .wrap(middleware::Logger::default()) + .service( + web::resource("/") + .route(web::get().to(index)) + .route(web::post().to_async(upload)), + ) }) - .bind("127.0.0.1:8080") - .unwrap() - .start(); - - println!("Starting http server: 127.0.0.1:8080"); - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } diff --git a/r2d2/Cargo.toml b/r2d2/Cargo.toml index a0b5e037..0f6d7b57 100644 --- a/r2d2/Cargo.toml +++ b/r2d2/Cargo.toml @@ -3,11 +3,11 @@ name = "r2d2-example" version = "0.1.0" authors = ["Nikolay Kim "] edition = "2018" -workspace = "../" +workspace = ".." [dependencies] actix-rt = "0.2" -actix-web = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" futures = "0.1" env_logger = "0.6" diff --git a/redis-session/Cargo.toml b/redis-session/Cargo.toml index 8b6152a6..5198d902 100644 --- a/redis-session/Cargo.toml +++ b/redis-session/Cargo.toml @@ -2,10 +2,12 @@ name = "redis-session" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [dependencies] -env_logger = "0.5" -actix = "0.7" -actix-web = "0.7.3" -actix-redis = { version = "0.5.1", features = ["web"] } +actix = "0.8.0-alpha.2" +actix-web = "1.0.0-alpha.1" +actix-session = "0.1.0-alpha.1" +actix-redis = { git = "https://github.com/actix/actix-redis.git", features = ["web"] } +env_logger = "0.6" diff --git a/redis-session/src/main.rs b/redis-session/src/main.rs index 18a68e15..0c49c6bf 100644 --- a/redis-session/src/main.rs +++ b/redis-session/src/main.rs @@ -1,50 +1,38 @@ //! Example of redis based session //! //! [User guide](https://actix.rs/book/actix-web/sec-9-middlewares.html#user-sessions) -extern crate actix; -extern crate actix_redis; -extern crate actix_web; -extern crate env_logger; - -use actix_redis::RedisSessionBackend; -use actix_web::middleware::session::{RequestSession, SessionStorage}; -use actix_web::{middleware, server, App, HttpRequest, HttpResponse, Result}; +use actix_redis::RedisSession; +use actix_session::Session; +use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer, Result}; /// simple handler -fn index(req: &HttpRequest) -> Result { +fn index(req: HttpRequest, session: Session) -> Result { println!("{:?}", req); // session - if let Some(count) = req.session().get::("counter")? { + if let Some(count) = session.get::("counter")? { println!("SESSION value: {}", count); - req.session().set("counter", count + 1)?; + session.set("counter", count + 1)?; } else { - req.session().set("counter", 1)?; + session.set("counter", 1)?; } Ok("Welcome!".into()) } -fn main() { - ::std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info,actix_redis=info"); env_logger::init(); - let sys = actix::System::new("basic-example"); - server::new(|| { + HttpServer::new(|| { App::new() // enable logger - .middleware(middleware::Logger::default()) + .wrap(middleware::Logger::default()) // redis session middleware - .middleware(SessionStorage::new(RedisSessionBackend::new( - "127.0.0.1:6379", - &[0; 32], - ))) + .wrap(RedisSession::new("127.0.0.1:6379", &[0; 32])) // register simple route, handle all methods - .resource("/", |r| r.f(index)) + .service(web::resource("/").to(index)) }) - .bind("127.0.0.1:8080") - .unwrap() - .start(); - - let _ = sys.run(); + .bind("127.0.0.1:8080")? + .run() } diff --git a/simple-auth-server/Cargo.toml b/simple-auth-server/Cargo.toml index 25ba9407..0c6a42be 100644 --- a/simple-auth-server/Cargo.toml +++ b/simple-auth-server/Cargo.toml @@ -2,18 +2,22 @@ name = "simple-auth-server" version = "0.1.0" authors = ["mygnu "] +edition = "2018" +workspace = ".." [dependencies] -actix = "0.7.7" -actix-web = "0.7.14" +actix = { version = "0.8.0-alpha.2", features = ["http"] } +actix-web = "1.0.0-alpha.1" +actix-files = "0.1.0-alpha.1" + bcrypt = "0.2.1" chrono = { version = "0.4.6", features = ["serde"] } diesel = { version = "1.3.3", features = ["postgres", "uuid", "r2d2", "chrono"] } dotenv = "0.13.0" +derive_more = "0.14" env_logger = "0.6.0" -failure = "0.1.3" jsonwebtoken = "5.0" -futures = "0.1" +futures = "0.1.25" r2d2 = "0.8.3" serde_derive="1.0.80" serde_json="1.0" diff --git a/simple-auth-server/src/app.rs b/simple-auth-server/src/app.rs deleted file mode 100644 index 05fdf2f7..00000000 --- a/simple-auth-server/src/app.rs +++ /dev/null @@ -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, -} - -/// creates and returns the app after mounting all routes/resources -pub fn create_app(db: Addr) -> App { - // 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"), - ) -} diff --git a/simple-auth-server/src/auth_handler.rs b/simple-auth-server/src/auth_handler.rs index 161a951f..13eb1476 100644 --- a/simple-auth-server/src/auth_handler.rs +++ b/simple-auth-server/src/auth_handler.rs @@ -1,10 +1,12 @@ 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 diesel::prelude::*; -use errors::ServiceError; -use models::{DbExecutor, SlimUser, User}; -use utils::decode_token; + +use crate::errors::ServiceError; +use crate::models::{DbExecutor, SlimUser, User}; +use crate::utils::decode_token; #[derive(Debug, Deserialize)] pub struct AuthData { @@ -19,7 +21,7 @@ impl Message for AuthData { impl Handler for DbExecutor { type Result = 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 mut items = users.filter(email.eq(&msg.email)).load::(conn)?; @@ -44,14 +46,15 @@ impl Handler for DbExecutor { // simple aliasing makes the intentions clear and its more readable pub type LoggedUser = SlimUser; -impl FromRequest for LoggedUser { - type Config = (); - type Result = Result; - fn from_request(req: &HttpRequest, _: &Self::Config) -> Self::Result { - if let Some(identity) = req.identity() { +impl

FromRequest

for LoggedUser { + type Error = Error; + type Future = Result; + + fn from_request(req: &mut ServiceFromRequest

) -> Self::Future { + if let Some(identity) = Identity::from_request(req)?.identity() { let user: SlimUser = decode_token(&identity)?; return Ok(user as LoggedUser); } - Err(ServiceError::Unauthorized) + Err(ServiceError::Unauthorized.into()) } } diff --git a/simple-auth-server/src/auth_routes.rs b/simple-auth-server/src/auth_routes.rs index 90cafec4..269c3a67 100644 --- a/simple-auth-server/src/auth_routes.rs +++ b/simple-auth-server/src/auth_routes.rs @@ -1,34 +1,32 @@ -use actix_web::middleware::identity::RequestIdentity; -use actix_web::{ - AsyncResponder, FutureResponse, HttpRequest, HttpResponse, Json, ResponseError, -}; -use futures::future::Future; -use utils::create_token; +use actix::Addr; +use actix_web::middleware::identity::Identity; +use actix_web::{web, Error, HttpRequest, HttpResponse, Responder, ResponseError}; +use futures::Future; -use app::AppState; -use auth_handler::{AuthData, LoggedUser}; +use crate::auth_handler::{AuthData, LoggedUser}; +use crate::models::DbExecutor; +use crate::utils::create_token; pub fn login( - (auth_data, req): (Json, HttpRequest), -) -> FutureResponse { - req.state() - .db - .send(auth_data.into_inner()) + auth_data: web::Json, + id: Identity, + db: web::Data>, +) -> impl Future { + db.send(auth_data.into_inner()) .from_err() .and_then(move |res| match res { Ok(user) => { let token = create_token(&user)?; - req.remember(token); + id.remember(token); Ok(HttpResponse::Ok().into()) } Err(err) => Ok(err.error_response()), }) - .responder() } -pub fn logout(req: HttpRequest) -> HttpResponse { - req.forget(); - HttpResponse::Ok().into() +pub fn logout(id: Identity) -> impl Responder { + id.forget(); + HttpResponse::Ok() } pub fn get_me(logged_user: LoggedUser) -> HttpResponse { diff --git a/simple-auth-server/src/email_service.rs b/simple-auth-server/src/email_service.rs index d9854f49..290d37ab 100644 --- a/simple-auth-server/src/email_service.rs +++ b/simple-auth-server/src/email_service.rs @@ -1,4 +1,4 @@ -use models::Invitation; +use crate::models::Invitation; use sparkpost::transmission::{ EmailAddress, Message, Options, Recipient, Transmission, TransmissionResponse, }; diff --git a/simple-auth-server/src/errors.rs b/simple-auth-server/src/errors.rs index 0be63125..bac56094 100644 --- a/simple-auth-server/src/errors.rs +++ b/simple-auth-server/src/errors.rs @@ -1,17 +1,18 @@ use actix_web::{error::ResponseError, HttpResponse}; +use derive_more::Display; use diesel::result::{DatabaseErrorKind, Error}; use std::convert::From; use uuid::ParseError; -#[derive(Fail, Debug)] +#[derive(Debug, Display)] pub enum ServiceError { - #[fail(display = "Internal Server Error")] + #[display(fmt = "Internal Server Error")] InternalServerError, - #[fail(display = "BadRequest: {}", _0)] + #[display(fmt = "BadRequest: {}", _0)] BadRequest(String), - #[fail(display = "Unauthorized")] + #[display(fmt = "Unauthorized")] Unauthorized, } diff --git a/simple-auth-server/src/invitation_handler.rs b/simple-auth-server/src/invitation_handler.rs index ac117f79..b0a8ceb7 100644 --- a/simple-auth-server/src/invitation_handler.rs +++ b/simple-auth-server/src/invitation_handler.rs @@ -1,10 +1,11 @@ use actix::{Handler, Message}; use chrono::{Duration, Local}; use diesel::{self, prelude::*}; -use errors::ServiceError; -use models::{DbExecutor, Invitation}; use uuid::Uuid; +use crate::errors::ServiceError; +use crate::models::{DbExecutor, Invitation}; + #[derive(Deserialize)] pub struct CreateInvitation { pub email: String, @@ -18,7 +19,7 @@ impl Handler for DbExecutor { type Result = 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(); // creating a new Invitation object with expired at time that is 24 hours from now diff --git a/simple-auth-server/src/invitation_routes.rs b/simple-auth-server/src/invitation_routes.rs index bd6a46c6..ea76bca2 100644 --- a/simple-auth-server/src/invitation_routes.rs +++ b/simple-auth-server/src/invitation_routes.rs @@ -1,18 +1,16 @@ -use actix_web::{ - AsyncResponder, FutureResponse, HttpResponse, Json, ResponseError, State, -}; +use actix::Addr; +use actix_web::{web, Error, HttpResponse, ResponseError}; use futures::future::Future; -use app::AppState; -use email_service::send_invitation; -use invitation_handler::CreateInvitation; +use crate::email_service::send_invitation; +use crate::invitation_handler::CreateInvitation; +use crate::models::DbExecutor; pub fn register_email( - (signup_invitation, state): (Json, State), -) -> FutureResponse { - state - .db - .send(signup_invitation.into_inner()) + signup_invitation: web::Json, + db: web::Data>, +) -> impl Future { + db.send(signup_invitation.into_inner()) .from_err() .and_then(|db_response| match db_response { Ok(invitation) => { @@ -21,5 +19,4 @@ pub fn register_email( } Err(err) => Ok(err.error_response()), }) - .responder() } diff --git a/simple-auth-server/src/main.rs b/simple-auth-server/src/main.rs index 5c1b3c27..90024095 100644 --- a/simple-auth-server/src/main.rs +++ b/simple-auth-server/src/main.rs @@ -1,26 +1,21 @@ -// to avoid the warning from diesel macros -#![allow(proc_macro_derive_resolution_fallback)] +#![allow(unused_imports)] -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] extern crate diesel; #[macro_use] 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_routes; mod email_service; @@ -33,20 +28,17 @@ mod register_routes; mod schema; mod utils; -use actix::prelude::*; -use actix_web::server; -use diesel::{r2d2::ConnectionManager, PgConnection}; -use dotenv::dotenv; -use models::DbExecutor; -use std::env; +use crate::models::DbExecutor; -fn main() { +fn main() -> std::io::Result<()> { dotenv().ok(); - std::env::set_var("RUST_LOG", "simple-auth-server=debug,actix_web=info"); - std::env::set_var("RUST_BACKTRACE", "1"); + std::env::set_var( + "RUST_LOG", + "simple-auth-server=debug,actix_web=info,actix_server=info", + ); 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 let manager = ConnectionManager::::new(database_url); @@ -57,10 +49,49 @@ fn main() { let address: Addr = SyncArbiter::start(4, move || DbExecutor(pool.clone())); - server::new(move || app::create_app(address.clone())) - .bind("127.0.0.1:3000") - .expect("Can not bind to '127.0.0.1:3000'") - .start(); + HttpServer::new(move || { + // 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()); - 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() } diff --git a/simple-auth-server/src/models.rs b/simple-auth-server/src/models.rs index 651ad9f3..76dcfac7 100644 --- a/simple-auth-server/src/models.rs +++ b/simple-auth-server/src/models.rs @@ -5,7 +5,7 @@ use diesel::r2d2::{ConnectionManager, Pool}; use std::convert::From; use uuid::Uuid; -use schema::{invitations, users}; +use crate::schema::{invitations, users}; /// This is db executor actor. can be run in parallel pub struct DbExecutor(pub Pool>); diff --git a/simple-auth-server/src/register_handler.rs b/simple-auth-server/src/register_handler.rs index 961061b0..04fe164e 100644 --- a/simple-auth-server/src/register_handler.rs +++ b/simple-auth-server/src/register_handler.rs @@ -1,11 +1,12 @@ use actix::{Handler, Message}; use chrono::Local; use diesel::prelude::*; -use errors::ServiceError; -use models::{DbExecutor, Invitation, SlimUser, User}; -use utils::hash_password; 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 #[derive(Debug, Deserialize)] pub struct UserData { @@ -26,8 +27,8 @@ impl Message for RegisterUser { impl Handler for DbExecutor { type Result = Result; fn handle(&mut self, msg: RegisterUser, _: &mut Self::Context) -> Self::Result { - use schema::invitations::dsl::{id, invitations}; - use schema::users::dsl::users; + use crate::schema::invitations::dsl::{id, invitations}; + use crate::schema::users::dsl::users; let conn: &PgConnection = &self.0.get().unwrap(); // try parsing the string provided by the user as url parameter diff --git a/simple-auth-server/src/register_routes.rs b/simple-auth-server/src/register_routes.rs index 79b9f9a2..19b3866f 100644 --- a/simple-auth-server/src/register_routes.rs +++ b/simple-auth-server/src/register_routes.rs @@ -1,27 +1,25 @@ -use actix_web::{ - AsyncResponder, FutureResponse, HttpResponse, Json, Path, ResponseError, State, -}; -use futures::future::Future; +use actix::Addr; +use actix_web::{web, Error, HttpResponse, ResponseError}; +use futures::Future; -use app::AppState; -use register_handler::{RegisterUser, UserData}; +use crate::models::DbExecutor; +use crate::register_handler::{RegisterUser, UserData}; pub fn register_user( - (invitation_id, user_data, state): (Path, Json, State), -) -> FutureResponse { + invitation_id: web::Path, + user_data: web::Json, + db: web::Data>, +) -> impl Future { let msg = RegisterUser { // into_inner() returns the inner string value from Path invitation_id: invitation_id.into_inner(), password: user_data.password.clone(), }; - state - .db - .send(msg) + db.send(msg) .from_err() .and_then(|db_response| match db_response { Ok(slim_user) => Ok(HttpResponse::Ok().json(slim_user)), Err(service_error) => Ok(service_error.error_response()), }) - .responder() } diff --git a/simple-auth-server/src/utils.rs b/simple-auth-server/src/utils.rs index 1f65d3e8..37035277 100644 --- a/simple-auth-server/src/utils.rs +++ b/simple-auth-server/src/utils.rs @@ -1,14 +1,13 @@ use bcrypt::{hash, DEFAULT_COST}; use chrono::{Duration, Local}; -use errors::ServiceError; -use jwt::{decode, encode, Header, Validation}; -use models::SlimUser; -use std::convert::From; -use std::env; +use jsonwebtoken::{decode, encode, Header, Validation}; + +use crate::errors::ServiceError; +use crate::models::SlimUser; pub fn hash_password(plain: &str) -> Result { // 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), _ => DEFAULT_COST, }; @@ -64,5 +63,5 @@ pub fn decode_token(token: &str) -> Result { } 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()) } diff --git a/state/Cargo.toml b/state/Cargo.toml index 39bf08a7..962b35d8 100644 --- a/state/Cargo.toml +++ b/state/Cargo.toml @@ -6,7 +6,6 @@ workspace = ".." edition = "2018" [dependencies] -actix-web = { git="https://github.com/actix/actix-web.git" } - -futures = "0.1" +actix-web = "1.0.0-alpha.1" +futures = "0.1.25" env_logger = "0.6" diff --git a/static_index/Cargo.toml b/static_index/Cargo.toml index 2dcdba30..6ae309a8 100644 --- a/static_index/Cargo.toml +++ b/static_index/Cargo.toml @@ -9,5 +9,5 @@ edition = "2018" futures = "0.1" env_logger = "0.5" -actix-web = { git="https://github.com/actix/actix-web.git" } -actix-files = { git="https://github.com/actix/actix-web.git" } +actix-web = "1.0.0-alpha.1" +actix-files = "0.1.0-alpha.1" diff --git a/template_askama/Cargo.toml b/template_askama/Cargo.toml index 242087ac..68ca3a9f 100644 --- a/template_askama/Cargo.toml +++ b/template_askama/Cargo.toml @@ -6,9 +6,9 @@ workspace = ".." edition = "2018" [dependencies] +actix-web = "1.0.0-alpha.1" env_logger = "0.6" askama = "0.6" -actix-web = { git="https://github.com/actix/actix-web.git" } [build-dependencies] askama = "0.6" diff --git a/template_askama/src/main.rs b/template_askama/src/main.rs index b27e94af..b07879ab 100644 --- a/template_askama/src/main.rs +++ b/template_askama/src/main.rs @@ -1,6 +1,3 @@ -#[macro_use] -extern crate askama; - use std::collections::HashMap; use actix_web::{web, App, HttpResponse, HttpServer, Result}; diff --git a/template_tera/Cargo.toml b/template_tera/Cargo.toml index ff35ad15..81ecb160 100644 --- a/template_tera/Cargo.toml +++ b/template_tera/Cargo.toml @@ -7,5 +7,5 @@ edition = "2018" [dependencies] env_logger = "0.6" -tera = "*" -actix-web = { git="https://github.com/actix/actix-web.git" } +tera = "0.11" +actix-web = "1.0.0-alpha.1" diff --git a/template_yarte/Cargo.toml b/template_yarte/Cargo.toml index 47a03b22..328052ee 100644 --- a/template_yarte/Cargo.toml +++ b/template_yarte/Cargo.toml @@ -4,14 +4,12 @@ version = "0.0.1" authors = ["Rust-iendo Barcelona "] publish = false edition = "2018" - workspace = ".." [dependencies] +actix-web = "1.0.0-alpha.1" env_logger = "0.6" - yarte = "0.1" -actix-web = { git="https://github.com/actix/actix-web.git" } [build-dependencies] yarte = "0.1" diff --git a/tls/Cargo.toml b/tls/Cargo.toml index 0442f206..6e9be047 100644 --- a/tls/Cargo.toml +++ b/tls/Cargo.toml @@ -10,8 +10,7 @@ name = "tls-server" path = "src/main.rs" [dependencies] -env_logger = "0.5" -openssl = { version="0.10" } - 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" } diff --git a/web-cors/backend/Cargo.toml b/web-cors/backend/Cargo.toml index f78d7adc..c50eb197 100644 --- a/web-cors/backend/Cargo.toml +++ b/web-cors/backend/Cargo.toml @@ -3,16 +3,13 @@ name = "actix-web-cors" version = "0.1.0" authors = ["krircc "] workspace = "../../" +edition = "2018" [dependencies] +actix-web = "1.0.0-alpha.1" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -http = "0.1" - -actix = "0.7" -actix-web = "0.7" - dotenv = "0.10" -env_logger = "0.5" +env_logger = "0.6" futures = "0.1" diff --git a/web-cors/backend/src/main.rs b/web-cors/backend/src/main.rs index 2fcec25b..5d951e03 100644 --- a/web-cors/backend/src/main.rs +++ b/web-cors/backend/src/main.rs @@ -1,49 +1,29 @@ #[macro_use] 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::{ - http::{header, Method}, - middleware, - middleware::cors::Cors, - server, App, + http::header, middleware::cors::Cors, middleware::Logger, web, App, HttpServer, }; -use std::env; mod user; -use user::info; -fn main() { - env::set_var("RUST_LOG", "actix_web=info"); +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); - let sys = actix::System::new("Actix-web-CORS"); - - server::new(move || { + HttpServer::new(move || { App::new() - .middleware(middleware::Logger::default()) - .configure(|app| { - Cors::for_app(app) + .wrap( + Cors::new() .allowed_origin("http://localhost:1234") .allowed_methods(vec!["GET", "POST"]) .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT]) .allowed_header(header::CONTENT_TYPE) - .max_age(3600) - .resource("/user/info", |r| { - r.method(Method::POST).with(info); - }) - .register() - }) + .max_age(3600), + ) + .wrap(Logger::default()) + .service(web::resource("/user/info").route(web::post().to(user::info))) }) - .bind("127.0.0.1:8000") - .unwrap() - .shutdown_timeout(2) - .start(); - - let _ = sys.run(); + .bind("127.0.0.1:8000")? + .run() } diff --git a/web-cors/backend/src/user.rs b/web-cors/backend/src/user.rs index aca44cbf..ed795589 100644 --- a/web-cors/backend/src/user.rs +++ b/web-cors/backend/src/user.rs @@ -1,4 +1,4 @@ -use actix_web::{Json, Result}; +use actix_web::web; #[derive(Deserialize, Serialize, Debug)] pub struct Info { @@ -8,12 +8,12 @@ pub struct Info { confirm_password: String, } -pub fn info(info: Json) -> Result> { +pub fn info(info: web::Json) -> web::Json { println!("=========={:?}=========", info); - Ok(Json(Info { + web::Json(Info { username: info.username.clone(), email: info.email.clone(), password: info.password.clone(), confirm_password: info.confirm_password.clone(), - })) + }) } diff --git a/websocket/Cargo.toml b/websocket/Cargo.toml index a68b058f..2ceab26e 100644 --- a/websocket/Cargo.toml +++ b/websocket/Cargo.toml @@ -14,10 +14,10 @@ path = "src/main.rs" #path = "src/client.rs" [dependencies] -actix = { git="https://github.com/actix/actix.git" } -actix-web = { git="https://github.com/actix/actix-web.git" } -actix-web-actors = { git="https://github.com/actix/actix-web.git" } -actix-files = { git="https://github.com/actix/actix-web.git" } +actix = "0.8.0-alpha.1" +actix-web = "1.0.0-alpha.1" +actix-web-actors = "1.0.0-alpha.1" +actix-files = "0.1.0-alpha.1" env_logger = "0.6" futures = "0.1" bytes = "0.4" \ No newline at end of file diff --git a/websocket/src/client.rs b/websocket/src/client.rs index 7cb5fa3b..11f827bb 100644 --- a/websocket/src/client.rs +++ b/websocket/src/client.rs @@ -1,16 +1,9 @@ //! 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::{io, thread}; use actix::*; -use actix_web::ws::{Client, ClientWriter, Message, ProtocolError}; +use actix_web::client::{Client, ClientWriter, Message, ProtocolError}; use futures::Future; fn main() { From 769cc5b84e86bcf2665762e63c702a76696b3605 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 29 Mar 2019 15:08:35 -0700 Subject: [PATCH 23/23] upgrade ws examples --- basics/Cargo.toml | 2 +- websocket-chat/Cargo.toml | 19 +++--- websocket-chat/src/main.rs | 99 +++++++++++---------------- websocket-tcp-chat/Cargo.toml | 16 +++-- websocket-tcp-chat/src/main.rs | 109 ++++++++++++------------------ websocket-tcp-chat/src/server.rs | 2 +- websocket-tcp-chat/src/session.rs | 12 ++-- 7 files changed, 111 insertions(+), 148 deletions(-) diff --git a/basics/Cargo.toml b/basics/Cargo.toml index 4eb17bcc..64c08aa1 100644 --- a/basics/Cargo.toml +++ b/basics/Cargo.toml @@ -2,7 +2,7 @@ name = "basics" version = "1.0.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." edition = "2018" [dependencies] diff --git a/websocket-chat/Cargo.toml b/websocket-chat/Cargo.toml index b6d281ff..64c7876e 100644 --- a/websocket-chat/Cargo.toml +++ b/websocket-chat/Cargo.toml @@ -2,23 +2,24 @@ name = "websocket-example" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [[bin]] name = "websocket-chat-server" path = "src/main.rs" [dependencies] -rand = "*" +actix = "0.8.0-alpha.2" +actix-web = "1.0.0-alpha.1" +actix-web-actors = "1.0.0-alpha.1" +actix-files = "0.1.0-alpha.1" + +rand = "0.6" bytes = "0.4" byteorder = "1.1" -futures = "0.1" +futures = "0.1.25" tokio-io = "0.1" -tokio-core = "0.1" -env_logger = "*" - +env_logger = "0.6" serde = "1.0" serde_json = "1.0" - -actix = "0.7" -actix-web = "0.7" diff --git a/websocket-chat/src/main.rs b/websocket-chat/src/main.rs index 8849aba7..45085f7c 100644 --- a/websocket-chat/src/main.rs +++ b/websocket-chat/src/main.rs @@ -1,22 +1,9 @@ -#![allow(unused_variables)] -extern crate byteorder; -extern crate bytes; -extern crate env_logger; -extern crate futures; -extern crate rand; -extern crate serde; -extern crate serde_json; -extern crate tokio_core; -extern crate tokio_io; - -extern crate actix; -extern crate actix_web; - use std::time::{Duration, Instant}; use actix::*; -use actix_web::server::HttpServer; -use actix_web::{fs, http, ws, App, Error, HttpRequest, HttpResponse}; +use actix_files as fs; +use actix_web::{web, App, Error, HttpRequest, HttpResponse, HttpServer}; +use actix_web_actors::ws; mod server; @@ -25,22 +12,22 @@ const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); /// How long before lack of client response causes a timeout const CLIENT_TIMEOUT: Duration = Duration::from_secs(10); -/// This is our websocket route state, this state is shared with all route -/// instances via `HttpContext::state()` -struct WsChatSessionState { - addr: Addr, -} - /// Entry point for our route -fn chat_route(req: &HttpRequest) -> Result { +fn chat_route( + req: HttpRequest, + stream: web::Payload, + srv: web::Data>, +) -> Result { ws::start( - req, WsChatSession { id: 0, hb: Instant::now(), room: "Main".to_owned(), name: None, + addr: srv.get_ref().clone(), }, + &req, + stream, ) } @@ -54,10 +41,12 @@ struct WsChatSession { room: String, /// peer name name: Option, + /// Chat server + addr: Addr, } impl Actor for WsChatSession { - type Context = ws::WebsocketContext; + type Context = ws::WebsocketContext; /// Method is called on actor start. /// We register ws session with ChatServer @@ -71,8 +60,7 @@ impl Actor for WsChatSession { // HttpContext::state() is instance of WsChatSessionState, state is shared // across all routes within application let addr = ctx.address(); - ctx.state() - .addr + self.addr .send(server::Connect { addr: addr.recipient(), }) @@ -88,9 +76,9 @@ impl Actor for WsChatSession { .wait(ctx); } - fn stopping(&mut self, ctx: &mut Self::Context) -> Running { + fn stopping(&mut self, _: &mut Self::Context) -> Running { // notify chat server - ctx.state().addr.do_send(server::Disconnect { id: self.id }); + self.addr.do_send(server::Disconnect { id: self.id }); Running::Stop } } @@ -126,8 +114,7 @@ impl StreamHandler for WsChatSession { // Send ListRooms message to chat server and wait for // response println!("List rooms"); - ctx.state() - .addr + self.addr .send(server::ListRooms) .into_actor(self) .then(|res, _, ctx| { @@ -149,7 +136,7 @@ impl StreamHandler for WsChatSession { "/join" => { if v.len() == 2 { self.room = v[1].to_owned(); - ctx.state().addr.do_send(server::Join { + self.addr.do_send(server::Join { id: self.id, name: self.room.clone(), }); @@ -175,14 +162,14 @@ impl StreamHandler for WsChatSession { m.to_owned() }; // send message to chat server - ctx.state().addr.do_send(server::ClientMessage { + self.addr.do_send(server::ClientMessage { id: self.id, msg: msg, room: self.room.clone(), }) } } - ws::Message::Binary(bin) => println!("Unexpected binary"), + ws::Message::Binary(_) => println!("Unexpected binary"), ws::Message::Close(_) => { ctx.stop(); } @@ -194,7 +181,7 @@ impl WsChatSession { /// helper method that sends ping to client every second. /// /// also this method checks heartbeats from client - fn hb(&self, ctx: &mut ws::WebsocketContext) { + fn hb(&self, ctx: &mut ws::WebsocketContext) { ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| { // check client heartbeats if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT { @@ -202,7 +189,7 @@ impl WsChatSession { println!("Websocket Client heartbeat failed, disconnecting!"); // notify chat server - ctx.state().addr.do_send(server::Disconnect { id: act.id }); + act.addr.do_send(server::Disconnect { id: act.id }); // stop actor ctx.stop(); @@ -216,38 +203,30 @@ impl WsChatSession { } } -fn main() { - let _ = env_logger::init(); - let sys = actix::System::new("websocket-example"); +fn main() -> std::io::Result<()> { + env_logger::init(); + let sys = System::new("ws-example"); - // Start chat server actor in separate thread - let server = Arbiter::start(|_| server::ChatServer::default()); + // Start chat server actor + let server = server::ChatServer::default().start(); // Create Http server with websocket support HttpServer::new(move || { - // Websocket sessions state - let state = WsChatSessionState { - addr: server.clone(), - }; - - App::with_state(state) + App::new() + .data(server.clone()) // redirect to websocket.html - .resource("/", |r| { - r.method(http::Method::GET).f(|_| { - HttpResponse::Found() - .header("LOCATION", "/static/websocket.html") - .finish() - }) - }) + .service(web::resource("/").route(web::get().to(|| { + HttpResponse::Found() + .header("LOCATION", "/static/websocket.html") + .finish() + }))) // websocket - .resource("/ws/", |r| r.route().f(chat_route)) + .service(web::resource("/ws/").to(chat_route)) // static resources - .handler("/static/", fs::StaticFiles::new("static/").unwrap()) + .service(fs::Files::new("/static/", "static/")) }) - .bind("127.0.0.1:8080") - .unwrap() + .bind("127.0.0.1:8080")? .start(); - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + sys.run() } diff --git a/websocket-tcp-chat/Cargo.toml b/websocket-tcp-chat/Cargo.toml index c73d5678..b4a06eb7 100644 --- a/websocket-tcp-chat/Cargo.toml +++ b/websocket-tcp-chat/Cargo.toml @@ -2,7 +2,8 @@ name = "websocket-tcp-example" version = "0.1.0" authors = ["Nikolay Kim "] -workspace = "../" +workspace = ".." +edition = "2018" [[bin]] name = "websocket-tcp-server" @@ -13,18 +14,19 @@ name = "websocket-tcp-client" path = "src/client.rs" [dependencies] -rand = "*" +actix = "0.8.0-alpha.2" +actix-web = "1.0.0-alpha.1" +actix-web-actors = "1.0.0-alpha.1" +actix-files = "0.1.0-alpha.1" + +rand = "0.6" bytes = "0.4" byteorder = "1.1" futures = "0.1" tokio-io = "0.1" tokio-tcp = "0.1" tokio-codec = "0.1" -env_logger = "*" - +env_logger = "0.6" serde = "1.0" serde_json = "1.0" serde_derive = "1.0" - -actix = "0.7" -actix-web = "0.7" diff --git a/websocket-tcp-chat/src/main.rs b/websocket-tcp-chat/src/main.rs index dff734c8..cd96c40b 100644 --- a/websocket-tcp-chat/src/main.rs +++ b/websocket-tcp-chat/src/main.rs @@ -1,25 +1,14 @@ -#![allow(unused_variables)] -extern crate byteorder; -extern crate bytes; -extern crate env_logger; -extern crate futures; -extern crate rand; -extern crate serde; -extern crate serde_json; -extern crate tokio_codec; -extern crate tokio_io; -extern crate tokio_tcp; #[macro_use] extern crate serde_derive; - #[macro_use] extern crate actix; -extern crate actix_web; + +use std::time::{Duration, Instant}; use actix::*; -use actix_web::server::HttpServer; -use actix_web::{fs, http, ws, App, Error, HttpRequest, HttpResponse}; -use std::time::{Duration, Instant}; +use actix_files as fs; +use actix_web::{web, App, Error, HttpRequest, HttpResponse, HttpServer}; +use actix_web_actors::ws; mod codec; mod server; @@ -30,22 +19,22 @@ const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); /// How long before lack of client response causes a timeout const CLIENT_TIMEOUT: Duration = Duration::from_secs(10); -/// This is our websocket route state, this state is shared with all route -/// instances via `HttpContext::state()` -struct WsChatSessionState { - addr: Addr, -} - /// Entry point for our route -fn chat_route(req: &HttpRequest) -> Result { +fn chat_route( + req: HttpRequest, + stream: web::Payload, + srv: web::Data>, +) -> Result { ws::start( - req, WsChatSession { id: 0, hb: Instant::now(), room: "Main".to_owned(), name: None, + addr: srv.get_ref().clone(), }, + &req, + stream, ) } @@ -59,26 +48,26 @@ struct WsChatSession { room: String, /// peer name name: Option, + /// Chat server + addr: Addr, } impl Actor for WsChatSession { - type Context = ws::WebsocketContext; + type Context = ws::WebsocketContext; /// Method is called on actor start. /// We register ws session with ChatServer fn started(&mut self, ctx: &mut Self::Context) { + // we'll start heartbeat process on session start. + self.hb(ctx); + // register self in chat server. `AsyncContext::wait` register // future within context, but context waits until this future resolves // before processing any other events. // HttpContext::state() is instance of WsChatSessionState, state is shared // across all routes within application - - // we'll start heartbeat process on session start. - self.hb(ctx); - let addr = ctx.address(); - ctx.state() - .addr + self.addr .send(server::Connect { addr: addr.recipient(), }) @@ -94,9 +83,9 @@ impl Actor for WsChatSession { .wait(ctx); } - fn stopping(&mut self, ctx: &mut Self::Context) -> Running { + fn stopping(&mut self, _: &mut Self::Context) -> Running { // notify chat server - ctx.state().addr.do_send(server::Disconnect { id: self.id }); + self.addr.do_send(server::Disconnect { id: self.id }); Running::Stop } } @@ -132,8 +121,7 @@ impl StreamHandler for WsChatSession { // Send ListRooms message to chat server and wait for // response println!("List rooms"); - ctx.state() - .addr + self.addr .send(server::ListRooms) .into_actor(self) .then(|res, _, ctx| { @@ -155,7 +143,7 @@ impl StreamHandler for WsChatSession { "/join" => { if v.len() == 2 { self.room = v[1].to_owned(); - ctx.state().addr.do_send(server::Join { + self.addr.do_send(server::Join { id: self.id, name: self.room.clone(), }); @@ -181,14 +169,14 @@ impl StreamHandler for WsChatSession { m.to_owned() }; // send message to chat server - ctx.state().addr.do_send(server::Message { + self.addr.do_send(server::Message { id: self.id, msg: msg, room: self.room.clone(), }) } } - ws::Message::Binary(bin) => println!("Unexpected binary"), + ws::Message::Binary(_) => println!("Unexpected binary"), ws::Message::Close(_) => { ctx.stop(); } @@ -200,7 +188,7 @@ impl WsChatSession { /// helper method that sends ping to client every second. /// /// also this method checks heartbeats from client - fn hb(&self, ctx: &mut ws::WebsocketContext) { + fn hb(&self, ctx: &mut ws::WebsocketContext) { ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| { // check client heartbeats if Instant::now().duration_since(act.hb) > CLIENT_TIMEOUT { @@ -208,7 +196,7 @@ impl WsChatSession { println!("Websocket Client heartbeat failed, disconnecting!"); // notify chat server - ctx.state().addr.do_send(server::Disconnect { id: act.id }); + act.addr.do_send(server::Disconnect { id: act.id }); // stop actor ctx.stop(); @@ -222,45 +210,38 @@ impl WsChatSession { } } -fn main() { +fn main() -> std::io::Result<()> { let _ = env_logger::init(); let sys = actix::System::new("websocket-example"); - // Start chat server actor in separate thread - let server = Arbiter::start(|_| server::ChatServer::default()); + // Start chat server actor + let server = server::ChatServer::default().start(); // Start tcp server in separate thread let srv = server.clone(); - Arbiter::new("tcp-server").do_send::(msgs::Execute::new(move || { + Arbiter::new().exec(move || { session::TcpServer::new("127.0.0.1:12345", srv); - Ok(()) - })); + Ok::<_, ()>(()) + }); // Create Http server with websocket support HttpServer::new(move || { - // Websocket sessions state - let state = WsChatSessionState { - addr: server.clone(), - }; - - App::with_state(state) + App::new() + .data(server.clone()) // redirect to websocket.html - .resource("/", |r| { - r.method(http::Method::GET).f(|_| { - HttpResponse::Found() - .header("LOCATION", "/static/websocket.html") - .finish() - }) - }) + .service(web::resource("/").route(web::get().to(|| { + HttpResponse::Found() + .header("LOCATION", "/static/websocket.html") + .finish() + }))) // websocket - .resource("/ws/", |r| r.route().f(chat_route)) + .service(web::resource("/ws/").to(chat_route)) // static resources - .handler("/static/", fs::StaticFiles::new("static/").unwrap()) + .service(fs::Files::new("/static/", "static/")) }) - .bind("127.0.0.1:8080") - .unwrap() + .bind("127.0.0.1:8080")? .start(); println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); + sys.run() } diff --git a/websocket-tcp-chat/src/server.rs b/websocket-tcp-chat/src/server.rs index efc946a8..c30b928b 100644 --- a/websocket-tcp-chat/src/server.rs +++ b/websocket-tcp-chat/src/server.rs @@ -6,7 +6,7 @@ use actix::prelude::*; use rand::{self, rngs::ThreadRng, Rng}; use std::collections::{HashMap, HashSet}; -use session; +use crate::session; /// Message for chat server communications diff --git a/websocket-tcp-chat/src/session.rs b/websocket-tcp-chat/src/session.rs index 37bd33a9..27478794 100644 --- a/websocket-tcp-chat/src/session.rs +++ b/websocket-tcp-chat/src/session.rs @@ -11,8 +11,8 @@ use tokio_tcp::{TcpListener, TcpStream}; use actix::prelude::*; -use codec::{ChatCodec, ChatRequest, ChatResponse}; -use server::{self, ChatServer}; +use crate::codec::{ChatCodec, ChatRequest, ChatResponse}; +use crate::server::{self, ChatServer}; /// Chat server sends this messages to session #[derive(Message)] @@ -62,7 +62,7 @@ impl Actor for ChatSession { .wait(ctx); } - fn stopping(&mut self, ctx: &mut Self::Context) -> Running { + fn stopping(&mut self, _: &mut Self::Context) -> Running { // notify chat server self.addr.do_send(server::Disconnect { id: self.id }); Running::Stop @@ -82,7 +82,7 @@ impl StreamHandler for ChatSession { self.addr .send(server::ListRooms) .into_actor(self) - .then(|res, act, ctx| { + .then(|res, act, _| { match res { Ok(rooms) => { act.framed.write(ChatResponse::Rooms(rooms)); @@ -124,7 +124,7 @@ impl StreamHandler for ChatSession { impl Handler for ChatSession { type Result = (); - fn handle(&mut self, msg: Message, ctx: &mut Context) { + fn handle(&mut self, msg: Message, _: &mut Context) { // send message to peer self.framed.write(ChatResponse::Message(msg.0)); } @@ -175,7 +175,7 @@ pub struct TcpServer { } impl TcpServer { - pub fn new(s: &str, chat: Addr) { + pub fn new(_s: &str, chat: Addr) { // Create server listener let addr = net::SocketAddr::from_str("127.0.0.1:12345").unwrap(); let listener = TcpListener::bind(&addr).unwrap();