Use App::configure to set up actix

This avoids the need for the messy cache-control-header macro.
Otherwise, it has no effect.
This commit is contained in:
Dustin J. Mitchell 2021-10-09 17:53:36 -04:00
parent f109056340
commit aaac1c3356
7 changed files with 63 additions and 40 deletions

View file

@ -7,7 +7,7 @@ use taskchampion_sync_server::{storage::InMemoryStorage, Server};
async fn cross_sync() -> anyhow::Result<()> { async fn cross_sync() -> anyhow::Result<()> {
let server = Server::new(Box::new(InMemoryStorage::new())); let server = Server::new(Box::new(InMemoryStorage::new()));
let httpserver = let httpserver =
HttpServer::new(move || App::new().service(server.service())).bind("0.0.0.0:0")?; HttpServer::new(move || App::new().configure(|sc| server.config(sc))).bind("0.0.0.0:0")?;
// bind was to :0, so the kernel will have selected an unused port // bind was to :0, so the kernel will have selected an unused port
let port = httpserver.addrs()[0].port(); let port = httpserver.addrs()[0].port();

View file

@ -85,7 +85,8 @@ mod test {
} }
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = format!("/v1/client/add-snapshot/{}", version_id); let uri = format!("/v1/client/add-snapshot/{}", version_id);
let req = test::TestRequest::post() let req = test::TestRequest::post()
@ -126,7 +127,8 @@ mod test {
} }
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
// add a snapshot for a nonexistent version // add a snapshot for a nonexistent version
let uri = format!("/v1/client/add-snapshot/{}", version_id); let uri = format!("/v1/client/add-snapshot/{}", version_id);
@ -155,7 +157,8 @@ mod test {
let version_id = Uuid::new_v4(); let version_id = Uuid::new_v4();
let storage: Box<dyn Storage> = Box::new(InMemoryStorage::new()); let storage: Box<dyn Storage> = Box::new(InMemoryStorage::new());
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = format!("/v1/client/add-snapshot/{}", version_id); let uri = format!("/v1/client/add-snapshot/{}", version_id);
let req = test::TestRequest::post() let req = test::TestRequest::post()
@ -174,7 +177,8 @@ mod test {
let version_id = Uuid::new_v4(); let version_id = Uuid::new_v4();
let storage: Box<dyn Storage> = Box::new(InMemoryStorage::new()); let storage: Box<dyn Storage> = Box::new(InMemoryStorage::new());
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = format!("/v1/client/add-snapshot/{}", version_id); let uri = format!("/v1/client/add-snapshot/{}", version_id);
let req = test::TestRequest::post() let req = test::TestRequest::post()

View file

@ -115,7 +115,8 @@ mod test {
} }
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = format!("/v1/client/add-version/{}", parent_version_id); let uri = format!("/v1/client/add-version/{}", parent_version_id);
let req = test::TestRequest::post() let req = test::TestRequest::post()
@ -156,7 +157,8 @@ mod test {
} }
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = format!("/v1/client/add-version/{}", parent_version_id); let uri = format!("/v1/client/add-version/{}", parent_version_id);
let req = test::TestRequest::post() let req = test::TestRequest::post()
@ -183,7 +185,8 @@ mod test {
let parent_version_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4();
let storage: Box<dyn Storage> = Box::new(InMemoryStorage::new()); let storage: Box<dyn Storage> = Box::new(InMemoryStorage::new());
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = format!("/v1/client/add-version/{}", parent_version_id); let uri = format!("/v1/client/add-version/{}", parent_version_id);
let req = test::TestRequest::post() let req = test::TestRequest::post()
@ -202,7 +205,8 @@ mod test {
let parent_version_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4();
let storage: Box<dyn Storage> = Box::new(InMemoryStorage::new()); let storage: Box<dyn Storage> = Box::new(InMemoryStorage::new());
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = format!("/v1/client/add-version/{}", parent_version_id); let uri = format!("/v1/client/add-version/{}", parent_version_id);
let req = test::TestRequest::post() let req = test::TestRequest::post()

View file

@ -70,7 +70,8 @@ mod test {
} }
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = format!("/v1/client/get-child-version/{}", parent_version_id); let uri = format!("/v1/client/get-child-version/{}", parent_version_id);
let req = test::TestRequest::get() let req = test::TestRequest::get()
@ -103,7 +104,8 @@ mod test {
let parent_version_id = Uuid::new_v4(); let parent_version_id = Uuid::new_v4();
let storage: Box<dyn Storage> = Box::new(InMemoryStorage::new()); let storage: Box<dyn Storage> = Box::new(InMemoryStorage::new());
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = format!("/v1/client/get-child-version/{}", parent_version_id); let uri = format!("/v1/client/get-child-version/{}", parent_version_id);
let req = test::TestRequest::get() let req = test::TestRequest::get()
@ -128,7 +130,8 @@ mod test {
txn.new_client(client_key, Uuid::new_v4()).unwrap(); txn.new_client(client_key, Uuid::new_v4()).unwrap();
} }
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
// the child of an unknown parent_version_id is GONE // the child of an unknown parent_version_id is GONE
let uri = format!("/v1/client/get-child-version/{}", parent_version_id); let uri = format!("/v1/client/get-child-version/{}", parent_version_id);

View file

@ -59,7 +59,8 @@ mod test {
} }
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = "/v1/client/snapshot"; let uri = "/v1/client/snapshot";
let req = test::TestRequest::get() let req = test::TestRequest::get()
@ -94,7 +95,8 @@ mod test {
} }
let server = Server::new(storage); let server = Server::new(storage);
let mut app = test::init_service(App::new().service(server.service())).await; let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let uri = "/v1/client/snapshot"; let uri = "/v1/client/snapshot";
let req = test::TestRequest::get() let req = test::TestRequest::get()

