mirror of
https://github.com/actix/examples
synced 2024-11-23 14:31:07 +01:00
upgrade example to actix-web 0.7
This commit is contained in:
parent
0b52c7850e
commit
2cc1b23761
946
Cargo.lock
generated
946
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -4,8 +4,10 @@ version = "0.1.0"
|
||||
authors = ["Darin Gordon <dkcdkg@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
dotenv = "0.10"
|
||||
env_logger = "0.5"
|
||||
failure = "0.1.1"
|
||||
|
@ -1,31 +1,28 @@
|
||||
use actix::prelude::*;
|
||||
use std::{time::Duration, thread::sleep};
|
||||
use failure::Error;
|
||||
use r2d2;
|
||||
use r2d2_sqlite;
|
||||
|
||||
use std::{thread::sleep, time::Duration};
|
||||
|
||||
pub type Pool = r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>;
|
||||
pub type Connection = r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
|
||||
|
||||
|
||||
pub struct DbExecutor(pub Pool);
|
||||
impl Actor for DbExecutor {
|
||||
type Context = SyncContext<Self>;
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum WeatherAgg {
|
||||
AnnualAgg { year: i32, total: f64 },
|
||||
MonthAgg {year: i32, month: i32, total: f64}
|
||||
MonthAgg { year: i32, month: i32, total: f64 },
|
||||
}
|
||||
|
||||
pub enum Queries {
|
||||
GetTopTenHottestYears,
|
||||
GetTopTenColdestYears,
|
||||
GetTopTenHottestMonths,
|
||||
GetTopTenColdestMonths
|
||||
GetTopTenColdestMonths,
|
||||
}
|
||||
|
||||
//pub struct GetTopTenHottestYears;
|
||||
@ -56,13 +53,17 @@ fn get_hottest_years(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
||||
GROUP BY theyear
|
||||
ORDER BY total DESC LIMIT 10;";
|
||||
|
||||
|
||||
let mut prep_stmt = conn.prepare(stmt)?;
|
||||
let annuals = prep_stmt.query_map(&[], |row| {
|
||||
WeatherAgg::AnnualAgg{year: row.get(0),
|
||||
total: row.get(1)}})
|
||||
.and_then(|mapped_rows|
|
||||
Ok(mapped_rows.map(|row| row.unwrap()).collect::<Vec<WeatherAgg>>()))?;
|
||||
let annuals = prep_stmt
|
||||
.query_map(&[], |row| WeatherAgg::AnnualAgg {
|
||||
year: row.get(0),
|
||||
total: row.get(1),
|
||||
})
|
||||
.and_then(|mapped_rows| {
|
||||
Ok(mapped_rows
|
||||
.map(|row| row.unwrap())
|
||||
.collect::<Vec<WeatherAgg>>())
|
||||
})?;
|
||||
|
||||
sleep(Duration::from_secs(2));
|
||||
|
||||
@ -79,11 +80,16 @@ fn get_coldest_years(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
||||
ORDER BY total ASC LIMIT 10;";
|
||||
|
||||
let mut prep_stmt = conn.prepare(stmt)?;
|
||||
let annuals = prep_stmt.query_map(&[], |row| {
|
||||
WeatherAgg::AnnualAgg{year: row.get(0),
|
||||
total: row.get(1)}})
|
||||
.and_then(|mapped_rows|
|
||||
Ok(mapped_rows.map(|row| row.unwrap()).collect::<Vec<WeatherAgg>>()))?;
|
||||
let annuals = prep_stmt
|
||||
.query_map(&[], |row| WeatherAgg::AnnualAgg {
|
||||
year: row.get(0),
|
||||
total: row.get(1),
|
||||
})
|
||||
.and_then(|mapped_rows| {
|
||||
Ok(mapped_rows
|
||||
.map(|row| row.unwrap())
|
||||
.collect::<Vec<WeatherAgg>>())
|
||||
})?;
|
||||
|
||||
sleep(Duration::from_secs(2));
|
||||
|
||||
@ -91,8 +97,7 @@ fn get_coldest_years(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
||||
}
|
||||
|
||||
fn get_hottest_months(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
||||
let stmt =
|
||||
"SELECT cast(strftime('%Y', date) as int) as theyear,
|
||||
let stmt = "SELECT cast(strftime('%Y', date) as int) as theyear,
|
||||
cast(strftime('%m', date) as int) as themonth,
|
||||
sum(tmax) as total
|
||||
FROM nyc_weather
|
||||
@ -101,20 +106,24 @@ fn get_hottest_months(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
||||
ORDER BY total DESC LIMIT 10;";
|
||||
|
||||
let mut prep_stmt = conn.prepare(stmt)?;
|
||||
let annuals = prep_stmt.query_map(&[], |row| {
|
||||
WeatherAgg::MonthAgg{year: row.get(0),
|
||||
let annuals = prep_stmt
|
||||
.query_map(&[], |row| WeatherAgg::MonthAgg {
|
||||
year: row.get(0),
|
||||
month: row.get(1),
|
||||
total: row.get(2)}})
|
||||
.and_then(|mapped_rows|
|
||||
Ok(mapped_rows.map(|row| row.unwrap()).collect::<Vec<WeatherAgg>>()))?;
|
||||
total: row.get(2),
|
||||
})
|
||||
.and_then(|mapped_rows| {
|
||||
Ok(mapped_rows
|
||||
.map(|row| row.unwrap())
|
||||
.collect::<Vec<WeatherAgg>>())
|
||||
})?;
|
||||
|
||||
sleep(Duration::from_secs(2));
|
||||
Ok(annuals)
|
||||
}
|
||||
|
||||
fn get_coldest_months(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
||||
let stmt =
|
||||
"SELECT cast(strftime('%Y', date) as int) as theyear,
|
||||
let stmt = "SELECT cast(strftime('%Y', date) as int) as theyear,
|
||||
cast(strftime('%m', date) as int) as themonth,
|
||||
sum(tmax) as total
|
||||
FROM nyc_weather
|
||||
@ -123,12 +132,17 @@ fn get_coldest_months(conn: Connection) -> Result<Vec<WeatherAgg>, Error> {
|
||||
ORDER BY total ASC LIMIT 10;";
|
||||
|
||||
let mut prep_stmt = conn.prepare(stmt)?;
|
||||
let annuals = prep_stmt.query_map(&[], |row| {
|
||||
WeatherAgg::MonthAgg{year: row.get(0),
|
||||
let annuals = prep_stmt
|
||||
.query_map(&[], |row| WeatherAgg::MonthAgg {
|
||||
year: row.get(0),
|
||||
month: row.get(1),
|
||||
total: row.get(2)}})
|
||||
.and_then(|mapped_rows|
|
||||
Ok(mapped_rows.map(|row| row.unwrap()).collect::<Vec<WeatherAgg>>()))?;
|
||||
total: row.get(2),
|
||||
})
|
||||
.and_then(|mapped_rows| {
|
||||
Ok(mapped_rows
|
||||
.map(|row| row.unwrap())
|
||||
.collect::<Vec<WeatherAgg>>())
|
||||
})?;
|
||||
|
||||
sleep(Duration::from_secs(2));
|
||||
Ok(annuals)
|
||||
|
@ -10,7 +10,7 @@ This project illustrates two examples:
|
||||
|
||||
*/
|
||||
|
||||
#[macro_use] extern crate actix;
|
||||
extern crate actix;
|
||||
extern crate actix_web;
|
||||
extern crate env_logger;
|
||||
extern crate failure;
|
||||
@ -19,42 +19,52 @@ extern crate num_cpus;
|
||||
extern crate r2d2;
|
||||
extern crate r2d2_sqlite;
|
||||
extern crate serde;
|
||||
#[macro_use] extern crate serde_derive;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
|
||||
use actix::prelude::*;
|
||||
use actix_web::{
|
||||
http, middleware, server, App, AsyncResponder, FutureResponse, HttpResponse,
|
||||
State, Error as AWError
|
||||
http, middleware, server, App, AsyncResponder, Error as AWError, FutureResponse,
|
||||
HttpResponse, State,
|
||||
};
|
||||
use std::error::Error as StdError;
|
||||
use failure::Error;
|
||||
use futures::future::{Future, join_all, ok as fut_ok, err as fut_err};
|
||||
use futures::future::{join_all, ok as fut_ok, Future};
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
|
||||
mod db;
|
||||
use db::{DbExecutor, Queries, WeatherAgg, Pool};
|
||||
use db::{DbExecutor, Pool, Queries, WeatherAgg};
|
||||
|
||||
/// State with DbExecutor address
|
||||
struct AppState {
|
||||
db: Addr<Syn, DbExecutor>,
|
||||
db: Addr<DbExecutor>,
|
||||
}
|
||||
|
||||
|
||||
/// Version 1: Calls 4 queries in sequential order, as an asynchronous handler
|
||||
fn asyncio_weather(state: State<AppState>) -> FutureResponse<HttpResponse> {
|
||||
let mut result: Vec<Vec<WeatherAgg>> = vec![];
|
||||
|
||||
state.db.send(Queries::GetTopTenHottestYears).from_err()
|
||||
state
|
||||
.db
|
||||
.send(Queries::GetTopTenHottestYears)
|
||||
.from_err()
|
||||
.and_then(move |res| {
|
||||
result.push(res.unwrap());
|
||||
state.db.send(Queries::GetTopTenColdestYears).from_err()
|
||||
state
|
||||
.db
|
||||
.send(Queries::GetTopTenColdestYears)
|
||||
.from_err()
|
||||
.and_then(move |res| {
|
||||
result.push(res.unwrap());
|
||||
state.db.send(Queries::GetTopTenHottestMonths).from_err()
|
||||
state
|
||||
.db
|
||||
.send(Queries::GetTopTenHottestMonths)
|
||||
.from_err()
|
||||
.and_then(move |res| {
|
||||
result.push(res.unwrap());
|
||||
state.db.send(Queries::GetTopTenColdestMonths).from_err()
|
||||
state
|
||||
.db
|
||||
.send(Queries::GetTopTenColdestMonths)
|
||||
.from_err()
|
||||
.and_then(move |res| {
|
||||
result.push(res.unwrap());
|
||||
fut_ok(result)
|
||||
@ -73,7 +83,8 @@ fn parallel_weather(state: State<AppState>) -> FutureResponse<HttpResponse> {
|
||||
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(state.db.send(Queries::GetTopTenColdestMonths)),
|
||||
];
|
||||
|
||||
join_all(fut_result)
|
||||
.map_err(AWError::from)
|
||||
|
@ -4,8 +4,10 @@ version = "0.1.0"
|
||||
authors = ["dowwie <dkcdkg@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
actix = "0.5.6"
|
||||
actix-web = { version = "^0.6", features=["alpn"] }
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
futures = "0.1"
|
||||
serde = "1.0.43"
|
||||
serde_derive = "1.0.43"
|
||||
|
@ -5,8 +5,10 @@ authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
futures = "0.1"
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
bytes = "0.4"
|
||||
|
@ -21,21 +21,14 @@ use futures::future::{result, FutureResult};
|
||||
use std::{env, io};
|
||||
|
||||
/// favicon handler
|
||||
fn favicon(req: HttpRequest) -> Result<fs::NamedFile> {
|
||||
fn favicon(req: &HttpRequest) -> Result<fs::NamedFile> {
|
||||
Ok(fs::NamedFile::open("static/favicon.ico")?)
|
||||
}
|
||||
|
||||
/// simple index handler
|
||||
fn welcome(mut req: HttpRequest) -> Result<HttpResponse> {
|
||||
fn welcome(req: &HttpRequest) -> Result<HttpResponse> {
|
||||
println!("{:?}", req);
|
||||
|
||||
// example of ...
|
||||
if let Ok(ch) = req.poll() {
|
||||
if let futures::Async::Ready(Some(d)) = ch {
|
||||
println!("{}", String::from_utf8_lossy(d.as_ref()));
|
||||
}
|
||||
}
|
||||
|
||||
// session
|
||||
let mut counter = 1;
|
||||
if let Some(count) = req.session().get::<i32>("counter")? {
|
||||
@ -53,12 +46,12 @@ fn welcome(mut req: HttpRequest) -> Result<HttpResponse> {
|
||||
}
|
||||
|
||||
/// 404 handler
|
||||
fn p404(req: HttpRequest) -> Result<fs::NamedFile> {
|
||||
fn p404(req: &HttpRequest) -> Result<fs::NamedFile> {
|
||||
Ok(fs::NamedFile::open("static/404.html")?.set_status_code(StatusCode::NOT_FOUND))
|
||||
}
|
||||
|
||||
/// async handler
|
||||
fn index_async(req: HttpRequest) -> FutureResult<HttpResponse, Error> {
|
||||
fn index_async(req: &HttpRequest) -> FutureResult<HttpResponse, Error> {
|
||||
println!("{:?}", req);
|
||||
|
||||
result(Ok(HttpResponse::Ok().content_type("text/html").body(
|
||||
@ -78,7 +71,7 @@ fn index_async_body(path: Path<String>) -> HttpResponse {
|
||||
}
|
||||
|
||||
/// handler with path parameters like `/user/{name}/`
|
||||
fn with_param(req: HttpRequest) -> HttpResponse {
|
||||
fn with_param(req: &HttpRequest) -> HttpResponse {
|
||||
println!("{:?}", req);
|
||||
|
||||
HttpResponse::Ok()
|
||||
@ -122,7 +115,7 @@ fn main() {
|
||||
io::Error::new(io::ErrorKind::Other, "test"), StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}))
|
||||
// static files
|
||||
.handler("/static", fs::StaticFiles::new("static"))
|
||||
.handler("/static", fs::StaticFiles::new("static").unwrap())
|
||||
// redirect
|
||||
.resource("/", |r| r.method(Method::GET).f(|req| {
|
||||
println!("{:?}", req);
|
||||
|
@ -5,8 +5,10 @@ authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
cookie = { version="0.10", features=["percent-encode", "secure"] }
|
||||
futures = "0.1"
|
||||
time = "0.1"
|
||||
|
@ -14,31 +14,31 @@ use actix_web::{Error, HttpRequest, HttpResponse, Result};
|
||||
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(&mut self) -> Option<&str>;
|
||||
fn identity(&self) -> Option<String>;
|
||||
|
||||
/// Remember identity.
|
||||
fn remember(&mut self, identity: String);
|
||||
fn remember(&self, identity: String);
|
||||
|
||||
/// This method is used to 'forget' the current identity on subsequent
|
||||
/// requests.
|
||||
fn forget(&mut self);
|
||||
fn forget(&self);
|
||||
}
|
||||
|
||||
impl<S> RequestIdentity for HttpRequest<S> {
|
||||
fn identity(&mut self) -> Option<&str> {
|
||||
fn identity(&self) -> Option<String> {
|
||||
if let Some(id) = self.extensions().get::<IdentityBox>() {
|
||||
return id.0.identity();
|
||||
return id.0.identity().map(|s| s.to_owned());
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn remember(&mut self, identity: String) {
|
||||
fn remember(&self, identity: String) {
|
||||
if let Some(id) = self.extensions_mut().get_mut::<IdentityBox>() {
|
||||
return id.0.remember(identity);
|
||||
return id.0.as_mut().remember(identity);
|
||||
}
|
||||
}
|
||||
|
||||
fn forget(&mut self) {
|
||||
fn forget(&self) {
|
||||
if let Some(id) = self.extensions_mut().get_mut::<IdentityBox>() {
|
||||
return id.0.forget();
|
||||
}
|
||||
@ -86,7 +86,7 @@ unsafe impl Send for IdentityBox {}
|
||||
unsafe impl Sync for IdentityBox {}
|
||||
|
||||
impl<S: 'static, T: IdentityPolicy<S>> Middleware<S> for IdentityService<T> {
|
||||
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
|
||||
fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
|
||||
let mut req = req.clone();
|
||||
|
||||
let fut = self
|
||||
@ -102,9 +102,7 @@ impl<S: 'static, T: IdentityPolicy<S>> Middleware<S> for IdentityService<T> {
|
||||
Ok(Started::Future(Box::new(fut)))
|
||||
}
|
||||
|
||||
fn response(
|
||||
&self, req: &mut HttpRequest<S>, resp: HttpResponse,
|
||||
) -> Result<Response> {
|
||||
fn response(&self, req: &HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||
if let Some(mut id) = req.extensions_mut().remove::<IdentityBox>() {
|
||||
id.0.write(resp)
|
||||
} else {
|
||||
@ -200,7 +198,7 @@ impl CookieIdentityInner {
|
||||
|
||||
fn load<S>(&self, req: &mut HttpRequest<S>) -> Option<String> {
|
||||
if let Ok(cookies) = req.cookies() {
|
||||
for cookie in cookies {
|
||||
for cookie in cookies.iter() {
|
||||
if cookie.name() == self.name {
|
||||
let mut jar = CookieJar::new();
|
||||
jar.add_original(cookie.clone());
|
||||
|
@ -10,16 +10,16 @@ use actix_web::{middleware, server, App, HttpRequest, HttpResponse};
|
||||
mod auth;
|
||||
use auth::{CookieIdentityPolicy, IdentityService, RequestIdentity};
|
||||
|
||||
fn index(mut req: HttpRequest) -> String {
|
||||
format!("Hello {}", req.identity().unwrap_or("Anonymous"))
|
||||
fn index(req: &HttpRequest) -> String {
|
||||
format!("Hello {}", req.identity().unwrap_or("Anonymous".to_owned()))
|
||||
}
|
||||
|
||||
fn login(mut req: HttpRequest) -> HttpResponse {
|
||||
fn login(req: &HttpRequest) -> HttpResponse {
|
||||
req.remember("user1".to_owned());
|
||||
HttpResponse::Found().header("location", "/").finish()
|
||||
}
|
||||
|
||||
fn logout(mut req: HttpRequest) -> HttpResponse {
|
||||
fn logout(req: &HttpRequest) -> HttpResponse {
|
||||
req.forget();
|
||||
HttpResponse::Found().header("location", "/").finish()
|
||||
}
|
||||
|
@ -5,8 +5,10 @@ authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
futures = "0.1"
|
||||
time = "0.1"
|
||||
env_logger = "0.5"
|
||||
|
@ -15,7 +15,7 @@ use actix_web::{middleware, server, App, HttpRequest, Result};
|
||||
use std::env;
|
||||
|
||||
/// simple index handler with session
|
||||
fn index(req: HttpRequest) -> Result<&'static str> {
|
||||
fn index(req: &HttpRequest) -> Result<&'static str> {
|
||||
println!("{:?}", req);
|
||||
|
||||
// RequestSession trait is used for session access
|
||||
|
@ -6,8 +6,10 @@ workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
futures = "0.1"
|
||||
uuid = { version = "0.5", features = ["serde", "v4"] }
|
||||
|
@ -35,7 +35,7 @@ use db::{CreateUser, DbExecutor};
|
||||
|
||||
/// State with DbExecutor address
|
||||
struct AppState {
|
||||
db: Addr<Syn, DbExecutor>,
|
||||
db: Addr<DbExecutor>,
|
||||
}
|
||||
|
||||
/// Async request handler
|
||||
|
@ -4,7 +4,9 @@ version = "0.1.0"
|
||||
authors = ["Gorm Casper <gcasper@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
|
@ -6,5 +6,7 @@ workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -4,7 +4,7 @@ extern crate env_logger;
|
||||
|
||||
use actix_web::{middleware, server, App, HttpRequest};
|
||||
|
||||
fn index(_req: HttpRequest) -> &'static str {
|
||||
fn index(_req: &HttpRequest) -> &'static str {
|
||||
"Hello world!"
|
||||
}
|
||||
|
||||
|
@ -15,5 +15,7 @@ path = "src/server.rs"
|
||||
[dependencies]
|
||||
env_logger = "0.5"
|
||||
futures = "0.1"
|
||||
actix = "0.5"
|
||||
actix-web = { version = "^0.6", features=["alpn"] }
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -10,7 +10,7 @@ use actix_web::{
|
||||
use futures::{Future, Stream};
|
||||
|
||||
/// Stream client request response and then send body to a server response
|
||||
fn index(_req: HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
fn index(_req: &HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
client::ClientRequest::get("http://127.0.0.1:8081/")
|
||||
.finish().unwrap()
|
||||
.send()
|
||||
@ -25,7 +25,7 @@ fn index(_req: HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
}
|
||||
|
||||
/// streaming client request to a streaming server response
|
||||
fn streaming(_req: HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
fn streaming(_req: &HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
// send client request
|
||||
client::ClientRequest::get("https://www.rust-lang.org/en-US/")
|
||||
.finish().unwrap()
|
||||
@ -35,7 +35,7 @@ fn streaming(_req: HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error
|
||||
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.from_err()))))
|
||||
.body(Body::Streaming(Box::new(resp.payload().from_err()))))
|
||||
})
|
||||
.responder()
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ extern crate futures;
|
||||
use actix_web::*;
|
||||
use futures::Future;
|
||||
|
||||
fn index(req: HttpRequest) -> FutureResponse<HttpResponse> {
|
||||
fn index(req: &HttpRequest) -> FutureResponse<HttpResponse> {
|
||||
req.body()
|
||||
.from_err()
|
||||
.map(|bytes| HttpResponse::Ok().body(bytes))
|
||||
|
@ -14,5 +14,6 @@ serde_json = "1.0"
|
||||
serde_derive = "1.0"
|
||||
json = "*"
|
||||
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -25,7 +25,7 @@ struct MyObj {
|
||||
}
|
||||
|
||||
/// This handler uses `HttpRequest::json()` for loading json object.
|
||||
fn index(req: HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
fn index(req: &HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
req.json()
|
||||
.from_err() // convert all errors into `Error`
|
||||
.and_then(|val: MyObj| {
|
||||
@ -50,9 +50,9 @@ fn extract_item_limit((item, _req): (Json<MyObj>, 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(req: HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
// HttpRequest is stream of Bytes objects
|
||||
req
|
||||
fn index_manual(req: &HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
// HttpRequest::payload() is stream of Bytes objects
|
||||
req.payload()
|
||||
// `Future::from_err` acts like `?` in that it coerces the error type from
|
||||
// the future into the final error type
|
||||
.from_err()
|
||||
@ -79,8 +79,11 @@ fn index_manual(req: HttpRequest) -> Box<Future<Item = HttpResponse, Error = Err
|
||||
}
|
||||
|
||||
/// This handler manually load request payload and parse json-rust
|
||||
fn index_mjsonrust(req: HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
req.concat2()
|
||||
fn index_mjsonrust(
|
||||
req: &HttpRequest,
|
||||
) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
req.payload()
|
||||
.concat2()
|
||||
.from_err()
|
||||
.and_then(|body| {
|
||||
// body is loaded, now we can deserialize json-rust
|
||||
@ -107,13 +110,15 @@ fn main() {
|
||||
.middleware(middleware::Logger::default())
|
||||
.resource("/extractor", |r| {
|
||||
r.method(http::Method::POST)
|
||||
.with(extract_item)
|
||||
.limit(4096); // <- limit size of the payload
|
||||
.with_config(extract_item, |cfg| {
|
||||
cfg.limit(4096); // <- limit size of the payload
|
||||
})
|
||||
})
|
||||
.resource("/extractor2", |r| {
|
||||
r.method(http::Method::POST)
|
||||
.with(extract_item_limit)
|
||||
.0.limit(4096); // <- limit size of the payload
|
||||
.with_config(extract_item_limit, |cfg| {
|
||||
cfg.0.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))
|
||||
|
@ -6,8 +6,10 @@ workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
futures = "0.1"
|
||||
serde = "1.0"
|
||||
|
@ -27,7 +27,7 @@ use schema::create_schema;
|
||||
use schema::Schema;
|
||||
|
||||
struct AppState {
|
||||
executor: Addr<Syn, GraphQLExecutor>,
|
||||
executor: Addr<GraphQLExecutor>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -61,7 +61,7 @@ impl Handler<GraphQLData> for GraphQLExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
fn graphiql(_req: HttpRequest<AppState>) -> Result<HttpResponse, Error> {
|
||||
fn graphiql(_req: &HttpRequest<AppState>) -> Result<HttpResponse, Error> {
|
||||
let html = graphiql_source("http://127.0.0.1:8080/graphql");
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
|
@ -4,5 +4,6 @@ version = "0.1.0"
|
||||
authors = ["Gorm Casper <gcasper@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -7,7 +7,7 @@ pub struct CheckLogin;
|
||||
|
||||
impl<S> Middleware<S> for CheckLogin {
|
||||
// We only need to hook into the `start` for this middleware.
|
||||
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
|
||||
fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
|
||||
let is_logged_in = false; // Change this to see the change in outcome in the browser
|
||||
|
||||
if is_logged_in {
|
||||
|
@ -8,21 +8,17 @@ use actix_web::{HttpRequest, HttpResponse, Result};
|
||||
pub struct SayHi;
|
||||
|
||||
impl<S> Middleware<S> for SayHi {
|
||||
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
|
||||
fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
|
||||
println!("Hi from start. You requested: {}", req.path());
|
||||
Ok(Started::Done)
|
||||
}
|
||||
|
||||
fn response(
|
||||
&self,
|
||||
_req: &mut HttpRequest<S>,
|
||||
resp: HttpResponse,
|
||||
) -> Result<Response> {
|
||||
fn response(&self, _req: &HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||
println!("Hi from response");
|
||||
Ok(Response::Done(resp))
|
||||
}
|
||||
|
||||
fn finish(&self, _req: &mut HttpRequest<S>, _resp: &HttpResponse) -> Finished {
|
||||
fn finish(&self, _req: &HttpRequest<S>, _resp: &HttpResponse) -> Finished {
|
||||
println!("Hi from finish");
|
||||
Finished::Done
|
||||
}
|
||||
|
@ -11,5 +11,7 @@ path = "src/main.rs"
|
||||
[dependencies]
|
||||
env_logger = "*"
|
||||
futures = "0.1"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -4,13 +4,13 @@ extern crate actix_web;
|
||||
extern crate env_logger;
|
||||
extern crate futures;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::cell::Cell;
|
||||
|
||||
use actix_web::{
|
||||
error, http, middleware, multipart, server, App, Error, FutureResponse, HttpMessage,
|
||||
HttpRequest, HttpResponse,
|
||||
dev, error, http, middleware, multipart, server, App, Error, FutureResponse,
|
||||
HttpMessage, HttpRequest, HttpResponse,
|
||||
};
|
||||
|
||||
use futures::future;
|
||||
@ -20,7 +20,9 @@ pub struct AppState {
|
||||
pub counter: Cell<usize>,
|
||||
}
|
||||
|
||||
pub fn save_file( field: multipart::Field<HttpRequest<AppState>>) -> Box<Future<Item = i64, Error = Error>> {
|
||||
pub fn save_file(
|
||||
field: multipart::Field<dev::Payload>,
|
||||
) -> Box<Future<Item = i64, Error = Error>> {
|
||||
let file_path_string = "upload.png";
|
||||
let mut file = match fs::File::create(file_path_string) {
|
||||
Ok(file) => file,
|
||||
@ -45,7 +47,9 @@ pub fn save_file( field: multipart::Field<HttpRequest<AppState>>) -> Box<Future<
|
||||
)
|
||||
}
|
||||
|
||||
pub fn handle_multipart_item( item: multipart::MultipartItem<HttpRequest<AppState>>) -> Box<Stream<Item = i64, Error = Error>> {
|
||||
pub fn handle_multipart_item(
|
||||
item: multipart::MultipartItem<dev::Payload>,
|
||||
) -> Box<Stream<Item = i64, Error = Error>> {
|
||||
match item {
|
||||
multipart::MultipartItem::Field(field) => {
|
||||
Box::new(save_file(field).into_stream())
|
||||
@ -62,8 +66,7 @@ pub fn upload(req: HttpRequest<AppState>) -> FutureResponse<HttpResponse> {
|
||||
req.state().counter.set(req.state().counter.get() + 1);
|
||||
println!("{:?}", req.state().counter.get());
|
||||
Box::new(
|
||||
req.clone()
|
||||
.multipart()
|
||||
req.multipart()
|
||||
.map_err(error::ErrorInternalServerError)
|
||||
.map(handle_multipart_item)
|
||||
.flatten()
|
||||
@ -96,8 +99,9 @@ fn main() {
|
||||
let sys = actix::System::new("multipart-example");
|
||||
|
||||
server::new(|| {
|
||||
App::with_state(AppState{counter: Cell::new(0)})
|
||||
.middleware(middleware::Logger::default())
|
||||
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);
|
||||
|
@ -13,5 +13,6 @@ env_logger = "*"
|
||||
prost = "0.2.0"
|
||||
prost-derive = "0.2.0"
|
||||
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -26,7 +26,7 @@ pub struct MyObj {
|
||||
}
|
||||
|
||||
/// This handler uses `ProtoBufMessage` for loading protobuf object.
|
||||
fn index(req: HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
fn index(req: &HttpRequest) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
protobuf::ProtoBufMessage::new(req)
|
||||
.from_err() // convert all errors into `Error`
|
||||
.and_then(|val: MyObj| {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use bytes::BytesMut;
|
||||
use futures::{Future, Poll, Stream};
|
||||
|
||||
use bytes::IntoBuf;
|
||||
@ -8,7 +8,7 @@ use prost::Message;
|
||||
|
||||
use actix_web::dev::HttpResponseBuilder;
|
||||
use actix_web::error::{Error, PayloadError, ResponseError};
|
||||
use actix_web::http::header::{CONTENT_LENGTH, CONTENT_TYPE};
|
||||
use actix_web::http::header::CONTENT_TYPE;
|
||||
use actix_web::{HttpMessage, HttpRequest, HttpResponse, Responder};
|
||||
|
||||
#[derive(Fail, Debug)]
|
||||
@ -72,84 +72,32 @@ impl<T: Message> Responder for ProtoBuf<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ProtoBufMessage<T, U: Message + Default> {
|
||||
limit: usize,
|
||||
ct: &'static str,
|
||||
req: Option<T>,
|
||||
fut: Option<Box<Future<Item = U, Error = ProtoBufPayloadError>>>,
|
||||
pub struct ProtoBufMessage<U: Message + Default> {
|
||||
fut: Box<Future<Item = U, Error = ProtoBufPayloadError>>,
|
||||
}
|
||||
|
||||
impl<T, U: Message + Default> ProtoBufMessage<T, U> {
|
||||
impl<U: Message + Default + 'static> ProtoBufMessage<U> {
|
||||
/// Create `ProtoBufMessage` for request.
|
||||
pub fn new(req: T) -> Self {
|
||||
ProtoBufMessage {
|
||||
limit: 262_144,
|
||||
req: Some(req),
|
||||
fut: None,
|
||||
ct: "application/protobuf",
|
||||
pub fn new(req: &HttpRequest) -> Self {
|
||||
let fut = req
|
||||
.payload()
|
||||
.map_err(|e| ProtoBufPayloadError::Payload(e))
|
||||
.fold(BytesMut::new(), move |mut body, chunk| {
|
||||
body.extend_from_slice(&chunk);
|
||||
Ok::<_, ProtoBufPayloadError>(body)
|
||||
})
|
||||
.and_then(|body| Ok(<U>::decode(&mut body.into_buf())?));
|
||||
|
||||
ProtoBufMessage { fut: Box::new(fut) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Change max size of payload. By default max size is 256Kb
|
||||
pub fn limit(mut self, limit: usize) -> Self {
|
||||
self.limit = limit;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set allowed content type.
|
||||
///
|
||||
/// By default *application/protobuf* content type is used. Set content type
|
||||
/// to empty string if you want to disable content type check.
|
||||
pub fn content_type(mut self, ct: &'static str) -> Self {
|
||||
self.ct = ct;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U: Message + Default + 'static> Future for ProtoBufMessage<T, U>
|
||||
where
|
||||
T: HttpMessage + Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
{
|
||||
impl<U: Message + Default + 'static> Future for ProtoBufMessage<U> where {
|
||||
type Item = U;
|
||||
type Error = ProtoBufPayloadError;
|
||||
|
||||
fn poll(&mut self) -> Poll<U, ProtoBufPayloadError> {
|
||||
if let Some(req) = self.req.take() {
|
||||
if let Some(len) = req.headers().get(CONTENT_LENGTH) {
|
||||
if let Ok(s) = len.to_str() {
|
||||
if let Ok(len) = s.parse::<usize>() {
|
||||
if len > self.limit {
|
||||
return Err(ProtoBufPayloadError::Overflow);
|
||||
}
|
||||
} else {
|
||||
return Err(ProtoBufPayloadError::Overflow);
|
||||
}
|
||||
}
|
||||
}
|
||||
// check content-type
|
||||
if !self.ct.is_empty() && req.content_type() != self.ct {
|
||||
return Err(ProtoBufPayloadError::ContentType);
|
||||
}
|
||||
|
||||
let limit = self.limit;
|
||||
let fut = req
|
||||
.from_err()
|
||||
.fold(BytesMut::new(), move |mut body, chunk| {
|
||||
if (body.len() + chunk.len()) > limit {
|
||||
Err(ProtoBufPayloadError::Overflow)
|
||||
} else {
|
||||
body.extend_from_slice(&chunk);
|
||||
Ok(body)
|
||||
}
|
||||
})
|
||||
.and_then(|body| Ok(<U>::decode(&mut body.into_buf())?));
|
||||
self.fut = Some(Box::new(fut));
|
||||
}
|
||||
|
||||
self.fut
|
||||
.as_mut()
|
||||
.expect("ProtoBufBody could not be used second time")
|
||||
.poll()
|
||||
self.fut.poll()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,10 @@ workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
futures = "0.1"
|
||||
uuid = { version = "0.5", features = ["serde", "v4"] }
|
||||
|
@ -22,11 +22,11 @@ use db::{CreateUser, DbExecutor};
|
||||
|
||||
/// State with DbExecutor address
|
||||
struct State {
|
||||
db: Addr<Syn, DbExecutor>,
|
||||
db: Addr<DbExecutor>,
|
||||
}
|
||||
|
||||
/// Async request handler
|
||||
fn index(req: HttpRequest<State>) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
fn index(req: &HttpRequest<State>) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
let name = &req.match_info()["name"];
|
||||
|
||||
req.state()
|
||||
|
@ -7,5 +7,7 @@ workspace = "../"
|
||||
[dependencies]
|
||||
futures = "0.1"
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -25,7 +25,7 @@ struct AppState {
|
||||
}
|
||||
|
||||
/// simple handle
|
||||
fn index(req: HttpRequest<AppState>) -> HttpResponse {
|
||||
fn index(req: &HttpRequest<AppState>) -> HttpResponse {
|
||||
println!("{:?}", req);
|
||||
req.state().counter.set(req.state().counter.get() + 1);
|
||||
|
||||
|
@ -7,5 +7,7 @@ workspace = "../"
|
||||
[dependencies]
|
||||
futures = "0.1"
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "0.6"
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -17,7 +17,7 @@ fn main() {
|
||||
.middleware(middleware::Logger::default())
|
||||
.handler(
|
||||
"/",
|
||||
fs::StaticFiles::new("./static/").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")
|
||||
|
@ -6,9 +6,11 @@ workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
askama = "0.6"
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
[build-dependencies]
|
||||
askama = "0.6"
|
@ -6,6 +6,7 @@ workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
tera = "*"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -10,6 +10,7 @@ path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = { version = "^0.6", features=["alpn"] }
|
||||
openssl = { version="0.10" }
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -8,7 +8,7 @@ use actix_web::{http, middleware, server, App, Error, HttpRequest, HttpResponse}
|
||||
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
|
||||
|
||||
/// simple handle
|
||||
fn index(req: HttpRequest) -> Result<HttpResponse, Error> {
|
||||
fn index(req: &HttpRequest) -> Result<HttpResponse, Error> {
|
||||
println!("{:?}", req);
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("text/plain")
|
||||
|
@ -6,6 +6,8 @@ workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.5"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
tokio-uds = "0.1"
|
||||
tokio-uds = "0.2"
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -7,7 +7,7 @@ use actix::*;
|
||||
use actix_web::{middleware, server, App, HttpRequest};
|
||||
use tokio_uds::UnixListener;
|
||||
|
||||
fn index(_req: HttpRequest) -> &'static str {
|
||||
fn index(_req: &HttpRequest) -> &'static str {
|
||||
"Hello world!"
|
||||
}
|
||||
|
||||
@ -16,8 +16,7 @@ fn main() {
|
||||
env_logger::init();
|
||||
let sys = actix::System::new("unix-socket");
|
||||
|
||||
let listener = UnixListener::bind("/tmp/actix-uds.socket", Arbiter::handle())
|
||||
.expect("bind failed");
|
||||
let listener = UnixListener::bind("/tmp/actix-uds.socket").expect("bind failed");
|
||||
server::new(|| {
|
||||
App::new()
|
||||
// enable logger
|
||||
|
@ -10,8 +10,10 @@ serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
http = "0.1"
|
||||
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
||||
dotenv = "0.10"
|
||||
env_logger = "0.5"
|
||||
futures = "0.1"
|
||||
|
@ -8,7 +8,10 @@ extern crate serde;
|
||||
extern crate serde_json;
|
||||
|
||||
use actix_web::{
|
||||
http::{header, Method}, middleware, middleware::cors::Cors, server, App,
|
||||
http::{header, Method},
|
||||
middleware,
|
||||
middleware::cors::Cors,
|
||||
server, App,
|
||||
};
|
||||
use std::env;
|
||||
|
||||
|
@ -20,5 +20,6 @@ env_logger = "*"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -24,11 +24,11 @@ mod server;
|
||||
/// This is our websocket route state, this state is shared with all route
|
||||
/// instances via `HttpContext::state()`
|
||||
struct WsChatSessionState {
|
||||
addr: Addr<Syn, server::ChatServer>,
|
||||
addr: Addr<server::ChatServer>,
|
||||
}
|
||||
|
||||
/// Entry point for our route
|
||||
fn chat_route(req: HttpRequest<WsChatSessionState>) -> Result<HttpResponse, Error> {
|
||||
fn chat_route(req: &HttpRequest<WsChatSessionState>) -> Result<HttpResponse, Error> {
|
||||
ws::start(
|
||||
req,
|
||||
WsChatSession {
|
||||
@ -63,7 +63,7 @@ impl Actor for WsChatSession {
|
||||
// before processing any other events.
|
||||
// HttpContext::state() is instance of WsChatSessionState, state is shared
|
||||
// across all routes within application
|
||||
let addr: Addr<Syn, _> = ctx.address();
|
||||
let addr = ctx.address();
|
||||
ctx.state()
|
||||
.addr
|
||||
.send(server::Connect {
|
||||
@ -183,7 +183,7 @@ fn main() {
|
||||
let sys = actix::System::new("websocket-example");
|
||||
|
||||
// Start chat server actor in separate thread
|
||||
let server: Addr<Syn, _> = Arbiter::start(|_| server::ChatServer::default());
|
||||
let server = Arbiter::start(|_| server::ChatServer::default());
|
||||
|
||||
// Create Http server with websocket support
|
||||
HttpServer::new(move || {
|
||||
@ -202,7 +202,7 @@ fn main() {
|
||||
// websocket
|
||||
.resource("/ws/", |r| r.route().f(chat_route))
|
||||
// static resources
|
||||
.handler("/static/", fs::StaticFiles::new("static/"))
|
||||
.handler("/static/", fs::StaticFiles::new("static/").unwrap())
|
||||
}).bind("127.0.0.1:8080")
|
||||
.unwrap()
|
||||
.start();
|
||||
|
@ -17,7 +17,7 @@ pub struct Message(pub String);
|
||||
#[derive(Message)]
|
||||
#[rtype(usize)]
|
||||
pub struct Connect {
|
||||
pub addr: Recipient<Syn, Message>,
|
||||
pub addr: Recipient<Message>,
|
||||
}
|
||||
|
||||
/// Session is disconnected
|
||||
@ -56,7 +56,7 @@ pub struct Join {
|
||||
/// `ChatServer` manages chat rooms and responsible for coordinating chat
|
||||
/// session. implementation is super primitive
|
||||
pub struct ChatServer {
|
||||
sessions: HashMap<usize, Recipient<Syn, Message>>,
|
||||
sessions: HashMap<usize, Recipient<Message>>,
|
||||
rooms: HashMap<String, HashSet<usize>>,
|
||||
rng: RefCell<ThreadRng>,
|
||||
}
|
||||
|
@ -18,12 +18,14 @@ bytes = "0.4"
|
||||
byteorder = "1.1"
|
||||
futures = "0.1"
|
||||
tokio-io = "0.1"
|
||||
tokio-core = "0.1"
|
||||
tokio-tcp = "0.1"
|
||||
tokio-codec = "0.1"
|
||||
env_logger = "*"
|
||||
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_derive = "1.0"
|
||||
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -5,8 +5,9 @@ extern crate bytes;
|
||||
extern crate futures;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate tokio_core;
|
||||
extern crate tokio_codec;
|
||||
extern crate tokio_io;
|
||||
extern crate tokio_tcp;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
@ -15,10 +16,10 @@ use futures::Future;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
use std::{io, net, process, thread};
|
||||
use tokio_core::net::TcpStream;
|
||||
use tokio_io::codec::FramedRead;
|
||||
use tokio_codec::FramedRead;
|
||||
use tokio_io::io::WriteHalf;
|
||||
use tokio_io::AsyncRead;
|
||||
use tokio_tcp::TcpStream;
|
||||
|
||||
mod codec;
|
||||
|
||||
@ -27,10 +28,10 @@ fn main() {
|
||||
|
||||
// Connect to server
|
||||
let addr = net::SocketAddr::from_str("127.0.0.1:12345").unwrap();
|
||||
Arbiter::handle().spawn(
|
||||
TcpStream::connect(&addr, Arbiter::handle())
|
||||
Arbiter::spawn(
|
||||
TcpStream::connect(&addr)
|
||||
.and_then(|stream| {
|
||||
let addr: Addr<Syn, _> = ChatClient::create(|ctx| {
|
||||
let addr = ChatClient::create(|ctx| {
|
||||
let (r, w) = stream.split();
|
||||
ChatClient::add_stream(
|
||||
FramedRead::new(r, codec::ClientChatCodec),
|
||||
@ -87,7 +88,7 @@ impl Actor for ChatClient {
|
||||
println!("Disconnected");
|
||||
|
||||
// Stop application on disconnect
|
||||
Arbiter::system().do_send(actix::msgs::SystemExit(0));
|
||||
System::current().stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,9 @@ extern crate futures;
|
||||
extern crate rand;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate tokio_core;
|
||||
extern crate tokio_codec;
|
||||
extern crate tokio_io;
|
||||
extern crate tokio_tcp;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
@ -28,11 +29,11 @@ mod session;
|
||||
/// This is our websocket route state, this state is shared with all route
|
||||
/// instances via `HttpContext::state()`
|
||||
struct WsChatSessionState {
|
||||
addr: Addr<Syn, server::ChatServer>,
|
||||
addr: Addr<server::ChatServer>,
|
||||
}
|
||||
|
||||
/// Entry point for our route
|
||||
fn chat_route(req: HttpRequest<WsChatSessionState>) -> Result<HttpResponse, Error> {
|
||||
fn chat_route(req: &HttpRequest<WsChatSessionState>) -> Result<HttpResponse, Error> {
|
||||
ws::start(
|
||||
req,
|
||||
WsChatSession {
|
||||
@ -67,7 +68,7 @@ impl Actor for WsChatSession {
|
||||
// before processing any other events.
|
||||
// HttpContext::state() is instance of WsChatSessionState, state is shared
|
||||
// across all routes within application
|
||||
let addr: Addr<Syn, _> = ctx.address();
|
||||
let addr = ctx.address();
|
||||
ctx.state()
|
||||
.addr
|
||||
.send(server::Connect {
|
||||
@ -187,7 +188,7 @@ fn main() {
|
||||
let sys = actix::System::new("websocket-example");
|
||||
|
||||
// Start chat server actor in separate thread
|
||||
let server: Addr<Syn, _> = Arbiter::start(|_| server::ChatServer::default());
|
||||
let server = Arbiter::start(|_| server::ChatServer::default());
|
||||
|
||||
// Start tcp server in separate thread
|
||||
let srv = server.clone();
|
||||
@ -213,7 +214,7 @@ fn main() {
|
||||
// websocket
|
||||
.resource("/ws/", |r| r.route().f(chat_route))
|
||||
// static resources
|
||||
.handler("/static/", fs::StaticFiles::new("static/"))
|
||||
.handler("/static/", fs::StaticFiles::new("static/").unwrap())
|
||||
}).bind("127.0.0.1:8080")
|
||||
.unwrap()
|
||||
.start();
|
||||
|
@ -15,7 +15,7 @@ use session;
|
||||
#[derive(Message)]
|
||||
#[rtype(usize)]
|
||||
pub struct Connect {
|
||||
pub addr: Recipient<Syn, session::Message>,
|
||||
pub addr: Recipient<session::Message>,
|
||||
}
|
||||
|
||||
/// Session is disconnected
|
||||
@ -54,7 +54,7 @@ pub struct Join {
|
||||
/// `ChatServer` manages chat rooms and responsible for coordinating chat
|
||||
/// session. implementation is super primitive
|
||||
pub struct ChatServer {
|
||||
sessions: HashMap<usize, Recipient<Syn, session::Message>>,
|
||||
sessions: HashMap<usize, Recipient<session::Message>>,
|
||||
rooms: HashMap<String, HashSet<usize>>,
|
||||
rng: RefCell<ThreadRng>,
|
||||
}
|
||||
|
@ -4,10 +4,10 @@ use futures::Stream;
|
||||
use std::str::FromStr;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{io, net};
|
||||
use tokio_core::net::{TcpListener, TcpStream};
|
||||
use tokio_io::codec::FramedRead;
|
||||
use tokio_codec::FramedRead;
|
||||
use tokio_io::io::WriteHalf;
|
||||
use tokio_io::AsyncRead;
|
||||
use tokio_tcp::{TcpListener, TcpStream};
|
||||
|
||||
use actix::prelude::*;
|
||||
|
||||
@ -23,7 +23,7 @@ pub struct ChatSession {
|
||||
/// unique session id
|
||||
id: usize,
|
||||
/// this is address of chat server
|
||||
addr: Addr<Syn, ChatServer>,
|
||||
addr: Addr<ChatServer>,
|
||||
/// Client must send ping at least once per 10 seconds, otherwise we drop
|
||||
/// connection.
|
||||
hb: Instant,
|
||||
@ -45,7 +45,7 @@ impl Actor for ChatSession {
|
||||
// register self in chat server. `AsyncContext::wait` register
|
||||
// future within context, but context waits until this future resolves
|
||||
// before processing any other events.
|
||||
let addr: Addr<Syn, _> = ctx.address();
|
||||
let addr = ctx.address();
|
||||
self.addr
|
||||
.send(server::Connect {
|
||||
addr: addr.recipient(),
|
||||
@ -133,7 +133,7 @@ impl Handler<Message> for ChatSession {
|
||||
/// Helper methods
|
||||
impl ChatSession {
|
||||
pub fn new(
|
||||
addr: Addr<Syn, ChatServer>,
|
||||
addr: Addr<ChatServer>,
|
||||
framed: actix::io::FramedWrite<WriteHalf<TcpStream>, ChatCodec>,
|
||||
) -> ChatSession {
|
||||
ChatSession {
|
||||
@ -172,14 +172,14 @@ impl ChatSession {
|
||||
/// Define tcp server that will accept incoming tcp connection and create
|
||||
/// chat actors.
|
||||
pub struct TcpServer {
|
||||
chat: Addr<Syn, ChatServer>,
|
||||
chat: Addr<ChatServer>,
|
||||
}
|
||||
|
||||
impl TcpServer {
|
||||
pub fn new(s: &str, chat: Addr<Syn, ChatServer>) {
|
||||
pub fn new(s: &str, chat: Addr<ChatServer>) {
|
||||
// Create server listener
|
||||
let addr = net::SocketAddr::from_str("127.0.0.1:12345").unwrap();
|
||||
let listener = TcpListener::bind(&addr, Arbiter::handle()).unwrap();
|
||||
let listener = TcpListener::bind(&addr).unwrap();
|
||||
|
||||
// Our chat server `Server` is an actor, first we need to start it
|
||||
// and then add stream on incoming tcp connections to it.
|
||||
@ -187,12 +187,9 @@ impl TcpServer {
|
||||
// items So to be able to handle this events `Server` actor has to
|
||||
// implement stream handler `StreamHandler<(TcpStream,
|
||||
// net::SocketAddr), io::Error>`
|
||||
let _: () = TcpServer::create(|ctx| {
|
||||
TcpServer::create(|ctx| {
|
||||
ctx.add_message_stream(
|
||||
listener
|
||||
.incoming()
|
||||
.map_err(|_| ())
|
||||
.map(|(t, a)| TcpConnect(t, a)),
|
||||
listener.incoming().map_err(|_| ()).map(|s| TcpConnect(s)),
|
||||
);
|
||||
TcpServer { chat: chat }
|
||||
});
|
||||
@ -206,7 +203,7 @@ impl Actor for TcpServer {
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
struct TcpConnect(TcpStream, net::SocketAddr);
|
||||
struct TcpConnect(TcpStream);
|
||||
|
||||
/// Handle stream of TcpStream's
|
||||
impl Handler<TcpConnect> for TcpServer {
|
||||
@ -216,7 +213,7 @@ impl Handler<TcpConnect> for TcpServer {
|
||||
// For each incoming connection we create `ChatSession` actor
|
||||
// with out chat server address.
|
||||
let server = self.chat.clone();
|
||||
let _: () = ChatSession::create(|ctx| {
|
||||
ChatSession::create(|ctx| {
|
||||
let (r, w) = msg.0.split();
|
||||
ChatSession::add_stream(FramedRead::new(r, ChatCodec), ctx);
|
||||
ChatSession::new(server, actix::io::FramedWrite::new(w, ChatCodec, ctx))
|
||||
|
@ -15,6 +15,7 @@ path = "src/client.rs"
|
||||
[dependencies]
|
||||
env_logger = "*"
|
||||
futures = "0.1"
|
||||
tokio-core = "0.1"
|
||||
actix = "0.5"
|
||||
actix-web = "^0.6"
|
||||
|
||||
actix = "0.7"
|
||||
#actix-web = "^0.7"
|
||||
actix-web = { git = "https://github.com/actix/actix-web.git" }
|
||||
|
@ -5,13 +5,11 @@ extern crate actix;
|
||||
extern crate actix_web;
|
||||
extern crate env_logger;
|
||||
extern crate futures;
|
||||
extern crate tokio_core;
|
||||
|
||||
use std::time::Duration;
|
||||
use std::{io, thread};
|
||||
|
||||
use actix::*;
|
||||
use actix_web::ws::WsWriter;
|
||||
use actix_web::ws::{Client, ClientWriter, Message, ProtocolError};
|
||||
use futures::Future;
|
||||
|
||||
@ -20,7 +18,7 @@ fn main() {
|
||||
let _ = env_logger::init();
|
||||
let sys = actix::System::new("ws-example");
|
||||
|
||||
Arbiter::handle().spawn(
|
||||
Arbiter::spawn(
|
||||
Client::new("http://127.0.0.1:8080/ws/")
|
||||
.connect()
|
||||
.map_err(|e| {
|
||||
@ -28,7 +26,7 @@ fn main() {
|
||||
()
|
||||
})
|
||||
.map(|(reader, writer)| {
|
||||
let addr: Addr<Syn, _> = ChatClient::create(|ctx| {
|
||||
let addr = ChatClient::create(|ctx| {
|
||||
ChatClient::add_stream(reader, ctx);
|
||||
ChatClient(writer)
|
||||
});
|
||||
@ -67,7 +65,7 @@ impl Actor for ChatClient {
|
||||
println!("Disconnected");
|
||||
|
||||
// Stop application on disconnect
|
||||
Arbiter::system().do_send(actix::msgs::SystemExit(0));
|
||||
System::current().stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ use actix_web::{
|
||||
};
|
||||
|
||||
/// do websocket handshake and start `MyWebSocket` actor
|
||||
fn ws_index(r: HttpRequest) -> Result<HttpResponse, Error> {
|
||||
fn ws_index(r: &HttpRequest) -> Result<HttpResponse, Error> {
|
||||
ws::start(r, MyWebSocket)
|
||||
}
|
||||
|
||||
@ -56,6 +56,7 @@ fn main() {
|
||||
.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()
|
||||
|
Loading…
Reference in New Issue
Block a user