Skip to content

Commit fb0aa02

Browse files
authored
move and update server+tls examples (#190)
1 parent 681eeb4 commit fb0aa02

File tree

14 files changed

+241
-217
lines changed

14 files changed

+241
-217
lines changed

actix-server/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,4 @@ mio-uds = { version = "0.6.7" }
4141
bytes = "0.5"
4242
env_logger = "0.7"
4343
actix-testing = "1.0.0"
44+
tokio = { version = "0.2", features = ["io-util"] }

actix-server/examples/basic.rs

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//! Simple composite-service TCP echo server.
2+
//!
3+
//! Using the following command:
4+
//!
5+
//! ```sh
6+
//! nc 127.0.0.1 8080
7+
//! ```
8+
//!
9+
//! Start typing. When you press enter the typed line will be echoed back. The server will log
10+
//! the length of each line it echos and the total size of data sent when the connection is closed.
11+
12+
use std::sync::{
13+
atomic::{AtomicUsize, Ordering},
14+
Arc,
15+
};
16+
use std::{env, io};
17+
18+
use actix_rt::net::TcpStream;
19+
use actix_server::Server;
20+
use actix_service::pipeline_factory;
21+
use bytes::BytesMut;
22+
use futures_util::future::ok;
23+
use log::{error, info};
24+
use tokio::io::{AsyncReadExt, AsyncWriteExt};
25+
26+
#[actix_rt::main]
27+
async fn main() -> io::Result<()> {
28+
env::set_var("RUST_LOG", "actix=trace,basic=trace");
29+
env_logger::init();
30+
31+
let count = Arc::new(AtomicUsize::new(0));
32+
33+
let addr = ("127.0.0.1", 8080);
34+
info!("starting server on port: {}", &addr.0);
35+
36+
// Bind socket address and start worker(s). By default, the server uses the number of available
37+
// logical CPU cores as the worker count. For this reason, the closure passed to bind needs
38+
// to return a service *factory*; so it can be created once per worker.
39+
Server::build()
40+
.bind("echo", addr, move || {
41+
let count = Arc::clone(&count);
42+
let num2 = Arc::clone(&count);
43+
44+
pipeline_factory(move |mut stream: TcpStream| {
45+
let count = Arc::clone(&count);
46+
47+
async move {
48+
let num = count.fetch_add(1, Ordering::SeqCst);
49+
let num = num + 1;
50+
51+
let mut size = 0;
52+
let mut buf = BytesMut::new();
53+
54+
loop {
55+
match stream.read_buf(&mut buf).await {
56+
// end of stream; bail from loop
57+
Ok(0) => break,
58+
59+
// more bytes to process
60+
Ok(bytes_read) => {
61+
info!("[{}] read {} bytes", num, bytes_read);
62+
stream.write_all(&buf[size..]).await.unwrap();
63+
size += bytes_read;
64+
}
65+
66+
// stream error; bail from loop with error
67+
Err(err) => {
68+
error!("Stream Error: {:?}", err);
69+
return Err(());
70+
}
71+
}
72+
}
73+
74+
// send data down service pipeline
75+
Ok((buf.freeze(), size))
76+
}
77+
})
78+
.map_err(|err| error!("Service Error: {:?}", err))
79+
.and_then(move |(_, size)| {
80+
let num = num2.load(Ordering::SeqCst);
81+
info!("[{}] total bytes read: {}", num, size);
82+
ok(size)
83+
})
84+
})?
85+
.workers(1)
86+
.run()
87+
.await
88+
}

actix-server/src/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
//! General purpose tcp server
2-
#![deny(rust_2018_idioms, warnings)]
3-
#![allow(clippy::type_complexity)]
1+
//! General purpose TCP server.
2+
3+
#![deny(rust_2018_idioms)]
44

55
mod accept;
66
mod builder;
@@ -19,7 +19,7 @@ pub use self::service::ServiceFactory;
1919
#[doc(hidden)]
2020
pub use self::socket::FromStream;
2121

22-
/// Socket id token
22+
/// Socket ID token
2323
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2424
pub(crate) struct Token(usize);
2525

actix-server/src/service.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ use crate::socket::{FromStream, StdStream};
1717
pub(crate) enum ServerMessage {
1818
/// New stream
1919
Connect(StdStream),
20-
/// Gracefull shutdown
20+
21+
/// Gracefully shutdown
2122
Shutdown(Duration),
23+
2224
/// Force shutdown
2325
ForceShutdown,
2426
}

actix-server/src/worker.rs

+1
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ enum WorkerState {
303303
Restarting(
304304
usize,
305305
Token,
306+
#[allow(clippy::type_complexity)]
306307
Pin<Box<dyn Future<Output = Result<Vec<(Token, BoxedServerService)>, ()>>>>,
307308
),
308309
Shutdown(

actix-service/src/pipeline.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::map_init_err::MapInitErr;
99
use crate::then::{ThenService, ThenServiceFactory};
1010
use crate::{IntoService, IntoServiceFactory, Service, ServiceFactory};
1111

12-
/// Contruct new pipeline with one service in pipeline chain.
12+
/// Construct new pipeline with one service in pipeline chain.
1313
pub fn pipeline<F, T>(service: F) -> Pipeline<T>
1414
where
1515
F: IntoService<T>,
@@ -20,7 +20,7 @@ where
2020
}
2121
}
2222

23-
/// Contruct new pipeline factory with one service factory.
23+
/// Construct new pipeline factory with one service factory.
2424
pub fn pipeline_factory<T, F>(factory: F) -> PipelineFactory<T>
2525
where
2626
T: ServiceFactory,

actix-tls/Cargo.toml

+8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ features = ["openssl", "rustls", "nativetls"]
1818
name = "actix_tls"
1919
path = "src/lib.rs"
2020

21+
[[example]]
22+
name = "basic"
23+
required-features = ["rustls"]
24+
2125
[features]
2226
default = []
2327

@@ -53,4 +57,8 @@ tokio-tls = { version = "0.3", optional = true }
5357

5458
[dev-dependencies]
5559
bytes = "0.5"
60+
log = "0.4"
61+
env_logger = "0.7"
5662
actix-testing = "1.0.0"
63+
actix-server = "1"
64+
actix-rt = "1"

actix-tls/examples/basic.rs

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//! TLS Acceptor Server
2+
//!
3+
//! Using either HTTPie (`http`) or cURL:
4+
//!
5+
//! This commands will produce errors in the server log:
6+
//! ```sh
7+
//! curl 127.0.0.1:8443
8+
//! http 127.0.0.1:8443
9+
//! ```
10+
//!
11+
//! These commands will show "empty reply" on the client but will debug print the TLS stream info
12+
//! in the server log, indicating a successful TLS handshake:
13+
//! ```sh
14+
//! curl -k https://127.0.0.1:8443
15+
//! http --verify=false https://127.0.0.1:8443
16+
//! ```
17+
18+
use std::{
19+
env,
20+
fs::File,
21+
io::{self, BufReader},
22+
sync::{
23+
atomic::{AtomicUsize, Ordering},
24+
Arc,
25+
},
26+
};
27+
28+
use actix_server::Server;
29+
use actix_service::pipeline_factory;
30+
use actix_tls::rustls::Acceptor as RustlsAcceptor;
31+
use futures_util::future::ok;
32+
use log::info;
33+
use rust_tls::{
34+
internal::pemfile::certs, internal::pemfile::rsa_private_keys, NoClientAuth, ServerConfig,
35+
};
36+
37+
#[derive(Debug)]
38+
struct ServiceState {
39+
num: Arc<AtomicUsize>,
40+
}
41+
42+
#[actix_rt::main]
43+
async fn main() -> io::Result<()> {
44+
env::set_var("RUST_LOG", "actix=trace,basic=trace");
45+
env_logger::init();
46+
47+
let mut tls_config = ServerConfig::new(NoClientAuth::new());
48+
49+
// Load TLS key and cert files
50+
let cert_file = &mut BufReader::new(File::open("./examples/cert.pem").unwrap());
51+
let key_file = &mut BufReader::new(File::open("./examples/key.pem").unwrap());
52+
53+
let cert_chain = certs(cert_file).unwrap();
54+
let mut keys = rsa_private_keys(key_file).unwrap();
55+
tls_config
56+
.set_single_cert(cert_chain, keys.remove(0))
57+
.unwrap();
58+
59+
let tls_acceptor = RustlsAcceptor::new(tls_config);
60+
61+
let count = Arc::new(AtomicUsize::new(0));
62+
63+
let addr = ("127.0.0.1", 8443);
64+
info!("starting server on port: {}", &addr.0);
65+
66+
Server::build()
67+
.bind("tls-example", addr, move || {
68+
let count = Arc::clone(&count);
69+
70+
// Set up TLS service factory
71+
pipeline_factory(tls_acceptor.clone())
72+
.map_err(|err| println!("Rustls error: {:?}", err))
73+
.and_then(move |stream| {
74+
let num = count.fetch_add(1, Ordering::Relaxed);
75+
info!("[{}] Got TLS connection: {:?}", num, stream);
76+
ok(())
77+
})
78+
})?
79+
.workers(1)
80+
.run()
81+
.await
82+
}

actix-tls/examples/cert.pem

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIENjCCAp6gAwIBAgIRANp+D9pBErdacw6KjrwJ+4swDQYJKoZIhvcNAQELBQAw
3+
bTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSEwHwYDVQQLDBhyb2JA
4+
c29tYnJhLng1Mi5kZXYgKFJvYikxKDAmBgNVBAMMH21rY2VydCByb2JAc29tYnJh
5+
Lng1Mi5kZXYgKFJvYikwHhcNMTkwNjAxMDAwMDAwWhcNMzAwOTEzMDIzNDI0WjBM
6+
MScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxITAfBgNV
7+
BAsMGHJvYkBzb21icmEueDUyLmRldiAoUm9iKTCCASIwDQYJKoZIhvcNAQEBBQAD
8+
ggEPADCCAQoCggEBALYAn8dsQUDTp8SptAtkiAySvQYLpAOct3/OjBn+dSYfbQcp
9+
Ph9w/Zo83Msl7Fb1DBvADHFtyBpESATZ2chS5fwCAwUFTlKrzMk3qauEoJ3cCQa8
10+
ccqhTMLeT38jRlhXrMHWBfz0ipqy+yTLWeM32LX8s0jPbbsZ3gVJ/Ls4qm0CTaqb
11+
zRdcQ7GTVKYet5DR7ZvwvAaLtWk/iiHKwnOveuF27HNlxj0Rwd/lhJ/t9x8xJwyR
12+
MTdm852KQadI8xOSbWNK4j9419yzKjUEMKgn78wT/7DQfeKKCAreHa4MaEw4+koD
13+
2Bqb+V4fI6T84VvXkNG3CjSpmIiYGlIE1LVgBL8CAwEAAaNyMHAwDgYDVR0PAQH/
14+
BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHwYDVR0j
15+
BBgwFoAUto/ox0MqZShmQpViV/gjfJKrMDkwGgYDVR0RBBMwEYIJbG9jYWxob3N0
16+
hwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBgQBUCMzqTY0sg+61gh8gKS5TCL6qs0R1
17+
xys/EFFaD5JYUsfM/HyhHd0jq+x5Pd3mB2Jvhoq9xhjMwP11H8Uw5lLBHA8USdF9
18+
EiLW1GvT3/gLfMqb0lPk0RMRBeX8c0QbDtqdiUCE7S6zJbZ5gjFeRuFNjdcGA1Ss
19+
8CPPts2mns5cwah6H7T/BFzj5aR9Qe14vo1Rpr5gD5CpHvk1t16q7YsczQfVMvt3
20+
Ydk6p0rwA8Z5okQK7y3qKPZI+//ygWL6ZBjVjl1/Al8vybG2UYjYgfMBwaVvMiDJ
21+
j/vCdVmlvGb+MZlZID/p2veaNeEKgi1A1EOj3sNuQYXXFfSD9mdamX7JIfGi/U7v
22+
ivvUjJUbzGrUngldt5iCKqcCQum7nlzu9sT1Tm2t/n4tz/btrI+Wimg8riSzM+Nk
23+
dfuvv4NbWe6Th5460HH8mMvfPZSB8dCoxwm98tuqcMXLkR1RJX5Z8LYAaPTsUs/h
24+
HxQCY4EaY7feZ/qFal9FGwvpzVr3/XjgSCU=
25+
-----END CERTIFICATE-----

actix-tls/examples/key.pem

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEpAIBAAKCAQEAtgCfx2xBQNOnxKm0C2SIDJK9BgukA5y3f86MGf51Jh9tByk+
3+
H3D9mjzcyyXsVvUMG8AMcW3IGkRIBNnZyFLl/AIDBQVOUqvMyTepq4SgndwJBrxx
4+
yqFMwt5PfyNGWFeswdYF/PSKmrL7JMtZ4zfYtfyzSM9tuxneBUn8uziqbQJNqpvN
5+
F1xDsZNUph63kNHtm/C8Bou1aT+KIcrCc6964Xbsc2XGPRHB3+WEn+33HzEnDJEx
6+
N2bznYpBp0jzE5JtY0riP3jX3LMqNQQwqCfvzBP/sNB94ooICt4drgxoTDj6SgPY
7+
Gpv5Xh8jpPzhW9eQ0bcKNKmYiJgaUgTUtWAEvwIDAQABAoIBADC0Zg21+Jhii6jj
8+
SR0rYAUNV6xAfTnCPJDlMzTZlXwIOOMLtGYxlIwr8WIj2eVDWmQqtqm8GSp+T0+N
9+
BOzI0mboGurDCryw4PKQBMWzjk/wTDITR9hT5fjYCSoaxH5rp/2PSrbwsg7ICtFD
10+
4eAeV84Lu+amK9VADNwZepqXhXP6EDOY5yovkwzOQNDM/qVzHSe9EoFP74M/oWnY
11+
ohIuWdZzwAZuTA5SUjPygiVzs/vhsrSE9crMIzr5VgKBi+C+ALkrL7Lc4GlRPI4r
12+
6VsbIxZHa7who+FhjZ0cVfdXHH47QDdf10X5bEXsaFBvGGCLtkQ3XEpov6GOlaH+
13+
aY7fzPECgYEA4LGloaMC9J27uyPxHkQwEehexmJdIu0vNUefv5yiO9PbvrjvYnh7
14+
JxRVgv1fy2bRMOvg19TujCYRZdkrLDqSDsfFfEiThvlFBRZfKKIHmWdyfvIe9Jp9
15+
rqdxhWAco7FoM+W6c8c4iR4xs8/GA60CVcAiTLqgPWWzn12fesiULi0CgYEAz1xD
16+
OulJyfpHVGQ6ZM1wR0SZ9H9GS3BenpL2ue5uBfe3hM+JIAAM61Y48wJuCWT5EvfL
17+
FgnH3oCo7SYGcgGkERS8H7k67DJCLlqDo/3FC7lX/irz+ya/FoZmKBagvjEUWhpe
18+
Bb2dRIbqsG0lsCzU9MVrgtvodD0MBTyt0RM5fhsCgYEAhgYQiLhGBAituLN4mBgO
19+
IDBdj7GOYk3dkcc2J0HTlyIIeduvlinNM4Myel6NrDKY5rhbtgGhhGEUkY6W7NvG
20+
0SAh0L8tmB3JKH6upfr3023b4pKjGj2oZ+wij27DxnQEdqg5reOP+mHTPbDaKMki
21+
kml3TBMpj1XBbXaXsNJBaMUCgYEAnnNzEC4563QrU2pvUJ3HgT4Dotgqv/Sy6NuG
22+
W1e9jSPYgU0RDHndZWtygwdFTDpzNbJR5po8t2J7MxQOcsmcNE0y387sHpbdCYyy
23+
8Po2uxm7CoaJ/02BUVYL8/Aujob0dVGWrS5SYY3zAjO1S+VGKXA+EjW2cDRB3jKa
24+
45ucICcCgYBdMxB5Oj6GpdewWWaBss9dwHtDaD4oVGYIBbIc2qdyCYixWdW9NccV
25+
fRJs0ulGrpg9OtyWbwZASu2jz55+s3hi4rnrcaXKiIh9Rs25v1irF6Dmduvo7CaN
26+
Mf7zBg7LUttmqN6D3npIAxmBULl8KRfjnt6U2tJolF5X0qQ1uqnnTA==
27+
-----END RSA PRIVATE KEY-----

examples/basic.rs

-77
This file was deleted.

0 commit comments

Comments
 (0)