From ca29121ad9790ee8a9954040db61df8e887089e5 Mon Sep 17 00:00:00 2001 From: mdecimus Date: Tue, 8 Aug 2023 19:21:01 +0200 Subject: [PATCH] Allow custom HTTP headers to be set (#52) --- crates/jmap/src/api/config.rs | 28 +++++++++++++++++++++++++++- crates/jmap/src/api/http.rs | 13 ++++++++++++- crates/jmap/src/lib.rs | 2 ++ resources/config/jmap.toml | 3 +++ tests/resources/test_config.toml | 3 +++ 5 files changed, 47 insertions(+), 2 deletions(-) diff --git a/crates/jmap/src/api/config.rs b/crates/jmap/src/api/config.rs index ac25b386..abed3120 100644 --- a/crates/jmap/src/api/config.rs +++ b/crates/jmap/src/api/config.rs @@ -21,7 +21,7 @@ * for more details. */ -use std::time::Duration; +use std::{str::FromStr, time::Duration}; use store::{ fts::Language, @@ -140,6 +140,32 @@ impl crate::Config { .unwrap_or(true), encrypt: settings.property_or_static("jmap.encryption.enable", "true")?, encrypt_append: settings.property_or_static("jmap.encryption.append", "false")?, + http_headers: settings + .values("jmap.http.headers") + .map(|(_, v)| { + if let Some((k, v)) = v.split_once(':') { + Ok(( + hyper::header::HeaderName::from_str(k.trim()).map_err(|err| { + format!( + "Invalid header found in property \"jmap.http.headers\": {}", + err + ) + })?, + hyper::header::HeaderValue::from_str(v.trim()).map_err(|err| { + format!( + "Invalid header found in property \"jmap.http.headers\": {}", + err + ) + })?, + )) + } else { + Err(format!( + "Invalid header found in property \"jmap.http.headers\": {}", + v + )) + } + }) + .collect::, String>>()?, }; config.add_capabilites(settings); Ok(config) diff --git a/crates/jmap/src/api/http.rs b/crates/jmap/src/api/http.rs index 2f07c94a..4153b4e1 100644 --- a/crates/jmap/src/api/http.rs +++ b/crates/jmap/src/api/http.rs @@ -446,7 +446,18 @@ async fn handle_request( uri = req.uri().to_string(), ); - let response = parse_jmap_request(jmap, req, session.remote_ip, instance).await; + // Parse JMAP request + let mut response = + parse_jmap_request(jmap.clone(), req, session.remote_ip, instance).await; + + // Add custom headers + if !jmap.config.http_headers.is_empty() { + let headers = response.headers_mut(); + + for (header, value) in &jmap.config.http_headers { + headers.insert(header.clone(), value.clone()); + } + } Ok::<_, hyper::Error>(response) } diff --git a/crates/jmap/src/lib.rs b/crates/jmap/src/lib.rs index fa297178..c218118d 100644 --- a/crates/jmap/src/lib.rs +++ b/crates/jmap/src/lib.rs @@ -150,6 +150,8 @@ pub struct Config { pub oauth_expiry_refresh_token_renew: u64, pub oauth_max_auth_attempts: u32, + pub http_headers: Vec<(hyper::header::HeaderName, hyper::header::HeaderValue)>, + pub encrypt: bool, pub encrypt_append: bool, diff --git a/resources/config/jmap.toml b/resources/config/jmap.toml index 6ee03c5d..3759bee5 100644 --- a/resources/config/jmap.toml +++ b/resources/config/jmap.toml @@ -36,6 +36,9 @@ timeout = "30s" [jmap] directory = "__DIRECTORY__" +[jmap.http] +#headers = ["Access-Control-Allow-Origin: *", "Access-Control-Allow-Methods: POST, GET"] + [jmap.encryption] enable = true append = false diff --git a/tests/resources/test_config.toml b/tests/resources/test_config.toml index c9704cee..1fbfc296 100644 --- a/tests/resources/test_config.toml +++ b/tests/resources/test_config.toml @@ -104,6 +104,9 @@ private-key = "file://./tests/resources/tls_privatekey.pem" [jmap] directory = "local" +[jmap.http] +headers = ["Access-Control-Allow-Origin: *", "Access-Control-Allow-Methods: POST, GET, HEAD"] + [jmap.protocol] set.max-objects = 100000