(ctx: &Ctx<'js>, array: Array<'js>, guard: HeadersGuard)
| 447 | headers.push((k_lower.into(), value.into())); |
| 448 | } |
| 449 | headers.sort_by(|a, b| a.0.cmp(&b.0)); |
| 450 | return Ok(Self { headers, guard }); |
| 451 | } |
| 452 | } |
| 453 | |
| 454 | Ok(Self { |
| 455 | headers: vec![], |
| 456 | guard, |
| 457 | }) |
| 458 | } |
| 459 | |
| 460 | fn from_array<'js>(ctx: &Ctx<'js>, array: Array<'js>, guard: HeadersGuard) -> Result<Self> { |
| 461 | let mut headers: Vec<(ImmutableString, ImmutableString)> = Vec::with_capacity(array.len()); |
| 462 | |
| 463 | for entry in array.into_iter().flatten() { |
| 464 | if let Some(array_entry) = entry.as_array() { |
| 465 | if array_entry.len() % 2 != 0 { |
| 466 | return Err(Exception::throw_type(ctx, "Header arrays are not paired")); |
| 467 | } |
| 468 | |
| 469 | let mut raw_key = array_entry.get::<String>(0)?; |
| 470 | raw_key.make_ascii_lowercase(); |
| 471 | if !is_http_header_name(&raw_key) { |
| 472 | return Err(Exception::throw_type(ctx, "Invalid key")); |
| 473 | } |
| 474 | // Skip forbidden headers |
| 475 | if matches!(guard, HeadersGuard::Request | HeadersGuard::RequestNoCors) |
| 476 | && is_forbidden_request_header(&raw_key) |
| 477 | { |
| 478 | continue; |
| 479 | } |
| 480 | |
| 481 | let raw_value = array_entry.get::<Value>(1)?; |
| 482 | let value: ImmutableString = coerce_to_string(ctx, raw_value)?.into(); |
| 483 | if !is_http_header_value(&value) { |
| 484 | return Err(Exception::throw_type(ctx, "Invalid value of key")); |
| 485 | } |
| 486 | |
| 487 | if matches!(guard, HeadersGuard::Request | HeadersGuard::RequestNoCors) |
| 488 | && is_forbidden_method_override(&raw_key, &value) |
| 489 | { |
| 490 | continue; |
| 491 | } |
| 492 | |
| 493 | // Skip non-safelisted headers in no-cors mode |
| 494 | if guard == HeadersGuard::RequestNoCors |
| 495 | && !is_cors_safelisted_request_header(&raw_key, &value) |
| 496 | { |
| 497 | continue; |
| 498 | } |
| 499 | |
| 500 | if raw_key == SET_COOKIE.as_str() { |
| 501 | let key: ImmutableString = raw_key.into(); |
| 502 | headers.push((key, value)); |
| 503 | continue; |
| 504 | } |
| 505 | |
| 506 | if let Some((_, existing_value)) = |
nothing calls this directly
no test coverage detected