From e8cebe068fe72d0909eb239ee2b1902281db2972 Mon Sep 17 00:00:00 2001 From: Dylan Bargatze Date: Wed, 16 Sep 2026 16:46:55 -0400 Subject: [PATCH 1/2] ts_control_serde: fix serialization of DerpMap::omit_default_regions In JSON, the field will be named `omitDefaultRegions` (lowercase first character); previously, `DerpMap` deserialization expected `OmitDefaultRegions` (pascal case), so a deserialized `DerpMap::omit_default_regions` would always be `false`. Signed-off-by: Dylan Bargatze --- ts_control_serde/src/derp_map.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/ts_control_serde/src/derp_map.rs b/ts_control_serde/src/derp_map.rs index b0a46186..9ce170b5 100644 --- a/ts_control_serde/src/derp_map.rs +++ b/ts_control_serde/src/derp_map.rs @@ -339,6 +339,7 @@ pub struct DerpMap<'a> { /// If there aren't any non-default DERP servers in [`DerpMap::regions`], this field is /// ignored. This field is only meaningful if [`DerpMap::regions`] is also populated, which /// indicates a change in the set of DERP regions/servers. + #[serde(rename = "omitDefaultRegions")] pub omit_default_regions: bool, } From ef25c8097dc4489c1a67907123737ca8b0cf2aba Mon Sep 17 00:00:00 2001 From: Dylan Bargatze Date: Wed, 16 Sep 2026 17:31:36 -0400 Subject: [PATCH 2/2] ts_control_serde: add omit_default_region parsing test Integration test on cut-down DerpMap to ensure we correctly parse/populate `DerpMap::omit_default_regions`. Signed-off-by: Dylan Bargatze --- ts_control_serde/tests/data/derp_map_odr.json | 47 +++++++++++++++++++ ts_control_serde/tests/parsing_tests.rs | 15 +++++- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 ts_control_serde/tests/data/derp_map_odr.json diff --git a/ts_control_serde/tests/data/derp_map_odr.json b/ts_control_serde/tests/data/derp_map_odr.json new file mode 100644 index 00000000..6bf84929 --- /dev/null +++ b/ts_control_serde/tests/data/derp_map_odr.json @@ -0,0 +1,47 @@ +{ + "Regions": { + "1": { + "RegionID": 1, + "RegionCode": "nyc", + "RegionName": "New York City", + "Latitude": 40.7128, + "Longitude": -74.006, + "Nodes": [ + { + "Name": "1h", + "RegionID": 1, + "HostName": "derp1h.tailscale.com", + "IPv4": "199.38.181.93", + "IPv6": "2607:f740:f::afd", + "CanPort80": true + }, + { + "Name": "1g", + "RegionID": 1, + "HostName": "derp1g.tailscale.com", + "IPv4": "209.177.145.120", + "IPv6": "2607:f740:f::3eb", + "CanPort80": true + }, + { + "Name": "1f", + "RegionID": 1, + "HostName": "derp1f.tailscale.com", + "IPv4": "199.38.181.104", + "IPv6": "2607:f740:f::bc", + "CanPort80": true + }, + { + "Name": "1i", + "RegionID": 1, + "HostName": "derp1i.tailscale.com", + "IPv4": "199.38.181.103", + "IPv6": "2607:f740:f::e19", + "STUNOnly": true, + "CanPort80": true + } + ] + } + }, + "omitDefaultRegions": true +} diff --git a/ts_control_serde/tests/parsing_tests.rs b/ts_control_serde/tests/parsing_tests.rs index 4818a3d2..19662e56 100644 --- a/ts_control_serde/tests/parsing_tests.rs +++ b/ts_control_serde/tests/parsing_tests.rs @@ -1,6 +1,6 @@ #![allow(missing_docs)] -use ts_control_serde::{MapResponse, Node}; +use ts_control_serde::{DerpMap, MapResponse, Node}; #[test] fn test_map_response_parse() { @@ -18,3 +18,16 @@ fn test_node_parse() { let node = serde_json::from_str::(TEST_NODE).expect("could not parse Node"); println!("{node:#?}"); } + +/// Validates that a `DerpMap` with "omitDefaultRegions" set is properly parsed. +#[test] +fn test_derp_map_omit_default_regions() { + const TEST_DERP_MAP: &str = include_str!("data/derp_map_odr.json"); + + let map = serde_json::from_str::(TEST_DERP_MAP) + .expect("could not parse DerpMap with omit_default_regions"); + assert!( + map.omit_default_regions, + "omit_default_regions should be true" + ); +}