From 14252f5ef2987337ac218d375118781dfd939dcd Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 15 Apr 2019 09:09:21 -0700 Subject: [PATCH 01/15] use test::call_service --- actix-files/src/lib.rs | 32 ++++++++++++++++---------------- actix-web-actors/src/context.rs | 4 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 4923536f6..8ff6b932c 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -775,7 +775,7 @@ mod tests { ); let request = TestRequest::get().uri("/").to_request(); - let response = test::call_success(&mut srv, request); + let response = test::call_service(&mut srv, request); assert_eq!(response.status(), StatusCode::OK); let content_disposition = response @@ -799,7 +799,7 @@ mod tests { .uri("/t%65st/Cargo.toml") .header(header::RANGE, "bytes=10-20") .to_request(); - let response = test::call_success(&mut srv, request); + let response = test::call_service(&mut srv, request); assert_eq!(response.status(), StatusCode::PARTIAL_CONTENT); // Invalid range header @@ -807,7 +807,7 @@ mod tests { .uri("/t%65st/Cargo.toml") .header(header::RANGE, "bytes=1-0") .to_request(); - let response = test::call_success(&mut srv, request); + let response = test::call_service(&mut srv, request); assert_eq!(response.status(), StatusCode::RANGE_NOT_SATISFIABLE); } @@ -824,7 +824,7 @@ mod tests { .header(header::RANGE, "bytes=10-20") .to_request(); - let response = test::call_success(&mut srv, request); + let response = test::call_service(&mut srv, request); let contentrange = response .headers() .get(header::CONTENT_RANGE) @@ -839,7 +839,7 @@ mod tests { .uri("/t%65st/tests/test.binary") .header(header::RANGE, "bytes=10-5") .to_request(); - let response = test::call_success(&mut srv, request); + let response = test::call_service(&mut srv, request); let contentrange = response .headers() @@ -862,7 +862,7 @@ mod tests { .uri("/t%65st/tests/test.binary") .header(header::RANGE, "bytes=10-20") .to_request(); - let response = test::call_success(&mut srv, request); + let response = test::call_service(&mut srv, request); let contentlength = response .headers() @@ -878,7 +878,7 @@ mod tests { .uri("/t%65st/tests/test.binary") .header(header::RANGE, "bytes=10-8") .to_request(); - let response = test::call_success(&mut srv, request); + let response = test::call_service(&mut srv, request); assert_eq!(response.status(), StatusCode::RANGE_NOT_SATISFIABLE); // Without range header @@ -886,7 +886,7 @@ mod tests { .uri("/t%65st/tests/test.binary") // .no_default_headers() .to_request(); - let response = test::call_success(&mut srv, request); + let response = test::call_service(&mut srv, request); let contentlength = response .headers() @@ -901,7 +901,7 @@ mod tests { let request = TestRequest::get() .uri("/t%65st/tests/test.binary") .to_request(); - let mut response = test::call_success(&mut srv, request); + let mut response = test::call_service(&mut srv, request); // with enabled compression // { @@ -932,7 +932,7 @@ mod tests { let request = TestRequest::get() .uri("/tests/test%20space.binary") .to_request(); - let mut response = test::call_success(&mut srv, request); + let mut response = test::call_service(&mut srv, request); assert_eq!(response.status(), StatusCode::OK); let bytes = @@ -975,7 +975,7 @@ mod tests { .uri("/") .header(header::ACCEPT_ENCODING, "gzip") .to_request(); - let res = test::call_success(&mut srv, request); + let res = test::call_service(&mut srv, request); assert_eq!(res.status(), StatusCode::OK); assert!(!res.headers().contains_key(header::CONTENT_ENCODING)); } @@ -994,7 +994,7 @@ mod tests { .uri("/") .header(header::ACCEPT_ENCODING, "gzip") .to_request(); - let res = test::call_success(&mut srv, request); + let res = test::call_service(&mut srv, request); assert_eq!(res.status(), StatusCode::OK); assert_eq!( res.headers() @@ -1021,20 +1021,20 @@ mod tests { ); let req = TestRequest::with_uri("/missing").to_request(); - let resp = test::call_success(&mut srv, req); + let resp = test::call_service(&mut srv, req); assert_eq!(resp.status(), StatusCode::NOT_FOUND); let mut srv = test::init_service(App::new().service(Files::new("/", "."))); let req = TestRequest::default().to_request(); - let resp = test::call_success(&mut srv, req); + let resp = test::call_service(&mut srv, req); assert_eq!(resp.status(), StatusCode::NOT_FOUND); let mut srv = test::init_service( App::new().service(Files::new("/", ".").show_files_listing()), ); let req = TestRequest::with_uri("/tests").to_request(); - let mut resp = test::call_success(&mut srv, req); + let mut resp = test::call_service(&mut srv, req); assert_eq!( resp.headers().get(header::CONTENT_TYPE).unwrap(), "text/html; charset=utf-8" @@ -1067,7 +1067,7 @@ mod tests { .unwrap(); let req = TestRequest::with_uri("/missing").to_srv_request(); - let mut resp = test::call_success(&mut st, req); + let mut resp = test::call_service(&mut st, req); assert_eq!(resp.status(), StatusCode::OK); let bytes = test::block_on(resp.take_body().fold(BytesMut::new(), |mut b, c| { diff --git a/actix-web-actors/src/context.rs b/actix-web-actors/src/context.rs index da473ff3f..31b29500a 100644 --- a/actix-web-actors/src/context.rs +++ b/actix-web-actors/src/context.rs @@ -199,7 +199,7 @@ mod tests { use actix::Actor; use actix_web::http::StatusCode; - use actix_web::test::{block_on, call_success, init_service, TestRequest}; + use actix_web::test::{block_on, call_service, init_service, TestRequest}; use actix_web::{web, App, HttpResponse}; use bytes::{Bytes, BytesMut}; @@ -237,7 +237,7 @@ mod tests { }))); let req = TestRequest::with_uri("/test").to_request(); - let mut resp = call_success(&mut srv, req); + let mut resp = call_service(&mut srv, req); assert_eq!(resp.status(), StatusCode::OK); let body = block_on(resp.take_body().fold( From 7f674febb18ad7347fff98bd081e573472930a14 Mon Sep 17 00:00:00 2001 From: Travis Harmon Date: Mon, 15 Apr 2019 19:55:06 -0400 Subject: [PATCH 02/15] add 422 to httpcodes.rs (#782) --- actix-http/src/httpcodes.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/actix-http/src/httpcodes.rs b/actix-http/src/httpcodes.rs index 85c384374..e7eda2da8 100644 --- a/actix-http/src/httpcodes.rs +++ b/actix-http/src/httpcodes.rs @@ -60,6 +60,7 @@ impl Response { STATIC_RESP!(UnsupportedMediaType, StatusCode::UNSUPPORTED_MEDIA_TYPE); STATIC_RESP!(RangeNotSatisfiable, StatusCode::RANGE_NOT_SATISFIABLE); STATIC_RESP!(ExpectationFailed, StatusCode::EXPECTATION_FAILED); + STATIC_RESP!(UnprocessableEntity, StatusCode::UNPROCESSABLE_ENTITY); STATIC_RESP!(InternalServerError, StatusCode::INTERNAL_SERVER_ERROR); STATIC_RESP!(NotImplemented, StatusCode::NOT_IMPLEMENTED); From a116c4c2c799e24f21bd57edde03d38ae64abea7 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Apr 2019 09:54:02 -0700 Subject: [PATCH 03/15] Expose peer addr via Request::peer_addr() and RequestHead::peer_addr --- Cargo.toml | 8 ++--- actix-http/CHANGES.md | 6 +++- actix-http/Cargo.toml | 14 ++++---- actix-http/src/h1/codec.rs | 9 ++--- actix-http/src/h1/dispatcher.rs | 20 ++++++----- actix-http/src/h1/service.rs | 20 +++++------ actix-http/src/h2/dispatcher.rs | 19 +++++----- actix-http/src/h2/service.rs | 58 +++++++++++++++++------------- actix-http/src/message.rs | 3 ++ actix-http/src/request.rs | 12 ++++++- actix-http/src/service.rs | 64 ++++++++++++++++++++++++++------- actix-http/src/test.rs | 15 ++++++++ actix-http/tests/test_server.rs | 7 +++- 13 files changed, 170 insertions(+), 85 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f2835d6c3..68979d096 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,8 +72,8 @@ actix-router = "0.1.2" actix-rt = "0.2.2" actix-web-codegen = "0.1.0-alpha.6" actix-http = { version = "0.1.0-alpha.5", features=["fail"] } -actix-server = "0.4.2" -actix-server-config = "0.1.0" +actix-server = "0.4.3" +actix-server-config = "0.1.1" actix-threadpool = "0.1.0" awc = { version = "0.1.0-alpha.6", optional = true } @@ -81,7 +81,7 @@ bytes = "0.4" derive_more = "0.14" encoding = "0.2" futures = "0.1" -hashbrown = "0.2.1" +hashbrown = "0.2.2" log = "0.4" mime = "0.3" net2 = "0.2.33" @@ -121,4 +121,4 @@ actix-web-codegen = { path = "actix-web-codegen" } actix-web-actors = { path = "actix-web-actors" } actix-session = { path = "actix-session" } actix-files = { path = "actix-files" } -awc = { path = "awc" } \ No newline at end of file +awc = { path = "awc" } diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 236436bb1..dc56b0401 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,6 +1,10 @@ # Changes -## [0.1.0] - 2019-04-xx +## [0.1.0] - 2019-04-16 + +### Added + +* Expose peer addr via `Request::peer_addr()` and `RequestHead::peer_addr` ### Changed diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index f7ca0bce1..746699a07 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "0.1.0-alpha.5" +version = "0.1.0" authors = ["Nikolay Kim "] description = "Actix http primitives" readme = "README.md" @@ -26,7 +26,7 @@ path = "src/lib.rs" default = [] # openssl -ssl = ["openssl", "actix-connect/ssl"] +ssl = ["openssl", "actix-connect/ssl", "actix-server-config/ssl"] # brotli encoding, requires c compiler brotli = ["brotli2"] @@ -48,7 +48,7 @@ actix-service = "0.3.6" actix-codec = "0.1.2" actix-connect = "0.1.4" actix-utils = "0.3.5" -actix-server-config = "0.1.0" +actix-server-config = "0.1.1" actix-threadpool = "0.1.0" base64 = "0.10" @@ -60,7 +60,7 @@ derive_more = "0.14" either = "1.5.2" encoding = "0.2" futures = "0.1" -hashbrown = "0.2.0" +hashbrown = "0.2.2" h2 = "0.1.16" http = "0.1.17" httparse = "1.3" @@ -76,10 +76,10 @@ serde = "1.0" serde_json = "1.0" sha1 = "0.6" slab = "0.4" -serde_urlencoded = "0.5.3" +serde_urlencoded = "0.5.5" time = "0.1" tokio-tcp = "0.1.3" -tokio-timer = "0.2" +tokio-timer = "0.2.8" tokio-current-thread = "0.1" trust-dns-resolver = { version="0.11.0", default-features = false } @@ -96,7 +96,7 @@ openssl = { version="0.10", optional = true } [dev-dependencies] actix-rt = "0.2.2" -actix-server = { version = "0.4.1", features=["ssl"] } +actix-server = { version = "0.4.3", features=["ssl"] } actix-connect = { version = "0.1.4", features=["ssl"] } actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] } env_logger = "0.6" diff --git a/actix-http/src/h1/codec.rs b/actix-http/src/h1/codec.rs index 1f3983adb..1e1e1602f 100644 --- a/actix-http/src/h1/codec.rs +++ b/actix-http/src/h1/codec.rs @@ -1,6 +1,6 @@ #![allow(unused_imports, unused_variables, dead_code)] -use std::fmt; -use std::io::{self, Write}; +use std::io::Write; +use std::{fmt, io, net}; use actix_codec::{Decoder, Encoder}; use bitflags::bitflags; @@ -40,7 +40,6 @@ pub struct Codec { // encoder part flags: Flags, encoder: encoder::MessageEncoder>, - // headers_size: u32, } impl Default for Codec { @@ -67,13 +66,11 @@ impl Codec { }; Codec { config, + flags, decoder: decoder::MessageDecoder::default(), payload: None, version: Version::HTTP_11, ctype: ConnectionType::Close, - - flags, - // headers_size: 0, encoder: encoder::MessageEncoder::default(), } } diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index cf39b8232..758466837 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -1,8 +1,9 @@ use std::collections::VecDeque; use std::time::Instant; -use std::{fmt, io}; +use std::{fmt, io, net}; -use actix_codec::{AsyncRead, AsyncWrite, Decoder, Encoder, Framed, FramedParts}; +use actix_codec::{Decoder, Encoder, Framed, FramedParts}; +use actix_server_config::IoStream; use actix_service::Service; use actix_utils::cloneable::CloneableService; use bitflags::bitflags; @@ -81,6 +82,7 @@ where expect: CloneableService, upgrade: Option>, flags: Flags, + peer_addr: Option, error: Option, state: State, @@ -161,7 +163,7 @@ impl PartialEq for PollResponse { impl Dispatcher where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Response: Into>, @@ -220,14 +222,15 @@ where Dispatcher { inner: DispatcherState::Normal(InnerDispatcher { - io, - codec, - read_buf, write_buf: BytesMut::with_capacity(HW_BUFFER_SIZE), payload: None, state: State::None, error: None, + peer_addr: io.peer_addr(), messages: VecDeque::new(), + io, + codec, + read_buf, service, expect, upgrade, @@ -241,7 +244,7 @@ where impl InnerDispatcher where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Response: Into>, @@ -490,6 +493,7 @@ where match msg { Message::Item(mut req) => { let pl = self.codec.message_type(); + req.head_mut().peer_addr = self.peer_addr; if pl == MessageType::Stream && self.upgrade.is_some() { self.messages.push_back(DispatcherMessage::Upgrade(req)); @@ -649,7 +653,7 @@ where impl Future for Dispatcher where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Response: Into>, diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index f92fd0c89..ecf6c8b93 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -1,8 +1,8 @@ use std::fmt; use std::marker::PhantomData; -use actix_codec::{AsyncRead, AsyncWrite, Framed}; -use actix_server_config::{Io, ServerConfig as SrvConfig}; +use actix_codec::Framed; +use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig}; use actix_service::{IntoNewService, NewService, Service}; use actix_utils::cloneable::CloneableService; use futures::future::{ok, FutureResult}; @@ -104,7 +104,7 @@ where impl NewService for H1Service where - T: AsyncRead + AsyncWrite, + T: IoStream, S: NewService, S::Error: Into, S::Response: Into>, @@ -161,7 +161,7 @@ where impl Future for H1ServiceResponse where - T: AsyncRead + AsyncWrite, + T: IoStream, S: NewService, S::Error: Into, S::Response: Into>, @@ -245,7 +245,7 @@ where impl Service for H1ServiceHandler where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Response: Into>, @@ -309,7 +309,7 @@ pub struct OneRequest { impl OneRequest where - T: AsyncRead + AsyncWrite, + T: IoStream, { /// Create new `H1SimpleService` instance. pub fn new() -> Self { @@ -322,7 +322,7 @@ where impl NewService for OneRequest where - T: AsyncRead + AsyncWrite, + T: IoStream, { type Request = Io; type Response = (Request, Framed); @@ -348,7 +348,7 @@ pub struct OneRequestService { impl Service for OneRequestService where - T: AsyncRead + AsyncWrite, + T: IoStream, { type Request = Io; type Response = (Request, Framed); @@ -372,14 +372,14 @@ where #[doc(hidden)] pub struct OneRequestServiceResponse where - T: AsyncRead + AsyncWrite, + T: IoStream, { framed: Option>, } impl Future for OneRequestServiceResponse where - T: AsyncRead + AsyncWrite, + T: IoStream, { type Item = (Request, Framed); type Error = ParseError; diff --git a/actix-http/src/h2/dispatcher.rs b/actix-http/src/h2/dispatcher.rs index de0b761f5..e66ff63c3 100644 --- a/actix-http/src/h2/dispatcher.rs +++ b/actix-http/src/h2/dispatcher.rs @@ -1,9 +1,10 @@ use std::collections::VecDeque; use std::marker::PhantomData; use std::time::Instant; -use std::{fmt, mem}; +use std::{fmt, mem, net}; use actix_codec::{AsyncRead, AsyncWrite}; +use actix_server_config::IoStream; use actix_service::Service; use actix_utils::cloneable::CloneableService; use bitflags::bitflags; @@ -29,14 +30,11 @@ use crate::response::Response; const CHUNK_SIZE: usize = 16_384; /// Dispatcher for HTTP/2 protocol -pub struct Dispatcher< - T: AsyncRead + AsyncWrite, - S: Service, - B: MessageBody, -> { +pub struct Dispatcher, B: MessageBody> { service: CloneableService, connection: Connection, config: ServiceConfig, + peer_addr: Option, ka_expire: Instant, ka_timer: Option, _t: PhantomData, @@ -44,7 +42,7 @@ pub struct Dispatcher< impl Dispatcher where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Future: 'static, @@ -56,6 +54,7 @@ where connection: Connection, config: ServiceConfig, timeout: Option, + peer_addr: Option, ) -> Self { // let keepalive = config.keep_alive_enabled(); // let flags = if keepalive { @@ -76,9 +75,10 @@ where Dispatcher { service, config, + peer_addr, + connection, ka_expire, ka_timer, - connection, _t: PhantomData, } } @@ -86,7 +86,7 @@ where impl Future for Dispatcher where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Future: 'static, @@ -117,6 +117,7 @@ where head.method = parts.method; head.version = parts.version; head.headers = parts.headers.into(); + head.peer_addr = self.peer_addr; tokio_current_thread::spawn(ServiceResponse:: { state: ServiceResponseState::ServiceCall( self.service.call(req), diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index 8ab244b50..42b8d8d82 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use std::{io, net}; use actix_codec::{AsyncRead, AsyncWrite, Framed}; -use actix_server_config::{Io, ServerConfig as SrvConfig}; +use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig}; use actix_service::{IntoNewService, NewService, Service}; use actix_utils::cloneable::CloneableService; use bytes::Bytes; @@ -63,7 +63,7 @@ where impl NewService for H2Service where - T: AsyncRead + AsyncWrite, + T: IoStream, S: NewService, S::Error: Into, S::Response: Into>, @@ -95,7 +95,7 @@ pub struct H2ServiceResponse, impl Future for H2ServiceResponse where - T: AsyncRead + AsyncWrite, + T: IoStream, S: NewService, S::Error: Into, S::Response: Into>, @@ -140,7 +140,7 @@ where impl Service for H2ServiceHandler where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Future: 'static, @@ -161,17 +161,20 @@ where } fn call(&mut self, req: Self::Request) -> Self::Future { + let io = req.into_parts().0; + let peer_addr = io.peer_addr(); H2ServiceHandlerResponse { state: State::Handshake( Some(self.srv.clone()), Some(self.cfg.clone()), - server::handshake(req.into_parts().0), + peer_addr, + server::handshake(io), ), } } } -enum State, B: MessageBody> +enum State, B: MessageBody> where S::Future: 'static, { @@ -179,13 +182,14 @@ where Handshake( Option>, Option, + Option, Handshake, ), } pub struct H2ServiceHandlerResponse where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Future: 'static, @@ -197,7 +201,7 @@ where impl Future for H2ServiceHandlerResponse where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Future: 'static, @@ -210,24 +214,28 @@ where fn poll(&mut self) -> Poll { match self.state { State::Incoming(ref mut disp) => disp.poll(), - State::Handshake(ref mut srv, ref mut config, ref mut handshake) => { - match handshake.poll() { - Ok(Async::Ready(conn)) => { - self.state = State::Incoming(Dispatcher::new( - srv.take().unwrap(), - conn, - config.take().unwrap(), - None, - )); - self.poll() - } - Ok(Async::NotReady) => Ok(Async::NotReady), - Err(err) => { - trace!("H2 handshake error: {}", err); - Err(err.into()) - } + State::Handshake( + ref mut srv, + ref mut config, + ref peer_addr, + ref mut handshake, + ) => match handshake.poll() { + Ok(Async::Ready(conn)) => { + self.state = State::Incoming(Dispatcher::new( + srv.take().unwrap(), + conn, + config.take().unwrap(), + None, + peer_addr.clone(), + )); + self.poll() } - } + Ok(Async::NotReady) => Ok(Async::NotReady), + Err(err) => { + trace!("H2 handshake error: {}", err); + Err(err.into()) + } + }, } } } diff --git a/actix-http/src/message.rs b/actix-http/src/message.rs index 61ca5161e..7f2dc603f 100644 --- a/actix-http/src/message.rs +++ b/actix-http/src/message.rs @@ -1,4 +1,5 @@ use std::cell::{Ref, RefCell, RefMut}; +use std::net; use std::rc::Rc; use bitflags::bitflags; @@ -43,6 +44,7 @@ pub struct RequestHead { pub version: Version, pub headers: HeaderMap, pub extensions: RefCell, + pub peer_addr: Option, flags: Flags, } @@ -54,6 +56,7 @@ impl Default for RequestHead { version: Version::HTTP_11, headers: HeaderMap::with_capacity(16), flags: Flags::empty(), + peer_addr: None, extensions: RefCell::new(Extensions::new()), } } diff --git a/actix-http/src/request.rs b/actix-http/src/request.rs index 468b4e337..5ba07929a 100644 --- a/actix-http/src/request.rs +++ b/actix-http/src/request.rs @@ -1,5 +1,5 @@ use std::cell::{Ref, RefMut}; -use std::fmt; +use std::{fmt, net}; use http::{header, Method, Uri, Version}; @@ -139,6 +139,7 @@ impl

Request

{ } /// Check if request requires connection upgrade + #[inline] pub fn upgrade(&self) -> bool { if let Some(conn) = self.head().headers.get(header::CONNECTION) { if let Ok(s) = conn.to_str() { @@ -147,6 +148,15 @@ impl

Request

{ } self.head().method == Method::CONNECT } + + /// Peer socket address + /// + /// Peer address is actual socket address, if proxy is used in front of + /// actix http server, then peer address would be address of this proxy. + #[inline] + pub fn peer_addr(&self) -> Option { + self.head().peer_addr + } } impl

