use fastly::http::{header, HeaderValue, Method, StatusCode};
use fastly::{Error, Request, Response};

#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
    if req.get_method() == Method::OPTIONS
        && req.contains_header(header::ORIGIN)
        && (req.contains_header(header::ACCESS_CONTROL_REQUEST_HEADERS)
            || req.contains_header(header::ACCESS_CONTROL_REQUEST_METHOD))
    {
        Ok(Response::new()
            // Standard response to a preflight does not have a
            // response body, so a 204 No Content is appropriate,
            // though you can also send a 200 OK, that works too.
            .with_status(StatusCode::NO_CONTENT)
            // Echo the requested origin back to the client.  You
            // may like to check this against an allowlist of origins
            // instead of blindly allowing potentially destructive
            // requests from any origin
            .with_header(
                header::ACCESS_CONTROL_ALLOW_ORIGIN,
                req.get_header(header::ORIGIN).unwrap(), // We checked the `Origin` header exists above.
            )
            .with_header(
                header::ACCESS_CONTROL_ALLOW_HEADERS,
                req.get_header(header::ACCESS_CONTROL_REQUEST_HEADERS)
                    .unwrap_or(&HeaderValue::from_str("")?),
            )
            // Client may use this preflight response to authorise
            // future requests that would otherwise also require a
            // preflight, so to maximise reuse, we'll list all allowed
            // methods here, not just the one that was requested.
            // (think carefully before adding 'DELETE' to this list!)
            .with_header(
                header::ACCESS_CONTROL_ALLOW_METHODS,
                "GET,HEAD,POST,OPTIONS",
            )
            // Setting a cache TTL on the response allows the client
            // to use this preflight response for other requests.
            .with_header(header::ACCESS_CONTROL_MAX_AGE, "86400"))
    } else {
        Ok(
            Response::from_body("The page you requested could not be found")
                .with_status(StatusCode::NOT_FOUND),
        )
    }
}