ddn.net.uri¶
The ddn.net.uri module provides a complete, practical implementation of RFC 3986 (URI Generic Syntax) in D.
It supports parsing and serializing absolute URIs and relative references, component access (scheme, authority, path, query, fragment), normalization, reference resolution (RFC 3986 §5.2), percent-encoding helpers, IDNA/Punycode for internationalized hostnames, and RFC 6570 URI Templates.
Overview¶
The core type is URI, which represents either:
- an absolute URI (has a
scheme), or - a relative reference (no
scheme).
For convenience, the module also provides:
URL: a wrapper for hierarchical absolute URIs with an authority (scheme://host...)URN: a wrapper forurn:URIs with convenient access to the NSS
Key features¶
- RFC 3986 parsing & serialization: absolute URIs and relative references
- Normalization: scheme/host case-folding, dot-segment removal, percent-encoding normalization, default port elision
- Reference resolution: RFC 3986 §5.2
base.resolve(reference) - Percent-encoding utilities: encode/decode/normalize, per component
- IDNA/Punycode for hostnames:
URI.normalizeIDNA()andhostUnicode() - URI Templates (RFC 6570):
UriTemplate.parse(...)+expand(...)(Levels 1–4)
Basic usage¶
Parse and serialize¶
import ddn.net.uri;
auto u = URI.parse("http://user:pass@example.com:80/a/./b/../c?x=1#frag");
assert(u.scheme == "http");
assert(u.hasAuthority);
assert(u.authority.host == "example.com");
assert(u.authority.port == 80);
assert(u.path == "/a/./b/../c");
assert(u.query == "x=1");
assert(u.fragment == "frag");
assert(u.toString() == "http://user:pass@example.com:80/a/./b/../c?x=1#frag");
Normalize¶
import ddn.net.uri;
auto u = URI.parse("HTTP://EXAMPLE.COM:80/%7Euser/./a/../b");
auto n = u.normalize();
assert(n.toString() == "http://example.com/~user/b");
Resolve a relative reference¶
import ddn.net.uri;
auto base = URI.parse("http://a/b/c/d;p?q");
auto ref = URI.parse("g?y#s");
assert(base.resolve(ref).toString() == "http://a/b/c/g?y#s");
IDNA (internationalized hostnames)¶
Use normalizeIDNA() to apply RFC 3986 normalization and convert the host (when present and not an IP-literal) to ASCII using IDNA ToASCII.
import ddn.net.uri;
auto u = URI.parse("http://bücher.example/");
auto n = u.normalizeIDNA();
assert(n.toString() == "http://xn--bcher-kva.example/");
assert(n.hostUnicode() == "bücher.example");
Standard compliance¶
This module focuses on URI/URL/URN parsing, normalization, and related helpers. The table below summarizes which URI-related RFCs are supported and at what level.
| RFC | Topic | Support | Notes |
|---|---|---|---|
| RFC 3986 | URI Generic Syntax | Yes | Core parser/serializer/normalizer + RFC 3986 reference resolution (§5.2). |
| RFC 3987 | Internationalized Resource Identifiers (IRIs) | Partial | Non-ASCII hostnames can be parsed (reg-name) and normalized via normalizeIDNA(), but this is not a full IRI implementation for all components. |
| RFC 6570 | URI Templates | Yes | Full Level 4 operator support with conformance tests from RFC examples (UriTemplate.parse / expand). |
| RFC 2141 | URN Syntax (obsolete) | Partial | URNs can be parsed/serialized via URN wrapper, but this module does not implement URN-specific resolution rules. |
| RFC 8141 | URN Syntax (current) | Partial | URN wrapper is syntax-focused; does not implement the full RFC 8141 processing model. |
| RFC 3492 | Punycode | Yes | Core Punycode algorithm implemented (punycodeEncodeLabel / punycodeDecodeLabel). |
| RFC 5890–5895 | IDNA2008 | Partial | Basic ToASCII/ToUnicode + some strict checks and optional limited mappings; does not implement full contextual rules/UTS #46. |
| RFC 6874 | IPv6 Zone Identifiers in URIs | Yes | Parses/serializes zone identifiers in IP-literals using %25 encoding (e.g. http://[fe80::1%25eth0]/). |
| RFC 5952 | IPv6 Text Representation | No | The module validates IPv6 but does not fully canonicalize IPv6 text per RFC 5952. |
URI Templates (RFC 6570)¶
RFC 6570 URI Template support is implemented in the same module: ddn.net.uri.
Public entry points:
UriTemplate.parse(string)UriTemplate.expand(UriTemplateVars)