1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-12-21 07:36:43 +00:00

Unix domain sockets (HttpServer::bind_uds) #92

This commit is contained in:
Nikolay Kim 2019-07-18 17:24:12 +06:00
parent d03296237e
commit fbdda8acb1
9 changed files with 108 additions and 10 deletions

View file

@ -1,9 +1,11 @@
# Changes # Changes
## [1.0.5] - ? ## [1.0.5] - 2019-07-xx
### Added ### Added
* Unix domain sockets (HttpServer::bind_uds) #92
* Actix now logs errors resulting in "internal server error" responses always, with the `error` * Actix now logs errors resulting in "internal server error" responses always, with the `error`
logging level logging level
@ -11,6 +13,7 @@
* Restored logging of errors through the `Logger` middleware * Restored logging of errors through the `Logger` middleware
## [1.0.4] - 2019-07-17 ## [1.0.4] - 2019-07-17
### Added ### Added

View file

@ -16,7 +16,7 @@ exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
edition = "2018" edition = "2018"
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["ssl", "brotli", "flate2-zlib", "secure-cookies", "client", "rust-tls"] features = ["ssl", "brotli", "flate2-zlib", "secure-cookies", "client", "rust-tls", "uds"]
[badges] [badges]
travis-ci = { repository = "actix/actix-web", branch = "master" } travis-ci = { repository = "actix/actix-web", branch = "master" }
@ -68,6 +68,9 @@ ssl = ["openssl", "actix-server/ssl", "awc/ssl"]
# rustls # rustls
rust-tls = ["rustls", "actix-server/rust-tls"] rust-tls = ["rustls", "actix-server/rust-tls"]
# unix domain sockets support
uds = ["actix-server/uds"]
[dependencies] [dependencies]
actix-codec = "0.1.2" actix-codec = "0.1.2"
actix-service = "0.4.1" actix-service = "0.4.1"
@ -76,8 +79,8 @@ actix-router = "0.1.5"
actix-rt = "0.2.4" actix-rt = "0.2.4"
actix-web-codegen = "0.1.2" actix-web-codegen = "0.1.2"
actix-http = "0.2.6" actix-http = "0.2.6"
actix-server = "0.5.1" actix-server = "0.6.0"
actix-server-config = "0.1.1" actix-server-config = "0.1.2"
actix-threadpool = "0.1.1" actix-threadpool = "0.1.1"
awc = { version = "0.2.1", optional = true } awc = { version = "0.2.1", optional = true }

View file

