Cors filter in Warp ignored

402 views Asked by At

I am learning Rust and am Following the Tutorial in Learning Rust Webdevelopment (Manning) by Bastian Gruber link. I have tried many ways, but I could not get the Cors filter, as outlined in the book, to actually do something. It is simply ignored.

Furthermore, an OPTIONS call is answered with 405 Method not Allowed. Or to be more precise, a Rejection(MethodNotAllowed).

I tried removing Method::GET from allow_methods() which had no effect (get localhost:8000/questions is still possible). Previously, I added an error handler to the filter chain with recover() in order to examine the error which always is Rejection(MethodNotAllowed). I have removed it so that the example is shorter.

Also, I tried to explicitly allow OPTIONS in the filter chain with warp::OPTIONS(), but this simply returns with the result of the get_questions() function as if it was a get request. Cors is, again, ignored.

My minimum (not-)working example:

main.rs:

use warp::{hyper::Method, Filter};

#[macro_use]
extern crate log;

async fn get_questions() -> Result<impl warp::Reply, warp::Rejection> {
    Ok(warp::reply::html("<p>There are no questions...</p>"))
}

#[tokio::main]
async fn main() {
    env_logger::init();
    info!("starting up");
    let cors = warp::cors()
        .allow_any_origin()
        .allow_headers(vec![
            "User-Agent",
            "Sec-Fetch-Mode",
            "Referer",
            "Origin",
            "Access-Control-Request-Method",
            "Access-Control-Request-Headers",
        ])
        .allow_methods(&[Method::PUT, Method::DELETE, Method::POST, Method::GET])
        .build();

    let get_items = warp::get()
        .and(warp::path("questions"))
        .and(warp::path::end())
        .and_then(get_questions)
        .with(cors)
        .with(warp::log("cors test"));

    warp::serve(get_items).run(([127, 0, 0, 1], 8000)).await;
}

Cargo.toml:

[package]
name = "cors_ignored"
version = "0.1.0"
edition = "2021"

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

[dependencies]
tokio = { version = "1.25", features = ["full"] }
warp = "0.3.3"
log = "0.4.0"
env_logger = "0.9.0"

curl for testing cors:

curl -X OPTIONS localhost:8000/questions -v \
     -H "Access-Control-Request-Methods: PUT" \
     -H "Access-Control-Request-Headers: content-type"

Edit: As suggested, I tried to define the endpoint as put rather than get using warp::put(). The result is the same. An OPTIONS request yields a 405 "Method not allowed", so does a GET request. PUT, the one allowed by the route, yields a Status 200 and my HTML snippet as expected.

Also as suggested, I added "Content-Type" to allow_headers, but the behavior stayed the same.

1

There are 1 answers

0
ZhouYu On
  1. Use request header Access-Control-Request-Method which did not endswith s.
  2. Preflight request needs the Origin header.
curl -X OPTIONS localhost:8000/questions -v \
     -H "Access-Control-Request-Method: PUT" \
     -H "Access-Control-Request-Headers: content-type" \
     -H "Origin: https://foo.example"