Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

return error instead of panicking when creating a new server #4

Merged
merged 4 commits into from
Aug 20, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
return error instead of panicking
Signed-off-by: Dan Bond <danbond@protonmail.com>
  • Loading branch information
loshz committed Aug 16, 2022
commit 9b6ccf7497c1ce62435222d9e452efe5109e94e2
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "metrics_server"
version = "0.8.1"
version = "0.9.0"
authors = ["Dan Bond <danbond@protonmail.com>"]
edition = "2021"
rust-version = "1.58"
Expand All @@ -18,8 +18,8 @@ include = ["src/**/*", "tests", "examples", "Cargo.toml", "LICENSE", "README.md"
doctest = false

[dependencies]
tiny_http = "0.11"
log = "0.4"
tiny_http = "0.11"

[dev-dependencies]
prometheus-client = "0.16"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ This crate provides a thread safe, minimalstic HTTP/S server used to buffer metr
Include the lib in your `Cargo.toml` dependencies:
```toml
[dependencies]
metrics_server = "0.8"
metrics_server = "0.9"
```

To enable TLS support, pass the optional feature flag:
```toml
[dependencies]
metrics_server = { version = "0.8", features = ["tls"] }
metrics_server = { version = "0.9", features = ["tls"] }
```

### HTTP
Expand Down
29 changes: 29 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::error::Error;
use std::fmt;

/// The error type for MetricsServer operations.
#[derive(Debug)]
pub struct ServerError {
details: String,
}

impl ServerError {
/// Creates a new ServerError with additional details.
pub fn new(msg: &str) -> ServerError {
ServerError {
details: msg.to_string(),
}
}
}

impl fmt::Display for ServerError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.details)
}
}

impl Error for ServerError {
fn description(&self) -> &str {
&self.details
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
//! let bytes = server.update(Vec::from([1, 2, 3, 4]));
//! assert_eq!(4, bytes);
//! ```
mod errors;
mod server;

pub use errors::ServerError;
pub use server::MetricsServer;
34 changes: 24 additions & 10 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;

use crate::errors::ServerError;

use log::{debug, error};
use tiny_http::{Method, Response, Server};

Expand All @@ -20,11 +22,11 @@ struct MetricsServerShared {

impl MetricsServer {
/// Creates an empty `MetricsServer` with a configured HTTP/S server.
///
/// # Panics
///
/// Panics if given an invalid address or incorrect TLS credentials.
pub fn new<A>(addr: A, certificate: Option<Vec<u8>>, private_key: Option<Vec<u8>>) -> Self
pub fn new<A>(
addr: A,
certificate: Option<Vec<u8>>,
private_key: Option<Vec<u8>>,
) -> Result<Self, ServerError>
where
A: ToSocketAddrs,
{
Expand All @@ -42,17 +44,27 @@ impl MetricsServer {
_ => tiny_http::ServerConfig { addr, ssl: None },
};

// Attempt to create a new server.
let server = match Server::new(config) {
Ok(s) => s,
Err(err) => {
return Err(ServerError::new(
format!("error creating metrics server: {}", err).as_str(),
));
}
};

// Create an Arc of the shared data.
let shared = Arc::new(MetricsServerShared {
data: Mutex::new(Vec::new()),
server: Server::new(config).unwrap(),
server,
stop: AtomicBool::new(false),
});

MetricsServer {
Ok(MetricsServer {
shared,
thread: None,
}
})
}

/// Shortcut for creating an empty `MetricsServer` and starting a HTTP server on a new thread at the given address.
Expand All @@ -66,7 +78,7 @@ impl MetricsServer {
where
A: ToSocketAddrs,
{
MetricsServer::new(addr, None, None).serve()
MetricsServer::new(addr, None, None).unwrap().serve()
}

/// Shortcut for creating an empty `MetricsServer` and starting a HTTPS server on a new thread at the given address.
Expand All @@ -83,7 +95,9 @@ impl MetricsServer {
where
A: ToSocketAddrs,
{
MetricsServer::new(addr, Some(certificate), Some(private_key)).serve()
MetricsServer::new(addr, Some(certificate), Some(private_key))
.unwrap()
.serve()
}

/// Safely updates the data in a `MetricsServer` and returns the number of bytes written.
Expand Down
43 changes: 30 additions & 13 deletions tests/server.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use metrics_server::MetricsServer;

#[test]
#[should_panic]
fn test_new_server_invalid_address() {
let _ = MetricsServer::new("invalid:99999999", None, None);
}
Expand All @@ -12,30 +11,47 @@ fn test_new_http_server() {
}

#[test]
#[should_panic]
#[cfg(feature = "tls")]
fn test_new_server_invalid_cert() {
fn test_new_server_invalid_certificate() {
// Load TLS config.
let cert = Vec::new();
let cert = "-----BEGIN CERTIFICATE-----
invaid certificate
-----END CERTIFICATE-----"
.as_bytes()
.to_vec();
let key = include_bytes!("./certs/private_key.pem").to_vec();

let _ = MetricsServer::new("localhost:8441", Some(cert), Some(key));
let server = MetricsServer::new("localhost:8441", Some(cert), Some(key));
assert!(server.is_err());

if let Err(error) = server {
assert!(error.to_string().contains("error creating metrics server"))
}
}

#[test]
#[should_panic]
#[cfg(feature = "tls")]
fn test_new_server_invalid_key() {
fn test_new_server_invalid_private_key() {
// Load TLS config.
let cert = include_bytes!("./certs/certificate.pem").to_vec();
let key = Vec::new();
let key = "-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----"
.as_bytes()
.to_vec();

let _ = MetricsServer::new("localhost:8442", Some(cert), Some(key));
let server = MetricsServer::new("localhost:8442", Some(cert), Some(key));
assert!(server.is_err());

if let Err(error) = server {
assert!(error.to_string().contains("error creating metrics server"))
}
}

#[test]
fn test_new_server_already_running() {
let srv = MetricsServer::new("localhost:8002", None, None).serve();
let srv = MetricsServer::new("localhost:8002", None, None)
.unwrap()
.serve();

// Attempt to start an already running server should be ok
// as we will return the pre-existing thread.
Expand All @@ -48,7 +64,8 @@ fn test_new_https_server() {
let cert = include_bytes!("./certs/certificate.pem").to_vec();
let key = include_bytes!("./certs/private_key.pem").to_vec();

let _ = MetricsServer::new("localhost:8443", Some(cert), Some(key));
let server = MetricsServer::new("localhost:8443", Some(cert), Some(key));
assert!(server.is_ok());
}

#[test]
Expand Down Expand Up @@ -102,7 +119,7 @@ fn test_https_server_invalid_address() {
#[test]
#[should_panic]
#[cfg(feature = "tls")]
fn test_https_server_invalid_cert() {
fn test_https_server_invalid_certificate() {
// Load TLS config.
let cert = Vec::new();
let key = include_bytes!("./certs/private_key.pem").to_vec();
Expand All @@ -113,7 +130,7 @@ fn test_https_server_invalid_cert() {
#[test]
#[should_panic]
#[cfg(feature = "tls")]
fn test_https_server_invalid_key() {
fn test_https_server_invalid_private_key() {
// Load TLS config.
let cert = include_bytes!("./certs/certificate.pem").to_vec();
let key = Vec::new();
Expand Down