@ -286,7 +286,10 @@ impl InnerMultipart {
} }
// read boundary // read boundary
InnerState::Boundary => { InnerState::Boundary => {
match InnerMultipart::read_boundary(&mut *payload, &self.boundary)? { match InnerMultipart::read_boundary(
&mut *payload,
&self.boundary,
)? {
None => return Ok(Async::NotReady), None => return Ok(Async::NotReady),
Some(eof) => { Some(eof) => {
if eof { if eof {
@ -411,7 +414,8 @@ impl Stream for Field {
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
if self.safety.current() { if self.safety.current() {
let mut inner = self.inner.borrow_mut(); let mut inner = self.inner.borrow_mut();
if let Some(mut payload) = inner.payload.as_ref().unwrap().get_mut(&self.safety) if let Some(mut payload) =
inner.payload.as_ref().unwrap().get_mut(&self.safety)
{ {
payload.poll_stream()?; payload.poll_stream()?;
} }
@ -582,7 +586,8 @@ impl InnerField {
return Ok(Async::Ready(None)); return Ok(Async::Ready(None));
} }
let result = if let Some(mut payload) = self.payload.as_ref().unwrap().get_mut(s) { let result = if let Some(mut payload) = self.payload.as_ref().unwrap().get_mut(s)
{
if !self.eof { if !self.eof {
let res = if let Some(ref mut len) = self.length { let res = if let Some(ref mut len) = self.length {
InnerField::read_len(&mut *payload, len)? InnerField::read_len(&mut *payload, len)?

49
examples/uds.rs Normal file
View file

@ -0,0 +1,49 @@
use futures::IntoFuture;
use actix_web::{
get, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer,
};
#[get("/resource1/{name}/index.html")]
fn index(req: HttpRequest, name: web::Path<String>) -> String {
println!("REQ: {:?}", req);
format!("Hello: {}!\r\n", name)
}
fn index_async(req: HttpRequest) -> impl IntoFuture<Item = &'static str, Error = Error> {
println!("REQ: {:?}", req);
Ok("Hello world!\r\n")
}
#[get("/")]
fn no_params() -> &'static str {
"Hello world!\r\n"
}
fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info");
env_logger::init();
HttpServer::new(|| {
App::new()
.wrap(middleware::DefaultHeaders::new().header("X-Version", "0.2"))
.wrap(middleware::Compress::default())
.wrap(middleware::Logger::default())
.service(index)
.service(no_params)
.service(
web::resource("/resource2/index.html")
.wrap(
middleware::DefaultHeaders::new().header("X-Version-R2", "0.3"),
)
.default_service(
web::route().to(|| HttpResponse::MethodNotAllowed()),
)
.route(web::get().to_async(index_async)),
)
.service(web::resource("/test1.html").to(|| "Test\r\n"))
})
.bind_uds("/Users/fafhrd91/uds-test")?
.workers(1)
.run()
}

View file

@ -78,6 +78,7 @@
//! `c` compiler (default enabled) //! `c` compiler (default enabled)
//! * `flate2-rust` - experimental rust based implementation for //! * `flate2-rust` - experimental rust based implementation for
//! `gzip`, `deflate` compression. //! `gzip`, `deflate` compression.
//! * `uds` - Unix domain support, enables `HttpServer::bind_uds()` method.
//! //!
#![allow(clippy::type_complexity, clippy::new_without_default)] #![allow(clippy::type_complexity, clippy::new_without_default)]

View file

@ -434,6 +434,38 @@ where
} }
Ok(self) Ok(self)
} }
#[cfg(feature = "uds")]
/// Start listening for incoming unix domain connections.
///
/// This method is available with `uds` feature.
pub fn bind_uds<A>(mut self, addr: A) -> io::Result<Self>
where
A: AsRef<std::path::Path>,
{
let cfg = self.config.clone();
let factory = self.factory.clone();
self.sockets.push(Socket {
scheme: "http",
addr: net::SocketAddr::new(
net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)),
8080,
),
});
self.builder = self.builder.bind_uds(
format!("actix-web-service-{:?}", addr.as_ref()),
addr,
move || {
let c = cfg.lock();
HttpService::build()
.keep_alive(c.keep_alive)
.client_timeout(c.client_timeout)
.finish(factory())
},
)?;
Ok(self)
}
} }
impl<F, I, S, B> HttpServer<F, I, S, B> impl<F, I, S, B> HttpServer<F, I, S, B>

View file

@ -1,5 +1,9 @@
# Changes # Changes
## [0.2.4] - 2019-07-18
* Update actix-server to 0.6
## [0.2.3] - 2019-07-16 ## [0.2.3] - 2019-07-16
* Add `delete`, `options`, `patch` methods to `TestServerRunner` * Add `delete`, `options`, `patch` methods to `TestServerRunner`

View file

@ -1,6 +1,6 @@
[package] [package]
name = "actix-http-test" name = "actix-http-test"
version = "0.2.3" version = "0.2.4"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"] authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "Actix http test server" description = "Actix http test server"
readme = "README.md" readme = "README.md"
@ -33,7 +33,7 @@ ssl = ["openssl", "actix-server/ssl", "awc/ssl"]
actix-codec = "0.1.2" actix-codec = "0.1.2"
actix-rt = "0.2.2" actix-rt = "0.2.2"
actix-service = "0.4.1" actix-service = "0.4.1"
actix-server = "0.5.1" actix-server = "0.6.0"
actix-utils = "0.4.1" actix-utils = "0.4.1"
awc = "0.2.2" awc = "0.2.2"

View file

@ -12,6 +12,7 @@ use futures::future::lazy;
use futures::{Future, IntoFuture, Stream}; use futures::{Future, IntoFuture, Stream};
use http::Method; use http::Method;
use net2::TcpBuilder; use net2::TcpBuilder;
use tokio_tcp::TcpStream;
thread_local! { thread_local! {
static RT: RefCell<Inner> = { static RT: RefCell<Inner> = {
@ -109,7 +110,7 @@ pub struct TestServerRuntime {
impl TestServer { impl TestServer {
#[allow(clippy::new_ret_no_self)] #[allow(clippy::new_ret_no_self)]
/// Start new test server with application factory /// Start new test server with application factory
pub fn new<F: StreamServiceFactory>(factory: F) -> TestServerRuntime { pub fn new<F: StreamServiceFactory<TcpStream>>(factory: F) -> TestServerRuntime {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
// run server in separate thread // run server in separate thread