Rust rocket 을 이용한 백엔드 개발 (2)

Patch: https://github.com/spyrr/rocket-backend-ex/commit/f91cdec4fbddac711e46aec06a8444de9f5c1208

 

Update backend for CORS · spyrr/rocket-backend-ex@f91cdec

NEVER USE FOR PRODUCTION Signed-off-by: Hosub Lee <spyrr83@gmail.com></spyrr83@gmail.com>

github.com

 

지난번에 rocket으로 만든 백엔드에 vue 프론트를 붙여, 실행해보면, CORS와 관련하여 console error를 보여주면서, 정상적인 동작을 하지 않는다.

 

망할 CORS 에러

혹시나 해서... Rocket::shield [1] 의 내용을 확인했으나, CORS에 대한 설정은 지원하지 않는 것 같다.

 

이에.. 아래[2]와 같이 패치를 작성해서 1차적으로 테스트를 진행했다.

* CORS 설정 상 보안 요소는... 고려하지 않았다. 나중에 여러 가지로 테스트 해보려 함 -_-;

 

main.rs 파일 내, 추가한 CORS 관련 설정 내용 [2]

// for CORS settings
use rocket::{Request, Response};
use rocket::fairing::{Fairing, Info, Kind};
use rocket::http::Header;

pub struct CORS;

#[rocket::async_trait]
impl Fairing for CORS {
  fn info(&self) -> Info {
    Info {
      name: "Add CORS headers to responses",
      kind: Kind::Response,
    }
  }

  async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
    response.set_header(Header::new("Access-Control-Allow-Origin", "*"));
    response.set_header(Header::new("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE"));
    response.set_header(Header::new("Access-Control-Allow-Headers", "*"));
    response.set_header(Header::new("Access-Control-Allow-Credentials", "true"));
  }
}

 

 CORS를 사용하도록 설정 [2]

  rocket::build()
    .attach(CORS)
    .manage(db)
    .mount("/health", routes![check_health])
    .mount("/api/v1/books", routes![
      routes::books::get_books, // get
      routes::books::get_book, // get
      routes::books::new_book, // post
      routes::books::update_book, // put
      routes::books::delete_book,// delete
    ]).launch().await

 

그러나, 결과는... OPTIONS 메소드로 요청하는 preflight 결과가 404 에러를 뱉어내자, 기능이 정상적으로 동작하지 않았다. 이것 때문에, CORS 설정이 잘못된 줄 알고 이짓 저짓하느라 시간 낭비를....

결과적으로 OPTIONS 요청에 대해 200 OK 응답을 하면... 정상적으로 실행되었다.

망할 preflight

 

Rocket 의 Faring Hook을 통해, 모든 OPTIONS 요청에 대해 200 OK 204 No Content로 응답하도록 코드 작성

// for CORS settings
use rocket::{Request, Response};
use rocket::fairing::{Fairing, Info, Kind};
-use rocket::http::Header;
+use rocket::http::{Header, Status, Method};
+use rocket::yansi::Paint;
+use std::io::Cursor;

pub struct CORS;

#[rocket::async_trait]
impl Fairing for CORS {
  fn info(&self) -> Info {
    Info {
      name: "Add CORS headers to responses",
      kind: Kind::Response,
    }
  }

  async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
    response.set_header(Header::new("Access-Control-Allow-Origin", "*"));
    response.set_header(Header::new("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE"));
    response.set_header(Header::new("Access-Control-Allow-Headers", "*"));
    response.set_header(Header::new("Access-Control-Allow-Credentials", "true"));

+    // For preflight
+    if request.method() == Method::Options {
+      info_!("{}", Paint::green("Maybe preflight?"));
+      let rv = "";
+      response.set_status(Status::NoContent);
+      response.set_sized_body(rv.len(), Cursor::new(rv));
+    }
  }
}

 

처음엔... 모든 routes 에 대해 options 함수를 등록해서 사용했으나, 매우 비효율 적인데다, options 함수에서는 특별히 하는 일도 없기에... 위에처럼 로켓의 후커에서 response 명령에 대해 options 요청이 오면 무조건 200 ok를 뱉어내도록 강제했다.

 

아마도.... CORS와 더불어... preflight에 대해서도 공부가 필요할 것 같다. 저게 왜 필요한지도...

 

참고자료

[1] rocket::shield - Rust

 

rocket::shield - Rust

Security and privacy headers for all outgoing responses. The Shield fairing provides a typed interface for injecting HTTP security and privacy headers into all outgoing responses. It takes some inspiration from helmetjs, a similar piece of middleware for e

api.rocket.rs

[2] http - How to set up CORS or OPTIONS for Rocket.rs - Stack Overflow

 

How to set up CORS or OPTIONS for Rocket.rs

I've got a backend running rocket.rs which my flutter web app sends a request to, but it can't get past the OPTIONS response. I have tried adding CORS (rocket_cors) to the backend and having a op...

stackoverflow.com

[3] rocket_cors - Rust (docs.rs)

 

rocket_cors - Rust

Cross-origin resource sharing (CORS) for Rocket applications Nightly Rust Rocket >= 0.4 If you are using Rocket 0.3, use the 0.3.0 version of this crate. Rocket requires nightly Rust. You should probably install Rust with rustup, then override the code dir

docs.rs

 

Comment