1use rocket::fairing::{Fairing, Info, Kind};
3use rocket::http::Header;
4use std::io::Cursor;
5pub struct CORS();
7
8#[rocket::async_trait]
9impl Fairing for CORS {
10 fn info(&self) -> Info {
11 Info {
12 name: "Add CORS headers to requests",
13 kind: Kind::Response,
14 }
15 }
16
17 async fn on_response<'r>(
18 &self,
19 request: &'r rocket::Request<'_>,
20 response: &mut rocket::Response<'r>,
21 ) {
22 if request.method() == rocket::http::Method::Options
23 || response.content_type() == Some(rocket::http::ContentType::JSON)
24 {
25 response.set_header(Header::new("Access-Control-Allow-Origin", "*"));
32 response.set_header(Header::new(
33 "Access-Control-Allow-Methods",
34 "POST, GET, OPTIONS",
35 ));
36 response.set_header(Header::new("Access-Control-Allow-Headers", "Content-Type"));
37 }
42
43 if request.method() == rocket::http::Method::Options {
44 response.set_header(rocket::http::ContentType::Plain);
45 response.set_sized_body(0, Cursor::new(""));
46 }
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::CORS;
53 use rocket::local::blocking::Client;
54 use rocket::serde::json::Json;
55
56 #[rocket::get("/json")]
57 fn json_route() -> Json<&'static str> { Json("ok") }
58
59 fn client() -> Client {
60 let rocket = rocket::build()
61 .mount("/", rocket::routes![json_route])
62 .attach(CORS());
63 Client::tracked(rocket).expect("rocket client")
64 }
65
66 #[test]
67 fn public_json_gets_wildcard_origin_but_no_credentials() {
68 let client = client();
69 let resp = client.get("/json").dispatch();
70 let headers = resp.headers();
71 assert_eq!(headers.get_one("Access-Control-Allow-Origin"), Some("*"));
72 assert_eq!(headers.get_one("Access-Control-Allow-Credentials"), None);
74 assert_eq!(headers.get_one("Content-Security-Policy-Report-Only"), None);
76 }
77}