aws_sdk_s3/endpoint_lib/
parse_url.rs

1// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
2/*
3 *  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *  SPDX-License-Identifier: Apache-2.0
5 */
6
7use crate::endpoint_lib::diagnostic::DiagnosticCollector;
8use http::Uri;
9use url::{Host, Url as ParsedUrl};
10
11#[derive(PartialEq, Debug)]
12pub(crate) struct Url<'a> {
13    uri: Uri,
14    url: ParsedUrl,
15    raw: &'a str,
16}
17
18// individual methods on parse_url might not be used (although the [`parse_url`] itself _MUST_ be used
19// since stdlib functions are pulled into crate lazily)
20#[allow(unused)]
21impl<'a> Url<'a> {
22    pub(crate) fn is_ip(&self) -> bool {
23        matches!(self.url.host(), Some(Host::Ipv4(_) | Host::Ipv6(_)))
24    }
25    pub(crate) fn scheme(&self) -> &str {
26        self.url.scheme()
27    }
28
29    pub(crate) fn authority(&self) -> &str {
30        self.uri.authority().unwrap().as_str()
31    }
32
33    pub(crate) fn normalized_path(&self) -> &str {
34        match self.uri.path() {
35            path if !path.is_empty() => path,
36            _ => "/",
37        }
38    }
39
40    pub(crate) fn path(&self) -> &str {
41        if self.uri.path() == "/" && !self.raw.ends_with('/') {
42            ""
43        } else {
44            self.uri.path()
45        }
46    }
47}
48
49pub(crate) fn parse_url<'a>(url: &'a str, e: &mut DiagnosticCollector) -> Option<Url<'a>> {
50    let raw = url;
51    let uri: Uri = e.capture(url.parse())?;
52    let url: ParsedUrl = e.capture(url.parse())?;
53    if let Some(query) = uri.query() {
54        e.report_error(format!("URL cannot have a query component (found {})", query));
55        return None;
56    }
57    if !["http", "https"].contains(&url.scheme()) {
58        e.report_error(format!("URL scheme must be HTTP or HTTPS (found {})", url.scheme()));
59        return None;
60    }
61    Some(Url { url, uri, raw })
62}
63
64#[cfg(test)]
65mod test {
66    use super::*;
67    use crate::endpoint_lib::diagnostic::DiagnosticCollector;
68
69    #[allow(clippy::bool_assert_comparison)]
70    #[test]
71    fn parse_simple_url() {
72        let url = "https://control.vpce-1a2b3c4d-5e6f.s3.us-west-2.vpce.amazonaws.com";
73        let url = parse_url(url, &mut DiagnosticCollector::new()).expect("valid url");
74        assert_eq!(url.path(), "");
75        assert_eq!(url.normalized_path(), "/");
76        assert_eq!(url.is_ip(), false);
77        assert_eq!(url.scheme(), "https");
78        assert_eq!(url.authority(), "control.vpce-1a2b3c4d-5e6f.s3.us-west-2.vpce.amazonaws.com");
79    }
80
81    #[test]
82    fn schemes_are_normalized() {
83        let url = "HTTPS://control.vpce-1a2b3c4d-5e6f.s3.us-west-2.vpce.amazonaws.com";
84        let url = parse_url(url, &mut DiagnosticCollector::new()).expect("valid url");
85        assert_eq!(url.scheme(), "https");
86    }
87
88    #[allow(clippy::bool_assert_comparison)]
89    #[test]
90    fn parse_url_with_port() {
91        let url = "http://localhost:8000/path";
92        let url = parse_url(url, &mut DiagnosticCollector::new()).expect("valid url");
93        assert_eq!(url.path(), "/path");
94        assert_eq!(url.normalized_path(), "/path");
95        assert_eq!(url.is_ip(), false);
96        assert_eq!(url.scheme(), "http");
97        assert_eq!(url.authority(), "localhost:8000");
98    }
99
100    #[test]
101    fn only_http_https_supported() {
102        let url = "wss://localhost:8443/path";
103        assert_eq!(parse_url(url, &mut DiagnosticCollector::new()), None);
104    }
105}