fmt::Debug for Request

{ diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index 2af1238b1..dd3af1db0 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -1,8 +1,10 @@ use std::marker::PhantomData; -use std::{fmt, io}; +use std::{fmt, io, net}; use actix_codec::{AsyncRead, AsyncWrite, Framed}; -use actix_server_config::{Io as ServerIo, Protocol, ServerConfig as SrvConfig}; +use actix_server_config::{ + Io as ServerIo, IoStream, Protocol, ServerConfig as SrvConfig, +}; use actix_service::{IntoNewService, NewService, Service}; use actix_utils::cloneable::CloneableService; use bytes::{Buf, BufMut, Bytes, BytesMut}; @@ -128,7 +130,7 @@ where impl NewService for HttpService where - T: AsyncRead + AsyncWrite, + T: IoStream, S: NewService, S::Error: Into, S::InitError: fmt::Debug, @@ -182,7 +184,7 @@ pub struct HttpServiceResponse< impl Future for HttpServiceResponse where - T: AsyncRead + AsyncWrite, + T: IoStream, S: NewService, S::Error: Into, S::InitError: fmt::Debug, @@ -268,7 +270,7 @@ where impl Service for HttpServiceHandler where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Future: 'static, @@ -317,6 +319,7 @@ where let (io, _, proto) = req.into_parts(); match proto { Protocol::Http2 => { + let peer_addr = io.peer_addr(); let io = Io { inner: io, unread: None, @@ -326,6 +329,7 @@ where server::handshake(io), self.cfg.clone(), self.srv.clone(), + peer_addr, ))), } } @@ -357,7 +361,7 @@ where S: Service, S::Future: 'static, S::Error: Into, - T: AsyncRead + AsyncWrite, + T: IoStream, B: MessageBody, X: Service, X::Error: Into, @@ -376,12 +380,19 @@ where Option>, )>, ), - Handshake(Option<(Handshake, Bytes>, ServiceConfig, CloneableService)>), + Handshake( + Option<( + Handshake, Bytes>, + ServiceConfig, + CloneableService, + Option, + )>, + ), } pub struct HttpServiceHandlerResponse where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Future: 'static, @@ -399,7 +410,7 @@ const HTTP2_PREFACE: [u8; 14] = *b"PRI * HTTP/2.0"; impl Future for HttpServiceHandlerResponse where - T: AsyncRead + AsyncWrite, + T: IoStream, S: Service, S::Error: Into, S::Future: 'static, @@ -437,12 +448,17 @@ where } let (io, buf, cfg, srv, expect, upgrade) = data.take().unwrap(); if buf[..14] == HTTP2_PREFACE[..] { + let peer_addr = io.peer_addr(); let io = Io { inner: io, unread: Some(buf), }; - self.state = - State::Handshake(Some((server::handshake(io), cfg, srv))); + self.state = State::Handshake(Some(( + server::handshake(io), + cfg, + srv, + peer_addr, + ))); } else { self.state = State::H1(h1::Dispatcher::with_timeout( io, @@ -470,8 +486,8 @@ where } else { panic!() }; - let (_, cfg, srv) = data.take().unwrap(); - self.state = State::H2(Dispatcher::new(srv, conn, cfg, None)); + let (_, cfg, srv, peer_addr) = data.take().unwrap(); + self.state = State::H2(Dispatcher::new(srv, conn, cfg, None, peer_addr)); self.poll() } } @@ -523,3 +539,25 @@ impl AsyncWrite for Io { self.inner.write_buf(buf) } } + +impl IoStream for Io { + #[inline] + fn peer_addr(&self) -> Option { + self.inner.peer_addr() + } + + #[inline] + fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> { + self.inner.set_nodelay(nodelay) + } + + #[inline] + fn set_linger(&mut self, dur: Option) -> io::Result<()> { + self.inner.set_linger(dur) + } + + #[inline] + fn set_keepalive(&mut self, dur: Option) -> io::Result<()> { + self.inner.set_keepalive(dur) + } +} diff --git a/actix-http/src/test.rs b/actix-http/src/test.rs index ce55912f7..b4344a676 100644 --- a/actix-http/src/test.rs +++ b/actix-http/src/test.rs @@ -4,6 +4,7 @@ use std::io; use std::str::FromStr; use actix_codec::{AsyncRead, AsyncWrite}; +use actix_server_config::IoStream; use bytes::{Buf, Bytes, BytesMut}; use futures::{Async, Poll}; use http::header::{self, HeaderName, HeaderValue}; @@ -253,3 +254,17 @@ impl AsyncWrite for TestBuffer { Ok(Async::NotReady) } } + +impl IoStream for TestBuffer { + fn set_nodelay(&mut self, _nodelay: bool) -> io::Result<()> { + Ok(()) + } + + fn set_linger(&mut self, _dur: Option) -> io::Result<()> { + Ok(()) + } + + fn set_keepalive(&mut self, _dur: Option) -> io::Result<()> { + Ok(()) + } +} diff --git a/actix-http/tests/test_server.rs b/actix-http/tests/test_server.rs index e53ff0212..4b56e4b2c 100644 --- a/actix-http/tests/test_server.rs +++ b/actix-http/tests/test_server.rs @@ -35,7 +35,10 @@ fn test_h1() { .keep_alive(KeepAlive::Disabled) .client_timeout(1000) .client_disconnect(1000) - .h1(|_| future::ok::<_, ()>(Response::Ok().finish())) + .h1(|req: Request| { + assert!(req.peer_addr().is_some()); + future::ok::<_, ()>(Response::Ok().finish()) + }) }); let response = srv.block_on(srv.get("/").send()).unwrap(); @@ -50,6 +53,7 @@ fn test_h1_2() { .client_timeout(1000) .client_disconnect(1000) .finish(|req: Request| { + assert!(req.peer_addr().is_some()); assert_eq!(req.version(), http::Version::HTTP_11); future::ok::<_, ()>(Response::Ok().finish()) }) @@ -115,6 +119,7 @@ fn test_h2_1() -> std::io::Result<()> { .and_then( HttpService::build() .finish(|req: Request| { + assert!(req.peer_addr().is_some()); assert_eq!(req.version(), http::Version::HTTP_2); future::ok::<_, Error>(Response::Ok().finish()) }) From 420d3064c5b748d40c64473f5ac0de2ad851ef26 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Apr 2019 10:11:38 -0700 Subject: [PATCH 04/15] Add .peer_addr() #744 --- CHANGES.md | 6 ++++-- src/info.rs | 10 +++++----- src/middleware/logger.rs | 15 ++++++++------- src/request.rs | 13 ++++++++++++- src/service.rs | 20 +++++++++++++++++++- 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8909f3e29..00518764d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,12 +1,14 @@ # Changes -## [1.0.0-alpha.7] - 2019-04-xx +## [1.0.0-beta.1] - 2019-04-xx ### Added -* Added helper functions for reading test response body, +* Add helper functions for reading test response body, `test::read_response()` and test::read_response_json()` +* Add `.peer_addr()` #744 + ### Changed * Rename `RouterConfig` to `ServiceConfig` diff --git a/src/info.rs b/src/info.rs index ece17bf04..e9b375875 100644 --- a/src/info.rs +++ b/src/info.rs @@ -30,7 +30,7 @@ impl ConnectionInfo { let mut host = None; let mut scheme = None; let mut remote = None; - let peer = None; + let mut peer = None; // load forwarded header for hdr in req.headers.get_all(&header::FORWARDED) { @@ -116,10 +116,10 @@ impl ConnectionInfo { remote = h.split(',').next().map(|v| v.trim()); } } - // if remote.is_none() { - // get peeraddr from socketaddr - // peer = req.peer_addr().map(|addr| format!("{}", addr)); - // } + if remote.is_none() { + // get peeraddr from socketaddr + peer = req.peer_addr.map(|addr| format!("{}", addr)); + } } ConnectionInfo { diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs index d5fca526b..43893bc0f 100644 --- a/src/middleware/logger.rs +++ b/src/middleware/logger.rs @@ -363,13 +363,6 @@ impl FormatText { let rt = (rt.num_nanoseconds().unwrap_or(0) as f64) / 1_000_000.0; fmt.write_fmt(format_args!("{:.6}", rt)) } - // FormatText::RemoteAddr => { - // if let Some(remote) = req.connection_info().remote() { - // return remote.fmt(fmt); - // } else { - // "-".fmt(fmt) - // } - // } FormatText::EnvironHeader(ref name) => { if let Ok(val) = env::var(name) { fmt.write_fmt(format_args!("{}", val)) @@ -441,6 +434,14 @@ impl FormatText { }; *self = FormatText::Str(s.to_string()); } + FormatText::RemoteAddr => { + let s = if let Some(remote) = req.connection_info().remote() { + FormatText::Str(remote.to_string()) + } else { + FormatText::Str("-".to_string()) + }; + *self = s; + } _ => (), } } diff --git a/src/request.rs b/src/request.rs index 5823c08ca..ad5b2488f 100644 --- a/src/request.rs +++ b/src/request.rs @@ -1,6 +1,6 @@ use std::cell::{Ref, RefCell, RefMut}; -use std::fmt; use std::rc::Rc; +use std::{fmt, net}; use actix_http::http::{HeaderMap, Method, Uri, Version}; use actix_http::{Error, Extensions, HttpMessage, Message, Payload, RequestHead}; @@ -170,6 +170,17 @@ impl HttpRequest { self.url_for(name, &NO_PARAMS) } + /// Peer socket address + /// + /// Peer address is actual socket address, if proxy is used in front of + /// actix http server, then peer address would be address of this proxy. + /// + /// To get client connection information `.connection_info()` should be used. + #[inline] + pub fn peer_addr(&self) -> Option { + self.head().peer_addr + } + /// Get *ConnectionInfo* for the current request. #[inline] pub fn connection_info(&self) -> Ref { diff --git a/src/service.rs b/src/service.rs index 8bc2ff9a5..5303436ce 100644 --- a/src/service.rs +++ b/src/service.rs @@ -1,5 +1,5 @@ use std::cell::{Ref, RefMut}; -use std::fmt; +use std::{fmt, net}; use actix_http::body::{Body, MessageBody, ResponseBody}; use actix_http::http::{HeaderMap, Method, StatusCode, Uri, Version}; @@ -12,6 +12,7 @@ use futures::future::{ok, FutureResult, IntoFuture}; use crate::config::{AppConfig, AppService}; use crate::data::Data; +use crate::info::ConnectionInfo; use crate::request::HttpRequest; pub trait HttpServiceFactory { @@ -134,6 +135,23 @@ impl ServiceRequest { } } + /// Peer socket address + /// + /// Peer address is actual socket address, if proxy is used in front of + /// actix http server, then peer address would be address of this proxy. + /// + /// To get client connection information `ConnectionInfo` should be used. + #[inline] + pub fn peer_addr(&self) -> Option { + self.head().peer_addr + } + + /// Get *ConnectionInfo* for the current request. + #[inline] + pub fn connection_info(&self) -> Ref { + ConnectionInfo::get(self.head(), &*self.app_config()) + } + /// Get a reference to the Path parameters. /// /// Params is a container for url parameters. From 3744957804c7fae209aa4eb6f5d1fb180f7eda36 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Apr 2019 10:27:58 -0700 Subject: [PATCH 05/15] actix_http::encoding always available --- actix-http/CHANGES.md | 2 ++ actix-http/src/lib.rs | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index dc56b0401..3f2ccd4eb 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -8,6 +8,8 @@ ### Changed +* `actix_http::encoding` always available + * use trust-dns-resolver 0.11.0 diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index 5af802601..ac085eaea 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -12,7 +12,6 @@ pub mod body; mod builder; pub mod client; mod config; -#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust", feature = "brotli"))] pub mod encoding; mod extensions; mod header; From 2986077a2839314f61133ed339b3e7fb04f77b02 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Apr 2019 10:32:48 -0700 Subject: [PATCH 06/15] no need for feature --- actix-http/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 746699a07..205f39cd7 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -26,7 +26,7 @@ path = "src/lib.rs" default = [] # openssl -ssl = ["openssl", "actix-connect/ssl", "actix-server-config/ssl"] +ssl = ["openssl", "actix-connect/ssl"] # brotli encoding, requires c compiler brotli = ["brotli2"] From ddfd7523f7f4b81c29d4aa91256d41e1742bdc39 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Apr 2019 10:49:38 -0700 Subject: [PATCH 07/15] prepare awc release --- Cargo.toml | 4 ++-- awc/CHANGES.md | 5 +++++ awc/Cargo.toml | 8 ++++---- awc/README.md | 32 ++++++++++++++++++++++++++++++++ test-server/Cargo.toml | 4 ++-- 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 68979d096..e77292c05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,7 @@ actix-utils = "0.3.4" actix-router = "0.1.2" actix-rt = "0.2.2" actix-web-codegen = "0.1.0-alpha.6" -actix-http = { version = "0.1.0-alpha.5", features=["fail"] } +actix-http = { version = "0.1.0", features=["fail"] } actix-server = "0.4.3" actix-server-config = "0.1.1" actix-threadpool = "0.1.0" @@ -98,7 +98,7 @@ openssl = { version="0.10", optional = true } rustls = { version = "^0.15", optional = true } [dev-dependencies] -actix-http = { version = "0.1.0-alpha.5", features=["ssl", "brotli", "flate2-zlib"] } +actix-http = { version = "0.1.0", features=["ssl", "brotli", "flate2-zlib"] } actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] } actix-files = { version = "0.1.0-alpha.6" } rand = "0.6" diff --git a/awc/CHANGES.md b/awc/CHANGES.md index ddeefd94c..fa85ef3bb 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,5 +1,10 @@ # Changes +## [0.1.0] - 2019-04-16 + +* No changes + + ## [0.1.0-alpha.6] - 2019-04-14 ### Changed diff --git a/awc/Cargo.toml b/awc/Cargo.toml index cbca0f477..681131218 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "0.1.0-alpha.6" +version = "0.1.0" authors = ["Nikolay Kim "] description = "Actix http client." readme = "README.md" @@ -38,7 +38,7 @@ flate2-rust = ["actix-http/flate2-rust"] [dependencies] actix-codec = "0.1.2" actix-service = "0.3.6" -actix-http = "0.1.0-alpha.5" +actix-http = "0.1.0" base64 = "0.10.1" bytes = "0.4" derive_more = "0.14" @@ -56,10 +56,10 @@ openssl = { version="0.10", optional = true } [dev-dependencies] actix-rt = "0.2.2" actix-web = { version = "1.0.0-alpha.6", features=["ssl"] } -actix-http = { version = "0.1.0-alpha.5", features=["ssl"] } +actix-http = { version = "0.1.0", features=["ssl"] } actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] } actix-utils = "0.3.4" -actix-server = { version = "0.4.1", features=["ssl"] } +actix-server = { version = "0.4.3", features=["ssl"] } brotli2 = { version="0.3.2" } flate2 = { version="1.0.2" } env_logger = "0.6" diff --git a/awc/README.md b/awc/README.md index bb64559c1..d9eb45f8c 100644 --- a/awc/README.md +++ b/awc/README.md @@ -1 +1,33 @@ # Actix http client [![Build Status](https://travis-ci.org/actix/actix-web.svg?branch=master)](https://travis-ci.org/actix/actix-web) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) [![crates.io](https://meritbadge.herokuapp.com/awc)](https://crates.io/crates/awc) [![Join the chat at https://gitter.im/actix/actix](https://badges.gitter.im/actix/actix.svg)](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +An HTTP Client + +## Documentation & community resources + +* [User Guide](https://actix.rs/docs/) +* [API Documentation](https://docs.rs/awc/) +* [Chat on gitter](https://gitter.im/actix/actix) +* Cargo package: [actix-http](https://crates.io/crates/awc) +* Minimum supported Rust version: 1.33 or later + +## Example + +```rust +# use futures::future::{Future, lazy}; +use actix_rt::System; +use awc::Client; + +fn main() { + System::new("test").block_on(lazy(|| { + let mut client = Client::default(); + + client.get("http://www.rust-lang.org") // <- Create request builder + .header("User-Agent", "Actix-web") + .send() // <- Send http request + .and_then(|response| { // <- server http response + println!("Response: {:?}", response); + Ok(()) + }) + })); +} +``` diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index 873eaea87..5b84533cf 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -33,7 +33,7 @@ ssl = ["openssl", "actix-server/ssl", "awc/ssl"] actix-codec = "0.1.2" actix-rt = "0.2.2" actix-service = "0.3.6" -actix-server = "0.4.1" +actix-server = "0.4.3" actix-utils = "0.3.5" awc = "0.1.0-alpha.5" @@ -56,4 +56,4 @@ openssl = { version="0.10", optional = true } [dev-dependencies] actix-web = "1.0.0-alpha.5" -actix-http = "0.1.0-alpha.5" +actix-http = "0.1.0" From e7ec77aa81dad46092878ec6ef1e201efbfcd155 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Apr 2019 10:50:37 -0700 Subject: [PATCH 08/15] update readme --- awc/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/awc/README.md b/awc/README.md index d9eb45f8c..3b0034d76 100644 --- a/awc/README.md +++ b/awc/README.md @@ -7,15 +7,15 @@ An HTTP Client * [User Guide](https://actix.rs/docs/) * [API Documentation](https://docs.rs/awc/) * [Chat on gitter](https://gitter.im/actix/actix) -* Cargo package: [actix-http](https://crates.io/crates/awc) +* Cargo package: [awc](https://crates.io/crates/awc) * Minimum supported Rust version: 1.33 or later ## Example ```rust -# use futures::future::{Future, lazy}; use actix_rt::System; use awc::Client; +use futures::future::{Future, lazy}; fn main() { System::new("test").block_on(lazy(|| { From 4c0ebd55d3a759d1b1360857f92579c3341c435f Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Apr 2019 11:02:26 -0700 Subject: [PATCH 09/15] prepare actix-http-test release --- Cargo.toml | 2 +- test-server/CHANGES.md | 5 +++++ test-server/Cargo.toml | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e77292c05..dc7530932 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,7 +75,7 @@ actix-http = { version = "0.1.0", features=["fail"] } actix-server = "0.4.3" actix-server-config = "0.1.1" actix-threadpool = "0.1.0" -awc = { version = "0.1.0-alpha.6", optional = true } +awc = { version = "0.1.0", optional = true } bytes = "0.4" derive_more = "0.14" diff --git a/test-server/CHANGES.md b/test-server/CHANGES.md index 14a8ce628..cec01fde6 100644 --- a/test-server/CHANGES.md +++ b/test-server/CHANGES.md @@ -1,5 +1,10 @@ # Changes +## [0.1.0] - 2019-04-16 + +* No changes + + ## [0.1.0-alpha.3] - 2019-04-02 * Request functions accept path #743 diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index 5b84533cf..657dd2615 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http-test" -version = "0.1.0-alpha.3" +version = "0.1.0" authors = ["Nikolay Kim "] description = "Actix http test server" readme = "README.md" @@ -35,7 +35,7 @@ actix-rt = "0.2.2" actix-service = "0.3.6" actix-server = "0.4.3" actix-utils = "0.3.5" -awc = "0.1.0-alpha.5" +awc = "0.1.0" base64 = "0.10" bytes = "0.4" From c943e95812ecb71ac0c3abc4c2513bc185606d3a Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Apr 2019 11:17:29 -0700 Subject: [PATCH 10/15] update dependencies --- Cargo.toml | 3 +-- actix-framed/Cargo.toml | 6 +++--- actix-http/Cargo.toml | 2 +- actix-multipart/Cargo.toml | 4 ++-- actix-web-actors/Cargo.toml | 4 ++-- actix-web-codegen/Cargo.toml | 4 ++-- awc/Cargo.toml | 2 +- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dc7530932..535bcb82d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,7 +99,7 @@ rustls = { version = "^0.15", optional = true } [dev-dependencies] actix-http = { version = "0.1.0", features=["ssl", "brotli", "flate2-zlib"] } -actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] } +actix-http-test = { version = "0.1.0", features=["ssl"] } actix-files = { version = "0.1.0-alpha.6" } rand = "0.6" env_logger = "0.6" @@ -116,7 +116,6 @@ codegen-units = 1 [patch.crates-io] actix-web = { path = "." } actix-http = { path = "actix-http" } -actix-http-test = { path = "test-server" } actix-web-codegen = { path = "actix-web-codegen" } actix-web-actors = { path = "actix-web-actors" } actix-session = { path = "actix-session" } diff --git a/actix-framed/Cargo.toml b/actix-framed/Cargo.toml index ba433e17e..38f12f440 100644 --- a/actix-framed/Cargo.toml +++ b/actix-framed/Cargo.toml @@ -25,13 +25,13 @@ actix-service = "0.3.6" actix-utils = "0.3.4" actix-router = "0.1.2" actix-rt = "0.2.2" -actix-http = "0.1.0-alpha.5" +actix-http = "0.1.0" bytes = "0.4" futures = "0.1.25" log = "0.4" [dev-dependencies] -actix-server = { version = "0.4.1", features=["ssl"] } +actix-server = { version = "0.4.3", features=["ssl"] } actix-connect = { version = "0.1.4", features=["ssl"] } -actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] } +actix-http-test = { version = "0.1.0", features=["ssl"] } diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 205f39cd7..575a08a0e 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -98,7 +98,7 @@ openssl = { version="0.10", optional = true } actix-rt = "0.2.2" actix-server = { version = "0.4.3", features=["ssl"] } actix-connect = { version = "0.1.4", features=["ssl"] } -actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] } +actix-http-test = { version = "0.1.0", features=["ssl"] } env_logger = "0.6" serde_derive = "1.0" openssl = { version="0.10" } diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 006f7066a..58ab45230 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -18,7 +18,7 @@ name = "actix_multipart" path = "src/lib.rs" [dependencies] -actix-web = "1.0.0-alpha.3" +actix-web = "1.0.0-alpha.6" actix-service = "0.3.4" bytes = "0.4" derive_more = "0.14" @@ -31,4 +31,4 @@ twoway = "0.2" [dev-dependencies] actix-rt = "0.2.2" -actix-http = "0.1.0-alpha.3" \ No newline at end of file +actix-http = "0.1.0" \ No newline at end of file diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index f56b47fbf..3e67c2313 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -20,11 +20,11 @@ path = "src/lib.rs" [dependencies] actix = "0.8.0" actix-web = "1.0.0-alpha.5" -actix-http = "0.1.0-alpha.5" +actix-http = "0.1.0" actix-codec = "0.1.2" bytes = "0.4" futures = "0.1.25" [dev-dependencies] env_logger = "0.6" -actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] } +actix-http-test = { version = "0.1.0", features=["ssl"] } diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 26dbd9b71..13928f67a 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -17,6 +17,6 @@ syn = { version = "0.15", features = ["full", "parsing"] } [dev-dependencies] actix-web = { version = "1.0.0-alpha.6" } -actix-http = { version = "0.1.0-alpha.5", features=["ssl"] } -actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] } +actix-http = { version = "0.1.0", features=["ssl"] } +actix-http-test = { version = "0.1.0", features=["ssl"] } futures = { version = "0.1" } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 681131218..bbc3d9287 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -57,7 +57,7 @@ openssl = { version="0.10", optional = true } actix-rt = "0.2.2" actix-web = { version = "1.0.0-alpha.6", features=["ssl"] } actix-http = { version = "0.1.0", features=["ssl"] } -actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] } +actix-http-test = { version = "0.1.0", features=["ssl"] } actix-utils = "0.3.4" actix-server = { version = "0.4.3", features=["ssl"] } brotli2 = { version="0.3.2" } From 5740f1e63ac9568ce623c2b46b0c1d429ae4ea90 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Apr 2019 11:18:47 -0700 Subject: [PATCH 11/15] prepare actix-framed release --- actix-framed/Cargo.toml | 2 +- actix-framed/changes.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/actix-framed/Cargo.toml b/actix-framed/Cargo.toml index 38f12f440..f0622fd90 100644 --- a/actix-framed/Cargo.toml +++ b/actix-framed/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-framed" -version = "0.1.0-alpha.1" +version = "0.1.0" authors = ["Nikolay Kim "] description = "Actix framed app server" readme = "README.md" diff --git a/actix-framed/changes.md b/actix-framed/changes.md index 125e22bcd..9cef3c057 100644 --- a/actix-framed/changes.md +++ b/actix-framed/changes.md @@ -1,5 +1,10 @@ # Changes +## [0.1.0] - 2019-04-16 + +* Update tests + + ## [0.1.0-alpha.1] - 2019-04-12 * Initial release From cc8420377e93c0a82d3b1b3f5865b75a67789cc4 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Apr 2019 15:43:55 -0700 Subject: [PATCH 12/15] pass request ownership to closure instead of ref --- awc/CHANGES.md | 7 +++++++ awc/src/request.rs | 14 ++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index fa85ef3bb..a4f43d292 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,5 +1,12 @@ # Changes +## [0.1.1] - 2019-04-xx + +### Changed + +* `ClientRequest::if_true()` and `ClientRequest::if_some()` use instance instead of ref + + ## [0.1.0] - 2019-04-16 * No changes diff --git a/awc/src/request.rs b/awc/src/request.rs index c97e08f81..d6716cdcf 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -333,24 +333,26 @@ impl ClientRequest { /// value is `true`. pub fn if_true(mut self, value: bool, f: F) -> Self where - F: FnOnce(&mut ClientRequest), + F: FnOnce(ClientRequest) -> ClientRequest, { if value { - f(&mut self); + f(self) + } else { + self } - self } /// This method calls provided closure with builder reference if /// value is `Some`. pub fn if_some(mut self, value: Option, f: F) -> Self where - F: FnOnce(T, &mut ClientRequest), + F: FnOnce(T, ClientRequest) -> ClientRequest, { if let Some(val) = value { - f(val, &mut self); + f(val, self) + } else { + self } - self } /// Complete request construction and send body. From b64851c5ec286a547c36bd00a5a720fb60500ffb Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 17 Apr 2019 10:28:27 -0700 Subject: [PATCH 13/15] enable runtime for test:: methods --- awc/src/request.rs | 4 +-- src/responder.rs | 4 +-- src/test.rs | 65 +++++++++++++++++++--------------------------- 3 files changed, 31 insertions(+), 42 deletions(-) diff --git a/awc/src/request.rs b/awc/src/request.rs index d6716cdcf..c868d052b 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -331,7 +331,7 @@ impl ClientRequest { /// This method calls provided closure with builder reference if /// value is `true`. - pub fn if_true(mut self, value: bool, f: F) -> Self + pub fn if_true(self, value: bool, f: F) -> Self where F: FnOnce(ClientRequest) -> ClientRequest, { @@ -344,7 +344,7 @@ impl ClientRequest { /// This method calls provided closure with builder reference if /// value is `Some`. - pub fn if_some(mut self, value: Option, f: F) -> Self + pub fn if_some(self, value: Option, f: F) -> Self where F: FnOnce(T, ClientRequest) -> ClientRequest, { diff --git a/src/responder.rs b/src/responder.rs index 3e0676289..103009e75 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -307,11 +307,11 @@ pub(crate) mod tests { ); let req = TestRequest::with_uri("/none").to_request(); - let resp = TestRequest::block_on(srv.call(req)).unwrap(); + let resp = block_on(srv.call(req)).unwrap(); assert_eq!(resp.status(), StatusCode::NOT_FOUND); let req = TestRequest::with_uri("/some").to_request(); - let resp = TestRequest::block_on(srv.call(req)).unwrap(); + let resp = block_on(srv.call(req)).unwrap(); assert_eq!(resp.status(), StatusCode::OK); match resp.response().body() { ResponseBody::Body(Body::Bytes(ref b)) => { diff --git a/src/test.rs b/src/test.rs index 89562c61a..ad40a0321 100644 --- a/src/test.rs +++ b/src/test.rs @@ -58,7 +58,7 @@ where /// This function panics on nested call. pub fn run_on(f: F) -> R where - F: Fn() -> R, + F: FnOnce() -> R, { RT.with(move |rt| rt.borrow_mut().block_on(lazy(|| Ok::<_, ()>(f())))) .unwrap() @@ -117,7 +117,9 @@ where S::InitError: std::fmt::Debug, { let cfg = ServerConfig::new("127.0.0.1:8080".parse().unwrap()); - block_on(app.into_new_service().new_service(&cfg)).unwrap() + let srv = app.into_new_service(); + let fut = run_on(move || srv.new_service(&cfg)); + block_on(fut).unwrap() } /// Calls service and waits for response future completion. @@ -146,7 +148,7 @@ where S: Service, Error = E>, E: std::fmt::Debug, { - block_on(app.call(req)).unwrap() + block_on(run_on(move || app.call(req))).unwrap() } /// Helper function that returns a response body of a TestRequest @@ -178,13 +180,15 @@ where S: Service, Error = Error>, B: MessageBody, { - block_on(app.call(req).and_then(|mut resp: ServiceResponse| { - resp.take_body() - .fold(BytesMut::new(), move |mut body, chunk| { - body.extend_from_slice(&chunk); - Ok::<_, Error>(body) - }) - .map(|body: BytesMut| body.freeze()) + block_on(run_on(move || { + app.call(req).and_then(|mut resp: ServiceResponse| { + resp.take_body() + .fold(BytesMut::new(), move |mut body, chunk| { + body.extend_from_slice(&chunk); + Ok::<_, Error>(body) + }) + .map(|body: BytesMut| body.freeze()) + }) })) .unwrap_or_else(|_| panic!("read_response failed at block_on unwrap")) } @@ -229,17 +233,19 @@ where B: MessageBody, T: DeserializeOwned, { - block_on(app.call(req).and_then(|mut resp: ServiceResponse| { - resp.take_body() - .fold(BytesMut::new(), move |mut body, chunk| { - body.extend_from_slice(&chunk); - Ok::<_, Error>(body) - }) - .and_then(|body: BytesMut| { - ok(serde_json::from_slice(&body).unwrap_or_else(|_| { - panic!("read_response_json failed during deserialization") - })) - }) + block_on(run_on(move || { + app.call(req).and_then(|mut resp: ServiceResponse| { + resp.take_body() + .fold(BytesMut::new(), move |mut body, chunk| { + body.extend_from_slice(&chunk); + Ok::<_, Error>(body) + }) + .and_then(|body: BytesMut| { + ok(serde_json::from_slice(&body).unwrap_or_else(|_| { + panic!("read_response_json failed during deserialization") + })) + }) + }) })) .unwrap_or_else(|_| panic!("read_response_json failed at block_on unwrap")) } @@ -460,23 +466,6 @@ impl TestRequest { req.set_route_data(Some(Rc::new(self.route_data))); (req, payload) } - - /// Runs the provided future, blocking the current thread until the future - /// completes. - /// - /// This function can be used to synchronously block the current thread - /// until the provided `future` has resolved either successfully or with an - /// error. The result of the future is then returned from this function - /// call. - /// - /// Note that this function is intended to be used only for testing purpose. - /// This function panics on nested call. - pub fn block_on(f: F) -> Result - where - F: Future, - { - block_on(f) - } } #[cfg(test)] From 85b598a614c6c29a010cf853f9fa44752171258c Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 17 Apr 2019 11:02:03 -0700 Subject: [PATCH 14/15] add cookie session test --- actix-session/src/cookie.rs | 65 +++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/actix-session/src/cookie.rs b/actix-session/src/cookie.rs index 634288b45..4f7614dc6 100644 --- a/actix-session/src/cookie.rs +++ b/actix-session/src/cookie.rs @@ -17,6 +17,7 @@ use std::collections::HashMap; use std::rc::Rc; +use std::time::Duration; use actix_service::{Service, Transform}; use actix_web::cookie::{Cookie, CookieJar, Key, SameSite}; @@ -27,7 +28,6 @@ use derive_more::{Display, From}; use futures::future::{ok, Future, FutureResult}; use futures::Poll; use serde_json::error::Error as JsonError; -use time::Duration; use crate::Session; @@ -98,7 +98,7 @@ impl CookieSessionInner { } if let Some(max_age) = self.max_age { - cookie.set_max_age(max_age); + cookie.set_max_age(time::Duration::from_std(max_age).unwrap()); } if let Some(same_site) = self.same_site { @@ -317,6 +317,7 @@ where mod tests { use super::*; use actix_web::{test, web, App}; + use bytes::Bytes; #[test] fn cookie_session() { @@ -338,6 +339,26 @@ mod tests { .is_some()); } + #[test] + fn private_cookie() { + let mut app = test::init_service( + App::new() + .wrap(CookieSession::private(&[0; 32]).secure(false)) + .service(web::resource("/").to(|ses: Session| { + let _ = ses.set("counter", 100); + "test" + })), + ); + + let request = test::TestRequest::get().to_request(); + let response = test::block_on(app.call(request)).unwrap(); + assert!(response + .response() + .cookies() + .find(|c| c.name() == "actix-session") + .is_some()); + } + #[test] fn cookie_session_extractor() { let mut app = test::init_service( @@ -357,4 +378,44 @@ mod tests { .find(|c| c.name() == "actix-session") .is_some()); } + + #[test] + fn basics() { + let mut app = test::init_service( + App::new() + .wrap( + CookieSession::signed(&[0; 32]) + .path("/test/") + .name("actix-test") + .domain("localhost") + .http_only(true) + .same_site(SameSite::Lax) + .max_age(Duration::from_secs(100)), + ) + .service(web::resource("/").to(|ses: Session| { + let _ = ses.set("counter", 100); + "test" + })) + .service(web::resource("/test/").to(|ses: Session| { + let val: usize = ses.get("counter").unwrap().unwrap(); + format!("counter: {}", val) + })), + ); + + let request = test::TestRequest::get().to_request(); + let response = test::block_on(app.call(request)).unwrap(); + let cookie = response + .response() + .cookies() + .find(|c| c.name() == "actix-test") + .unwrap() + .clone(); + assert_eq!(cookie.path().unwrap(), "/test/"); + + let request = test::TestRequest::with_uri("/test/") + .cookie(cookie) + .to_request(); + let body = test::read_response(&mut app, request); + assert_eq!(body, Bytes::from_static(b"counter: 100")); + } } From 163ca89cf4ccc010163e7a447d3bf54c2a49fc9e Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 17 Apr 2019 17:48:25 -0700 Subject: [PATCH 15/15] more tests --- actix-http/src/request.rs | 25 +++++++++++++++++++++++++ tests/test_server.rs | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/actix-http/src/request.rs b/actix-http/src/request.rs index 5ba07929a..e9252a829 100644 --- a/actix-http/src/request.rs +++ b/actix-http/src/request.rs @@ -178,3 +178,28 @@ impl

fmt::Debug for Request

{ Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + use http::HttpTryFrom; + + #[test] + fn test_basics() { + let msg = Message::new(); + let mut req = Request::from(msg); + req.headers_mut().insert( + header::CONTENT_TYPE, + header::HeaderValue::from_static("text/plain"), + ); + assert!(req.headers().contains_key(header::CONTENT_TYPE)); + + *req.uri_mut() = Uri::try_from("/index.html?q=1").unwrap(); + assert_eq!(req.uri().path(), "/index.html"); + assert_eq!(req.uri().query(), Some("q=1")); + + let s = format!("{:?}", req); + println!("T: {:?}", s); + assert!(s.contains("Request HTTP/1.1 GET:/index.html")); + } +} diff --git a/tests/test_server.rs b/tests/test_server.rs index 718aa7d4f..33c18b001 100644 --- a/tests/test_server.rs +++ b/tests/test_server.rs @@ -17,7 +17,7 @@ use futures::stream::once; use rand::{distributions::Alphanumeric, Rng}; use actix_web::middleware::{BodyEncoding, Compress}; -use actix_web::{http, test, web, App, HttpResponse, HttpServer}; +use actix_web::{dev, http, test, web, App, HttpResponse, HttpServer}; const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \ @@ -89,6 +89,39 @@ fn test_body_gzip() { assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); } +#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))] +#[test] +fn test_body_gzip2() { + let mut srv = TestServer::new(|| { + h1::H1Service::new( + App::new() + .wrap(Compress::new(ContentEncoding::Gzip)) + .service(web::resource("/").route(web::to(|| { + Response::Ok().body(STR).into_body::() + }))), + ) + }); + + let mut response = srv + .block_on( + srv.get("/") + .no_decompress() + .header(ACCEPT_ENCODING, "gzip") + .send(), + ) + .unwrap(); + assert!(response.status().is_success()); + + // read response + let bytes = srv.block_on(response.body()).unwrap(); + + // decode + let mut e = GzDecoder::new(&bytes[..]); + let mut dec = Vec::new(); + e.read_to_end(&mut dec).unwrap(); + assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref())); +} + #[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))] #[test] fn test_body_encoding_override() {