I am building a HTTP server using Tokio and Hyper, much like the api example given in the GitHub repo.
Adding preflight headers (in this case, for Cross-Origin-Resource-Sharing) turned out to be tricky. I think I figured out something that worked, but it was difficult enough I wanted to document it for posterity.
This didn't work - part of a function that generates a response is below. A web page in Chrome calling the api built with Hyper on the back end still told me the "Access-Control-Allow-Origin" hearer was missing on the preflight request. But I thought I added it?
pub async fn some_responder(&self, req: Request<Body>) -> Result<Response<Body>, GenericError> {
// ---- snip ----
let response = Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "application/json")
.header("Access-Control-Allow-Origin", "*") // I THOUGHT THIS WOULD FIX IT!?
.body(Body::default())?;
Ok(response)
}
Instead, I needed to add this matching pattern to the function routing incoming requests:
async fn request_router(req: Request<Body>,) -> Result<Response<Body>, GenericError> {
match (req.method(), req.uri().path()) {
(&Method::OPTIONS, "/") => preflight(req).await,
(&Method::GET, "/") | (&Method::GET, "/index.html") => Ok(Response::new(INDEX.into())),
// ---- snip ----
... and then add this handler for preflight requests...
pub async fn preflight(&self, req: Request<Body>) -> Result<Response<Body>, GenericError> {
let _whole_body = hyper::body::aggregate(req).await?;
let response = Response::builder()
.status(StatusCode::OK)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "*")
.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
.body(Body::default())?;
Ok(response)
}
It appears as though when Chrome calls the api, it first sends an OPTIONS request (which needs to confirm CORS), then the GET/POST etc.