Coverage Report

Created: 2025-11-11 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/url-2.5.7/src/origin.rs
Line
Count
Source
1
// Copyright 2016 The rust-url developers.
2
//
3
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6
// option. This file may not be copied, modified, or distributed
7
// except according to those terms.
8
9
use crate::host::Host;
10
use crate::parser::default_port;
11
use crate::Url;
12
use alloc::borrow::ToOwned;
13
use alloc::format;
14
use alloc::string::String;
15
use core::sync::atomic::{AtomicUsize, Ordering};
16
17
0
pub fn url_origin(url: &Url) -> Origin {
18
0
    let scheme = url.scheme();
19
0
    match scheme {
20
0
        "blob" => {
21
0
            let result = Url::parse(url.path());
22
0
            match result {
23
0
                Ok(ref url) => url_origin(url),
24
0
                Err(_) => Origin::new_opaque(),
25
            }
26
        }
27
0
        "ftp" | "http" | "https" | "ws" | "wss" => Origin::Tuple(
28
0
            scheme.to_owned(),
29
0
            url.host().unwrap().to_owned(),
30
0
            url.port_or_known_default().unwrap(),
31
0
        ),
32
        // TODO: Figure out what to do if the scheme is a file
33
0
        "file" => Origin::new_opaque(),
34
0
        _ => Origin::new_opaque(),
35
    }
36
0
}
37
38
/// The origin of an URL
39
///
40
/// Two URLs with the same origin are considered
41
/// to originate from the same entity and can therefore trust
42
/// each other.
43
///
44
/// The origin is determined based on the scheme as follows:
45
///
46
/// - If the scheme is "blob" the origin is the origin of the
47
///   URL contained in the path component. If parsing fails,
48
///   it is an opaque origin.
49
/// - If the scheme is "ftp", "http", "https", "ws", or "wss",
50
///   then the origin is a tuple of the scheme, host, and port.
51
/// - If the scheme is anything else, the origin is opaque, meaning
52
///   the URL does not have the same origin as any other URL.
53
///
54
/// For more information see <https://url.spec.whatwg.org/#origin>
55
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
56
pub enum Origin {
57
    /// A globally unique identifier
58
    Opaque(OpaqueOrigin),
59
60
    /// Consists of the URL's scheme, host and port
61
    Tuple(String, Host<String>, u16),
62
}
63
64
impl Origin {
65
    /// Creates a new opaque origin that is only equal to itself.
66
0
    pub fn new_opaque() -> Self {
67
        static COUNTER: AtomicUsize = AtomicUsize::new(0);
68
0
        Self::Opaque(OpaqueOrigin(COUNTER.fetch_add(1, Ordering::SeqCst)))
69
0
    }
70
71
    /// Return whether this origin is a (scheme, host, port) tuple
72
    /// (as opposed to an opaque origin).
73
0
    pub fn is_tuple(&self) -> bool {
74
0
        matches!(*self, Self::Tuple(..))
75
0
    }
76
77
    /// <https://html.spec.whatwg.org/multipage/#ascii-serialisation-of-an-origin>
78
0
    pub fn ascii_serialization(&self) -> String {
79
0
        match *self {
80
0
            Self::Opaque(_) => "null".to_owned(),
81
0
            Self::Tuple(ref scheme, ref host, port) => {
82
0
                if default_port(scheme) == Some(port) {
83
0
                    format!("{scheme}://{host}")
84
                } else {
85
0
                    format!("{scheme}://{host}:{port}")
86
                }
87
            }
88
        }
89
0
    }
90
91
    /// <https://html.spec.whatwg.org/multipage/#unicode-serialisation-of-an-origin>
92
0
    pub fn unicode_serialization(&self) -> String {
93
0
        match *self {
94
0
            Self::Opaque(_) => "null".to_owned(),
95
0
            Self::Tuple(ref scheme, ref host, port) => {
96
0
                let host = match *host {
97
0
                    Host::Domain(ref domain) => {
98
0
                        let (domain, _errors) = idna::domain_to_unicode(domain);
99
0
                        Host::Domain(domain)
100
                    }
101
0
                    _ => host.clone(),
102
                };
103
0
                if default_port(scheme) == Some(port) {
104
0
                    format!("{scheme}://{host}")
105
                } else {
106
0
                    format!("{scheme}://{host}:{port}")
107
                }
108
            }
109
        }
110
0
    }
111
}
112
113
/// Opaque identifier for URLs that have file or other schemes
114
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
115
pub struct OpaqueOrigin(usize);