use actix_cors::Cors; use actix_web::{http::header, middleware::Logger, web, App, HttpServer}; #[actix_web::main] async fn main() -> std::io::Result<()> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); log::info!("starting HTTP server at http://localhost:8080"); HttpServer::new(move || { App::new() // `permissive` is a wide-open development config // .wrap(Cors::permissive()) .wrap( // default settings are overly restrictive to reduce chance of // misconfiguration leading to security concerns Cors::default() // add specific origin to allowed origin list .allowed_origin("http://project.local:8080") // allow any port on localhost .allowed_origin_fn(|origin, _req_head| { origin.as_bytes().starts_with(b"http://localhost") // manual alternative: // unwrapping is acceptable on the origin header since this function is // only called when it exists // req_head // .headers() // .get(header::ORIGIN) // .unwrap() // .as_bytes() // .starts_with(b"http://localhost") }) // set allowed methods list .allowed_methods(vec!["GET", "POST"]) // set allowed request header list .allowed_headers(&[header::AUTHORIZATION, header::ACCEPT]) // add header to allowed list .allowed_header(header::CONTENT_TYPE) // set list of headers that are safe to expose .expose_headers(&[header::CONTENT_DISPOSITION]) // allow cURL/HTTPie from working without providing Origin headers .block_on_origin_mismatch(false) // set preflight cache TTL .max_age(3600), ) .wrap(Logger::default()) .default_service(web::to(|| async { "Hello, cross-origin world!" })) }) .workers(1) .bind(("127.0.0.1", 8080))? .run() .await }