servo-net 0.1.0

A component of the servo web-engine.
Documentation
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use content_security_policy::Destination;
use headers::{Error, Header};
use http::{HeaderName, HeaderValue};
use net_traits::request::RequestMode;

static SEC_FETCH_DEST: HeaderName = HeaderName::from_static("sec-fetch-dest");

static SEC_FETCH_MODE: HeaderName = HeaderName::from_static("sec-fetch-mode");

static SEC_FETCH_SITE: HeaderName = HeaderName::from_static("sec-fetch-site");

static SEC_FETCH_USER: HeaderName = HeaderName::from_static("sec-fetch-user");

/// The `sec-fetch-dest` header
pub struct SecFetchDest(pub Destination);

/// The `sec-fetch-mode` header
///
/// This is effectively the same as a [RequestMode], except
/// it doesn't keep track of the websocket protocols
pub enum SecFetchMode {
    SameOrigin,
    Cors,
    NoCors,
    Navigate,
    WebSocket,
}

/// The `sec-fetch-user` header
pub struct SecFetchUser;

/// The `sec-fetch-site` header
#[derive(Eq, PartialEq)]
pub enum SecFetchSite {
    None,
    SameOrigin,
    SameSite,
    CrossSite,
}

impl Header for SecFetchDest {
    fn name() -> &'static HeaderName {
        &SEC_FETCH_DEST
    }

    fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
    where
        Self: Sized,
        I: Iterator<Item = &'i HeaderValue>,
    {
        // TODO
        Err(Error::invalid())
    }

    fn encode<E>(&self, values: &mut E)
    where
        E: Extend<HeaderValue>,
    {
        let value = HeaderValue::from_static(destination_as_str(self.0));
        values.extend(std::iter::once(value));
    }
}

impl From<Destination> for SecFetchDest {
    fn from(value: Destination) -> Self {
        Self(value)
    }
}

impl Header for SecFetchMode {
    fn name() -> &'static HeaderName {
        &SEC_FETCH_MODE
    }

    fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
    where
        Self: Sized,
        I: Iterator<Item = &'i HeaderValue>,
    {
        // TODO
        Err(Error::invalid())
    }

    fn encode<E>(&self, values: &mut E)
    where
        E: Extend<HeaderValue>,
    {
        let value = HeaderValue::from_static(self.as_str());
        values.extend(std::iter::once(value));
    }
}

impl<'a> From<&'a RequestMode> for SecFetchMode {
    fn from(value: &'a RequestMode) -> Self {
        match value {
            RequestMode::SameOrigin => Self::SameOrigin,
            RequestMode::CorsMode => Self::Cors,
            RequestMode::NoCors => Self::NoCors,
            RequestMode::Navigate => Self::Navigate,
            RequestMode::WebSocket { .. } => Self::WebSocket,
        }
    }
}

impl Header for SecFetchSite {
    fn name() -> &'static HeaderName {
        &SEC_FETCH_SITE
    }

    fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
    where
        Self: Sized,
        I: Iterator<Item = &'i HeaderValue>,
    {
        // TODO
        Err(Error::invalid())
    }

    fn encode<E>(&self, values: &mut E)
    where
        E: Extend<HeaderValue>,
    {
        let s = match self {
            Self::None => "none",
            Self::SameSite => "same-site",
            Self::CrossSite => "cross-site",
            Self::SameOrigin => "same-origin",
        };
        let value = HeaderValue::from_static(s);
        values.extend(std::iter::once(value));
    }
}

impl Header for SecFetchUser {
    fn name() -> &'static HeaderName {
        &SEC_FETCH_USER
    }

    fn decode<'i, I>(_: &mut I) -> Result<Self, Error>
    where
        Self: Sized,
        I: Iterator<Item = &'i HeaderValue>,
    {
        // TODO
        Err(Error::invalid())
    }

    fn encode<E>(&self, values: &mut E)
    where
        E: Extend<HeaderValue>,
    {
        let value = HeaderValue::from_static("?1");
        values.extend(std::iter::once(value));
    }
}

const fn destination_as_str(destination: Destination) -> &'static str {
    match destination {
        Destination::None => "empty",
        Destination::Audio => "audio",
        Destination::AudioWorklet => "audioworklet",
        Destination::Document => "document",
        Destination::Embed => "embed",
        Destination::Font => "font",
        Destination::Frame => "frame",
        Destination::IFrame => "iframe",
        Destination::Image => "image",
        Destination::Json => "json",
        Destination::Manifest => "manifest",
        Destination::Object => "object",
        Destination::PaintWorklet => "paintworklet",
        Destination::Report => "report",
        Destination::Script => "script",
        Destination::ServiceWorker => "serviceworker",
        Destination::SharedWorker => "sharedworker",
        Destination::Style => "style",
        Destination::Track => "track",
        Destination::Video => "video",
        Destination::WebIdentity => "webidentity",
        Destination::Worker => "worker",
        Destination::Xslt => "xslt",
    }
}

impl SecFetchMode {
    /// Converts to the spec representation of a [RequestMode]
    fn as_str(&self) -> &'static str {
        match self {
            Self::SameOrigin => "same-origin",
            Self::Cors => "cors",
            Self::NoCors => "no-cors",
            Self::Navigate => "navigate",
            Self::WebSocket => "websocket",
        }
    }
}