Rocket (Rust) で CORS の設定をする

今回も前回の軽い続きです。
ohshige.hatenablog.com

APIは作れるようになったので、今度はこれを呼び出したい思いです。
同じドメインなら問題無いですが、異なるドメインから呼び出したい場合に設定しないといけないがCORSです。

前回の状態で適当にJSからXHRを試して http://localhost:8000/users を呼び出そうとすると、以下のようにエラーとなります。

Access to XMLHttpRequest at 'http://localhost:8000/users' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

実際にレスポンスヘッダーを見ても、当たり前ですがCORSの設定は何もありません。

HTTP/1.1 200 OK
Content-Type: application/json
Server: Rocket
Content-Length: 73
Date: Mon, 24 Feb 2020 19:00:00 GMT

というわけで、 rocket_cors を使います。
docs.rs

Cargo.toml

rocket_cors = "*" を追記します。

[package]
name = "demo"
version = "0.1.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rusqlite = "*"
rocket = "*"
rocket_contrib = { version = "*", features = ["json"] }
rocket_cors = "*"
serde = "*"
serde_derive = "*"

main.rs

CorsOptions::default() をアタッチすることでCORSを設定できます。
デフォルトだとオールオッケーな感じなので、適宜必要な範囲に絞る必要があります。

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;
#[macro_use] extern crate serde_derive;

extern crate rusqlite;
extern crate rocket_contrib;
extern crate rocket_cors;

use rusqlite::{Connection, NO_PARAMS};
use rocket_contrib::json::Json;
use rocket_cors::CorsOptions;

(略)

fn main() {
  rocket::ignite()
      .mount("/", routes![get_users, get_user])
      .attach(CorsOptions::default().to_cors().expect("error"))
      .launch();
}

上記を実行すると以下のようになります。

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.10s
     Running `target/debug/demo`
🔧 Configured for development.
(略)
🛰  Mounting /:
    => GET /users (get_users)
    => GET /users/<user_id> (get_user)
🛰  Mounting /cors:
    => GET /cors/<status>
📡 Fairings:
    => 1 request: CORS
    => 1 response: CORS
🚀 Rocket has launched from http://localhost:8000

それらしい起動ができている気がします。

この状態で新たにJSからXHRを試してみると、エラーは起きず無事にできていることがわかります。
レスポンスヘッダーを見てみると、 null ではありますが Access-Control-Allow-OriginVary が増えています。

HTTP/1.1 200 OK
Content-Type: application/json
Server: Rocket
Access-Control-Allow-Origin: null
Vary: Origin
Content-Length: 73
Date: Mon, 24 Feb 2020 19:00:00 GMT