View file

@ -1,21 +1,10 @@
#![deny(clippy::all)] #![deny(clippy::all)]
use actix_web::{middleware, middleware::Logger, App, HttpServer}; use actix_web::{middleware::Logger, App, HttpServer};
use clap::Arg; use clap::Arg;
use taskchampion_sync_server::storage::SqliteStorage; use taskchampion_sync_server::storage::SqliteStorage;
use taskchampion_sync_server::Server; use taskchampion_sync_server::Server;
// The `.wrap` method returns an opaque type, meaning that we can't easily return it from
// functions. So, we must apply these default headers when the app is created, which occurs both
// in `main` and in the tests. To check that those are both doing precisely the same thing, we use
// a macro. This is ugly, and will go away when actix-web is no longer the framework in use.
macro_rules! cache_control_headers {
($wrapped:expr) => {
$wrapped
.wrap(middleware::DefaultHeaders::new().header("Cache-Control", "no-store, max-age=0"))
};
}
#[actix_web::main] #[actix_web::main]
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
env_logger::init(); env_logger::init();
@ -51,9 +40,9 @@ async fn main() -> anyhow::Result<()> {
log::warn!("Serving on port {}", port); log::warn!("Serving on port {}", port);
HttpServer::new(move || { HttpServer::new(move || {
cache_control_headers!(App::new()) App::new()
.wrap(Logger::default()) .wrap(Logger::default())
.service(server.service()) .configure(|cfg| server.config(cfg))
}) })
.bind(format!("0.0.0.0:{}", port))? .bind(format!("0.0.0.0:{}", port))?
.run() .run()
@ -65,21 +54,16 @@ async fn main() -> anyhow::Result<()> {
mod test { mod test {
use super::*; use super::*;
use actix_web::{test, App}; use actix_web::{test, App};
use pretty_assertions::assert_eq;
use taskchampion_sync_server::storage::InMemoryStorage; use taskchampion_sync_server::storage::InMemoryStorage;
#[actix_rt::test] #[actix_rt::test]
async fn test_index_get() { async fn test_index_get() {
let server = Server::new(Box::new(InMemoryStorage::new())); let server = Server::new(Box::new(InMemoryStorage::new()));
let app = cache_control_headers!(App::new()).service(server.service()); let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await; let mut app = test::init_service(app).await;
let req = test::TestRequest::get().uri("/").to_request(); let req = test::TestRequest::get().uri("/").to_request();
let resp = test::call_service(&mut app, req).await; let resp = test::call_service(&mut app, req).await;
assert!(resp.status().is_success()); assert!(resp.status().is_success());
assert_eq!(
resp.headers().get("Cache-Control").unwrap(),
&"no-store, max-age=0".to_string()
)
} }
} }

View file

@ -5,7 +5,7 @@ mod server;
pub mod storage; pub mod storage;
use crate::storage::Storage; use crate::storage::Storage;
use actix_web::{get, web, Responder, Scope}; use actix_web::{get, middleware, web, Responder};
use api::{api_scope, ServerState}; use api::{api_scope, ServerState};
#[get("/")] #[get("/")]
@ -28,17 +28,43 @@ impl Server {
} }
/// Get an Actix-web service for this server. /// Get an Actix-web service for this server.
pub fn service(&self) -> Scope { pub fn config(&self, cfg: &mut web::ServiceConfig) {
cfg.service(
web::scope("") web::scope("")
.data(self.storage.clone()) .data(self.storage.clone())
.wrap(
middleware::DefaultHeaders::new()
.header("Cache-Control", "no-store, max-age=0"),
)
.service(index) .service(index)
.service(api_scope()) .service(api_scope()),
);
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*;
use crate::storage::InMemoryStorage;
use actix_web::{test, App};
use pretty_assertions::assert_eq;
pub(crate) fn init_logging() { pub(crate) fn init_logging() {
let _ = env_logger::builder().is_test(true).try_init(); let _ = env_logger::builder().is_test(true).try_init();
} }
#[actix_rt::test]
async fn test_cache_control() {
let server = Server::new(Box::new(InMemoryStorage::new()));
let app = App::new().configure(|sc| server.config(sc));
let mut app = test::init_service(app).await;
let req = test::TestRequest::get().uri("/").to_request();
let resp = test::call_service(&mut app, req).await;
assert!(resp.status().is_success());
assert_eq!(
resp.headers().get("Cache-Control").unwrap(),
&"no-store, max-age=0".to_string()
)
}
} }