Expand description

URI and IRI resolvers.

IRI resolution can fail

Though this is not explicitly stated in RFC 3986, IRI resolution can fail. Below are examples:

  • base=scheme:, ref=.///bar.
    • Resulting IRI should have scheme scheme and path //bar, but does not have authority.
  • base=scheme:foo, ref=.///bar.
    • Resulting IRI should have scheme scheme and path //bar, but does not have authority.
  • base=scheme:, ref=/..//baz.
    • Resulting IRI should have scheme scheme and path //bar, but does not have authority.
  • base=scheme:foo/bar, ref=..//baz.
    • Resulting IRI should have scheme scheme and path //bar, but does not have authority.

IRI without authority (note that this is different from “with empty authority”) cannot have a path starting with //, since it is ambiguous and can be interpreted as an IRI with authority. For the above examples, scheme://bar is not valid output, as bar in scheme://bar will be interpreted as an authority, not a path.

Thus, IRI resolution can fail for some abnormal cases.

Note that this kind of failure can happen only when the base IRI has no authority and empty path. This would be rare in the wild, since many people would use an IRI with authority part, such as http://.

If you are handling scheme://-style URIs and IRIs, don’t worry about the failure. Currently no cases are known to fail when at least one of the base IRI or the relative IRI contains authorities.

If you want this kind of abnormal IRI resolution to succeed and to be idempotent, use WHATWG variation of resolution and normalization.

Examples

use iri_string::task::Error as TaskError;
use iri_string::types::{IriAbsoluteStr, IriReferenceStr};

let base = IriAbsoluteStr::new("scheme:")?;
{
    let reference = IriReferenceStr::new(".///not-a-host")?;
    let err = reference.resolve_against(base)
        .expect_err("this resolution should fail");
    assert!(matches!(err, TaskError::Process(_)), "normalization error");

    // WHATWG version.
    let resolved_whatwg = reference.resolve_whatwg_against(base)
        .expect("memory allocation failed");
    assert_eq!(*resolved_whatwg, "scheme:/.//not-a-host");
}

{
    let reference2 = IriReferenceStr::new("/..//not-a-host")?;
    // Resulting string will be `scheme://not-a-host`, but `not-a-host`
    // should be a path segment, not a host. So, the semantically correct
    // target IRI cannot be represented by RFC 3986 IRI resolution.
    let err2 = reference2.resolve_against(base)
        .expect_err("this resolution should fail");
    assert!(matches!(err2, TaskError::Process(_)), "normalization error");

    // Algorithm defined in WHATWG URL Standard addresses this case.
    let resolved_whatwg2 = reference2.resolve_whatwg_against(base)
        .expect("memory allocation failed");
    assert_eq!(*resolved_whatwg2, "scheme:/.//not-a-host");
}

Structs

A resolver against the fixed base.

Functions

Resolves the IRI reference.

Resolves and normalizes the IRI reference.

Resolves and normalizes the IRI reference.

Resolves the IRI reference.