Moved certificate into request, so this is no longer a breaking change
This commit is contained in:
parent
3547143860
commit
eaee14d174
|
@ -13,7 +13,7 @@ async fn main() -> Result<()> {
|
||||||
let users = Arc::<RwLock::<HashMap<CertBytes, String>>>::default();
|
let users = Arc::<RwLock::<HashMap<CertBytes, String>>>::default();
|
||||||
|
|
||||||
Server::bind(("0.0.0.0", GEMINI_PORT))
|
Server::bind(("0.0.0.0", GEMINI_PORT))
|
||||||
.serve(move|req, cert| handle_request(users.clone(), req, cert))
|
.serve(move|req| handle_request(users.clone(), req))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,12 +24,12 @@ async fn main() -> Result<()> {
|
||||||
/// selecting a username. They'll then get a message confirming their account creation.
|
/// selecting a username. They'll then get a message confirming their account creation.
|
||||||
/// Any time this user visits the site in the future, they'll get a personalized welcome
|
/// Any time this user visits the site in the future, they'll get a personalized welcome
|
||||||
/// message.
|
/// message.
|
||||||
fn handle_request(users: Arc<RwLock<HashMap<CertBytes, String>>>, request: Request, cert: Option<Certificate>) -> BoxFuture<'static, Result<Response>> {
|
fn handle_request(users: Arc<RwLock<HashMap<CertBytes, String>>>, request: Request) -> BoxFuture<'static, Result<Response>> {
|
||||||
async move {
|
async move {
|
||||||
if let Some(Certificate(cert_bytes)) = cert {
|
if let Some(Certificate(cert_bytes)) = request.certificate() {
|
||||||
// The user provided a certificate
|
// The user provided a certificate
|
||||||
let users_read = users.read().await;
|
let users_read = users.read().await;
|
||||||
if let Some(user) = users_read.get(&cert_bytes) {
|
if let Some(user) = users_read.get(cert_bytes) {
|
||||||
// The user has already registered
|
// The user has already registered
|
||||||
Ok(
|
Ok(
|
||||||
Response::success(&gemini_mime()?)?
|
Response::success(&gemini_mime()?)?
|
||||||
|
@ -42,7 +42,7 @@ fn handle_request(users: Arc<RwLock<HashMap<CertBytes, String>>>, request: Reque
|
||||||
// The user provided some input (a username request)
|
// The user provided some input (a username request)
|
||||||
let username = query_part.as_str();
|
let username = query_part.as_str();
|
||||||
let mut users_write = users.write().await;
|
let mut users_write = users.write().await;
|
||||||
users_write.insert(cert_bytes, username.to_owned());
|
users_write.insert(cert_bytes.clone(), username.to_owned());
|
||||||
Ok(
|
Ok(
|
||||||
Response::success(&gemini_mime()?)?
|
Response::success(&gemini_mime()?)?
|
||||||
.with_body(format!(
|
.with_body(format!(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
use futures::{future::BoxFuture, FutureExt};
|
use futures::{future::BoxFuture, FutureExt};
|
||||||
use northstar::{Server, Request, Response, GEMINI_PORT, Certificate};
|
use northstar::{Server, Request, Response, GEMINI_PORT};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
@ -9,7 +9,7 @@ async fn main() -> Result<()> {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_request(request: Request, _cert: Option<Certificate>) -> BoxFuture<'static, Result<Response>> {
|
fn handle_request(request: Request) -> BoxFuture<'static, Result<Response>> {
|
||||||
async move {
|
async move {
|
||||||
let path = request.path_segments();
|
let path = request.path_segments();
|
||||||
let response = northstar::util::serve_dir("public", &path).await?;
|
let response = northstar::util::serve_dir("public", &path).await?;
|
||||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -26,7 +26,7 @@ pub use rustls::Certificate;
|
||||||
pub const REQUEST_URI_MAX_LEN: usize = 1024;
|
pub const REQUEST_URI_MAX_LEN: usize = 1024;
|
||||||
pub const GEMINI_PORT: u16 = 1965;
|
pub const GEMINI_PORT: u16 = 1965;
|
||||||
|
|
||||||
type Handler = Arc<dyn Fn(Request, Option<Certificate>) -> HandlerResponse + Send + Sync>;
|
type Handler = Arc<dyn Fn(Request) -> HandlerResponse + Send + Sync>;
|
||||||
type HandlerResponse = BoxFuture<'static, Result<Response>>;
|
type HandlerResponse = BoxFuture<'static, Result<Response>>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -58,7 +58,7 @@ impl Server {
|
||||||
let stream = self.tls_acceptor.accept(stream).await?;
|
let stream = self.tls_acceptor.accept(stream).await?;
|
||||||
let mut stream = BufStream::new(stream);
|
let mut stream = BufStream::new(stream);
|
||||||
|
|
||||||
let request = receive_request(&mut stream).await?;
|
let mut request = receive_request(&mut stream).await?;
|
||||||
debug!("Client requested: {}", request.uri());
|
debug!("Client requested: {}", request.uri());
|
||||||
|
|
||||||
// Identify the client certificate from the tls stream. This is the first
|
// Identify the client certificate from the tls stream. This is the first
|
||||||
|
@ -69,7 +69,9 @@ impl Server {
|
||||||
.get_peer_certificates()
|
.get_peer_certificates()
|
||||||
.and_then(|mut v| if v.is_empty() {None} else {Some(v.remove(0))});
|
.and_then(|mut v| if v.is_empty() {None} else {Some(v.remove(0))});
|
||||||
|
|
||||||
let handler = (self.handler)(request, client_cert);
|
request.set_cert(client_cert);
|
||||||
|
|
||||||
|
let handler = (self.handler)(request);
|
||||||
let handler = AssertUnwindSafe(handler);
|
let handler = AssertUnwindSafe(handler);
|
||||||
|
|
||||||
let response = handler.catch_unwind().await
|
let response = handler.catch_unwind().await
|
||||||
|
@ -98,7 +100,7 @@ impl<A: ToSocketAddrs> Builder<A> {
|
||||||
|
|
||||||
pub async fn serve<F>(self, handler: F) -> Result<()>
|
pub async fn serve<F>(self, handler: F) -> Result<()>
|
||||||
where
|
where
|
||||||
F: Fn(Request, Option<Certificate>) -> HandlerResponse + Send + Sync + 'static,
|
F: Fn(Request) -> HandlerResponse + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let config = tls_config()?;
|
let config = tls_config()?;
|
||||||
|
|
||||||
|
|
20
src/types.rs
20
src/types.rs
|
@ -4,14 +4,23 @@ use mime::Mime;
|
||||||
use percent_encoding::percent_decode_str;
|
use percent_encoding::percent_decode_str;
|
||||||
use tokio::{io::AsyncRead, fs::File};
|
use tokio::{io::AsyncRead, fs::File};
|
||||||
use uriparse::URIReference;
|
use uriparse::URIReference;
|
||||||
|
use rustls::Certificate;
|
||||||
|
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
uri: URIReference<'static>,
|
uri: URIReference<'static>,
|
||||||
input: Option<String>,
|
input: Option<String>,
|
||||||
|
certificate: Option<Certificate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
pub fn from_uri(mut uri: URIReference<'static>) -> Result<Self> {
|
pub fn from_uri(uri: URIReference<'static>) -> Result<Self> {
|
||||||
|
Self::with_certificate(uri, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_certificate(
|
||||||
|
mut uri: URIReference<'static>,
|
||||||
|
certificate: Option<Certificate>
|
||||||
|
) -> Result<Self> {
|
||||||
uri.normalize();
|
uri.normalize();
|
||||||
|
|
||||||
let input = match uri.query() {
|
let input = match uri.query() {
|
||||||
|
@ -27,6 +36,7 @@ impl Request {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
uri,
|
uri,
|
||||||
input,
|
input,
|
||||||
|
certificate,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +56,14 @@ impl Request {
|
||||||
pub fn input(&self) -> Option<&str> {
|
pub fn input(&self) -> Option<&str> {
|
||||||
self.input.as_deref()
|
self.input.as_deref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_cert(&mut self, cert: Option<Certificate>) {
|
||||||
|
self.certificate = cert;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn certificate(&self) -> Option<&Certificate> {
|
||||||
|
self.certificate.as_ref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Deref for Request {
|
impl ops::Deref for Request {
|
||||||
|
|
Loading…
Reference in a new issue