serde icon indicating copy to clipboard operation
serde copied to clipboard

cannot deserialize IPv6 SocketAddr from Strings

Open cfal opened this issue 2 years ago • 2 comments

i just switched to serde - previously I was parsing configs with IPv6 addresses manually and calling to_socket_addrs directly.

i noticed that it's not possible to automatically parse IPv6 addresses when deserializing String fields, and I needed to write a manual deserialize_with and convert to a String first. things seem to work as expected with IPv4 addresses.

example:

use std::net::{SocketAddr, ToSocketAddrs};
use serde::Deserialize;

#[derive(Debug, Clone, Deserialize)]
struct Config {
  address: SocketAddr
}

fn main() {
    // prints "address: [::1]:8080"
    println!("address: {}", "::1:8080".to_socket_addrs().unwrap().next().unwrap());

    let s = "{\"address\": \"::1:8080\"}";

    // this line fails with:
    // thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("invalid IP address syntax", line: 1, column: 22)', src/main.rs:17:40
    serde_json::from_str::<Config>(&s).unwrap();
}

cfal avatar Jun 13 '22 09:06 cfal

@cfal FWIW [::1]:8080 parses as you'd expect. ::1:8080 is a valid IPv6 address, so many parsers need brackets to disambiguate these cases.

olix0r avatar Jun 15 '22 15:06 olix0r

@olix0r oh interesting! thanks for the tip. i was curious if it'd work with a 5-digit port number (since i think that wouldn't be a valid ipv6 address anymore?), but it does still raise an error.

it might actually be fine to always require the square brackets for my usecase. i haven't looked at the serde code, but still curious to me why it works directly with String, i had expected the same behavior.

cfal avatar Jun 16 '22 17:06 cfal

This behavior is consistent with the standard library's impl FromStr for SocketAddr.

dtolnay avatar Jul 09 '23 07:07 dtolnay

@cfal brackets in IPv6 with port or within an URL are mandatory per IETF RFC to distinguish address, port and how many last octets you want to define.

E.g. ::1 is the same as 0:0:0:0:0:0:0:1 and ::1:8080 is 0:0:0:0:0:0:1:8080 per IPv6 RFC

eirnym avatar Mar 06 '24 10:03 eirnym