Rust LogoURL

URL (Uniform Resource Locator) is a reference to a web resource that specifies its location on a computer network and a mechanism for retrieving it. URLs are fundamental to how the internet works, used for identifying websites, images, documents, and other resources.

Key components of a URL typically include:
* Scheme (Protocol): `http`, `https`, `ftp`, `mailto`, `file`, etc. Specifies the protocol to be used (e.g., how to retrieve the resource).
* Host: The domain name or IP address of the server providing the resource (e.g., `www.example.com`).
* Port (Optional): The specific port number on the server to connect to (e.g., `:8080`). If omitted, it defaults to the standard port for the scheme (e.g., 80 for HTTP, 443 for HTTPS).
* Path: The specific location of the resource on the server, resembling a file system path (e.g., `/path/to/resource`).
* Query (Optional): A string of key-value pairs, typically used to pass parameters to the server for dynamic content generation or filtering (e.g., `?query=value¶m=other`).
* Fragment (Optional): An identifier that points to a specific part of a resource within the document itself (e.g., `#section`). This part is client-side and not typically sent to the server.

In programming, handling URLs involves several common tasks:
* Parsing: Breaking down a URL string into its individual components for inspection or manipulation.
* Building/Constructing: Creating a URL string from its components programmatically.
* Modifying: Changing specific parts of an existing URL, such as updating query parameters or altering the path.
* Resolving Relative URLs: Combining a base URL with a relative path (e.g., `./items` or `/another/page`) to get a full, absolute URL.
* Encoding/Decoding: Handling special characters within URL components (e.g., spaces converted to `%20`, special symbols percent-encoded) to ensure they are valid and correctly interpreted.

Rust's standard library does not provide a comprehensive module for general URL parsing and manipulation directly. For robust URL handling, the `url` crate is the de-facto standard in the Rust ecosystem. It offers a powerful and flexible `Url` struct that implements the WHATWG URL Living Standard, making it suitable for web applications and general network programming. The `url` crate allows you to:
* Parse URL strings with strong error handling.
* Access individual components of a URL (scheme, host, path, query, fragment) through dedicated methods.
* Modify URL components safely.
* Build new URLs from scratch or by resolving relative paths against an existing base URL.
* Handle percent-encoding and decoding automatically for various components.

Example Code

```rust
use url::{Url, ParseError};

fn main() -> Result<(), ParseError> {
    // 1. Parsing a URL string
    let base_url_str = "https://www.example.com:8080/path/to/resource?name=Rust&version=1.60#chapter1";
    println!("Attempting to parse: {}\n", base_url_str);

    let mut url = match Url::parse(base_url_str) {
        Ok(u) => u,
        Err(e) => {
            eprintln!("Failed to parse URL: {}\n", e);
            return Err(e);
        }
    };

    // 2. Accessing URL components
    println!("--- URL Components ---");
    println!("Scheme:          {}", url.scheme());
    println!("Host:            {:?}", url.host_str());
    println!("Port:            {:?}", url.port());
    println!("Path:            {}", url.path());
    println!("Query:           {:?}", url.query()); // Raw query string
    println!("Fragment:        {:?}\n", url.fragment());

    // Iterating over query parameters (decoded automatically)
    println!("Query Parameters:");
    if url.query().is_some() {
        for (key, value) in url.query_pairs() {
            println!("  {}: {}", key, value);
        }
    }
    println!("");

    // 3. Modifying URL components
    println!("--- Modifying URL ---");
    url.set_host(Some("api.example.org")).unwrap(); // unwrap() for example simplicity
    url.set_scheme("http").unwrap(); // unwrap() for example simplicity
    url.set_path("/v2/data");
    url.set_port(None).unwrap(); // Remove port, unwrap() for example simplicity

    // Modify query parameters: clear existing and add new ones
    url.query_pairs_mut()
        .clear()
        .append_pair("id", "123")
        .append_pair("format", "json");
    url.set_fragment(Some("result"));

    println!("Modified URL: {}", url);
    println!("Scheme after modification: {}\n", url.scheme());

    // 4. Resolving relative URLs
    println!("--- Resolving Relative URL ---");
    let relative_path = "./items?limit=10";
    let resolved_url = url.join(relative_path)?;
    println!("Base URL for resolution:  {}", url);
    println!("Relative path:            {}", relative_path);
    println!("Resolved URL:             {}\n", resolved_url);

    // Example of a badly formed URL parsing attempt
    let bad_url_str = "this is not a url";
    println!("Attempting to parse a bad URL: {}\n", bad_url_str);
    match Url::parse(bad_url_str) {
        Ok(u) => println!("Unexpectedly parsed: {}\n", u),
        Err(e) => println!("Correctly failed to parse: {}\n", e),
    };

    Ok(())
}

/*
To run this code, add the `url` crate to your `Cargo.toml`:

[dependencies]
url = "2.5"
*/
```