Skip to content

Commit a24c247

Browse files
committed
Address IPv6
1 parent 239ffff commit a24c247

File tree

2 files changed

+50
-10
lines changed

2 files changed

+50
-10
lines changed

dsc/tests/dsc_functions.tests.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,10 @@ Describe 'tests for function expressions' {
11461146
@{ base = 'https://example.com/path'; relative = 'http://different.com/path'; expected = 'http://different.com/path' }
11471147
@{ base = 'https://user:pass@example.com/'; relative = 'path'; expected = 'https://user:pass@example.com/path' }
11481148
@{ base = 'https://example.com/'; relative = 'café/file.txt'; expected = 'https://example.com/caf%C3%A9/file.txt' }
1149+
@{ base = 'https://[::1]/'; relative = 'path'; expected = 'https://[0000:0000:0000:0000:0000:0000:0000:0001]/path' }
1150+
@{ base = 'https://[2001:db8::1]/'; relative = 'api/v1'; expected = 'https://[2001:0DB8:0000:0000:0000:0000:0000:0001]/api/v1' }
1151+
@{ base = 'https://[2001:db8::1]:8080/'; relative = 'api'; expected = 'https://[2001:0DB8:0000:0000:0000:0000:0000:0001]:8080/api' }
1152+
@{ base = 'http://192.168.1.1/'; relative = 'api/v1'; expected = 'http://192.168.1.1/api/v1' }
11491153
) {
11501154
param($base, $relative, $expected)
11511155

lib/dsc-lib/src/functions/uri.rs

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rust_i18n::t;
88
use serde_json::Value;
99
use super::Function;
1010
use url::Url;
11+
use std::net::Ipv6Addr;
1112

1213
#[derive(Debug, Default)]
1314
pub struct Uri {}
@@ -48,19 +49,24 @@ impl Function for Uri {
4849
return Err(DscError::Parser(t!("functions.uri.invalidRelativeUri").to_string()));
4950
}
5051

51-
if let Some(uri_without_slashes) = relative_uri.strip_prefix("//") {
52-
let scheme = base.scheme();
53-
54-
if uri_without_slashes.contains('/') {
55-
return Ok(Value::String(format!("{scheme}:{relative_uri}")));
56-
}
57-
return Ok(Value::String(format!("{scheme}:{relative_uri}/")));
58-
}
59-
6052
let result = base.join(relative_uri)
6153
.map_err(|e| DscError::Parser(format!("{}: {}", t!("functions.uri.invalidRelativeUri"), e)))?;
6254

63-
Ok(Value::String(result.to_string()))
55+
let final_result = if let Some(url::Host::Ipv6(ipv6_addr)) = result.host() {
56+
let segments = ipv6_addr.segments();
57+
let expanded = format!("{:04X}:{:04X}:{:04X}:{:04X}:{:04X}:{:04X}:{:04X}:{:04X}",
58+
segments[0], segments[1], segments[2], segments[3],
59+
segments[4], segments[5], segments[6], segments[7]
60+
);
61+
62+
let addr = Ipv6Addr::from(segments);
63+
let compressed = addr.to_string();
64+
result.to_string().replace(&compressed, &expanded)
65+
} else {
66+
result.to_string()
67+
};
68+
69+
Ok(Value::String(final_result))
6470
}
6571
}
6672

@@ -217,4 +223,34 @@ mod tests {
217223
let result = parser.parse_and_execute("[uri('https://example.com/', '//foo/bar')]", &Context::new()).unwrap();
218224
assert_eq!(result, "https://foo/bar");
219225
}
226+
227+
#[test]
228+
fn test_uri_ipv6_localhost() {
229+
let mut parser = Statement::new().unwrap();
230+
let result = parser.parse_and_execute("[uri('https://[::1]/', 'path')]", &Context::new()).unwrap();
231+
// IPv6 should be expanded to match .NET behavior
232+
assert_eq!(result, "https://[0000:0000:0000:0000:0000:0000:0000:0001]/path");
233+
}
234+
235+
#[test]
236+
fn test_uri_ipv6_address() {
237+
let mut parser = Statement::new().unwrap();
238+
let result = parser.parse_and_execute("[uri('https://[2001:db8::1]/', 'api/v1')]", &Context::new()).unwrap();
239+
// IPv6 should be expanded to match .NET behavior
240+
assert_eq!(result, "https://[2001:0DB8:0000:0000:0000:0000:0000:0001]/api/v1");
241+
}
242+
243+
#[test]
244+
fn test_uri_ipv6_with_port() {
245+
let mut parser = Statement::new().unwrap();
246+
let result = parser.parse_and_execute("[uri('https://[2001:db8::1]:8080/', 'api')]", &Context::new()).unwrap();
247+
assert_eq!(result, "https://[2001:0DB8:0000:0000:0000:0000:0000:0001]:8080/api");
248+
}
249+
250+
#[test]
251+
fn test_uri_ipv4_address() {
252+
let mut parser = Statement::new().unwrap();
253+
let result = parser.parse_and_execute("[uri('http://192.168.1.1/', 'api/v1')]", &Context::new()).unwrap();
254+
assert_eq!(result, "http://192.168.1.1/api/v1");
255+
}
220256
}

0 commit comments

Comments
 (0)