Repository: awslabs/llrt
File: src/http/fetch.rs (Rust)

Code before:
                    ctx,
                    &format!("Invalid HTTP method: {}", method_opt),
                )),
            }?);
        }

        if let Some(body_opt) = get_option::<Value>("body", &arg_opts, &resource_opts)? {
            let bytes = get_bytes(ctx, body_opt)?;
            body = Some(Full::from(bytes));
        }

        if let Some(url_opt) = get_option::<String>("url", &arg_opts, &resource_opts)? {
            url = Some(url_opt);
        }

        if let Some(headers_op) = get_option::<Value>("headers", &arg_opts, &resource_opts)? {
            headers = Some(Headers::from_value(ctx, headers_op)?);
        }

        if let Some(signal) = get_option::<Class<AbortSignal>>("signal", &arg_opts, &resource_opts)?
        {
            abort_receiver = Some(signal.borrow().sender.subscribe());
        }

        if let Some(redirect_opt) = get_option::<String>("redirect", &arg_opts, &resource_opts)? {
            redirect = Some(match redirect_opt.as_str() {
                "follow" => Ok("follow"),
                "error" => Ok("error"),
                "manual" => Ok("manual"),
                _ => Err(Exception::throw_type(
                    ctx,
                    &format!("Invalid redirect option: {}", redirect_opt),
                )),
            }?);
        }
    }

    let url = match url {
        Some(url) => url,
        None => return Err(Exception::throw_reference(ctx, "Missing required url")),
    };

    Ok(FetchOptions {
        method: method.unwrap_or_default(),
        url,
        headers,
        body: body.unwrap_or_default(),
        abort_receiver,
        redirect: redirect.unwrap_or_default().to_string(),
    })
}

Review comment (suggestion):
We can probably do something like:
```rust
let redirect_str = redirect_opt.as_str();
if !matches!(redirect_str, "follow" | "manual" | "error"){
   return Err(....)
}
```

Code after:

    if prev_status == 303 {
        return !matches!(*method, Method::GET | Method::HEAD);
    }

    false
}

fn is_request_body_header_name(key: &str) -> bool {
    matches!(
        key,
        "content-encoding" | "content-language" | "content-location" | "content-type"
    )
}

fn is_cors_non_wildcard_request_header_name(key: &str) -> bool {
    matches!(key, "authorization")
}

struct FetchOptions<'js> {
    method: hyper::Method,
    url: String,
    headers: Option<Headers>,
    body: Full<Bytes>,
    abort_receiver: Option<mc_oneshot::Receiver<Value<'js>>>,
    redirect: String,
}

fn get_fetch_options<'js>(
    ctx: &Ctx<'js>,
    resource: Value<'js>,
    opts: Opt<Value<'js>>,
) -> Result<FetchOptions<'js>> {
    let mut url = None;
    let mut resource_opts = None;
    let mut arg_opts = None;
    let mut headers = None;
    let mut method = None;
    let mut body = None;
    let mut abort_receiver = None;
    let mut redirect = String::from("");

    if let Some(obj) = resource.as_object() {
        let obj = obj.clone();
        if obj.instance_of::<crate::http::Request>() {
            resource_opts = Some(obj);
        } else if let Some(to_string) = obj.get::<_, Option<Function>>(PredefinedAtom::ToString)? {
            url = Some(to_string.call::<_, String>((This(obj),))?);
        } else {
            resource_opts = Some(obj);
        }