iri

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 30, 2023 License: Apache-2.0, BSD-3-Clause Imports: 4 Imported by: 1

README

Internationalized Resource identifiers (IRI) library for Go

Go version of Go module GoDoc reference GoReportCard License

This repository is archived. Ultimately, there was no need for this library. Furthermore, the realization is also that "Resource Identifier" could be an "unlimited" data structure, and separate serialization rules then govern whether it becomes an IRI, URI, URL, or whatever flavor (RFC) wanted. This would be a further (incompatible) rework of the API.

This library provides facilities for working with Internationalized Resource Identifiers (IRI) as specified in RFC 3987.

RFC reference: https://www.ietf.org/rfc/rfc3987.html

Generally speaking, an IRI is a URI that allows international characters; And a URI is a generic form of the now rather deprecated URL (= address) and URN (= name).

Although conceptually an IRI is meant to be a generalized concept of a URL, type iri.IRI and its functions cannot be used as a drop-in replacement of net/url.URL. The standard Go implementation handles many corner cases and "real life" behaviour of existing systems.

Examples

func ExampleParse_https() {
	value, _ := iri.Parse("https://user@example.com/µ/path?q=€#frag1")
	fmt.Printf("%#v", value)
	// Output: iri.IRI{Scheme:"https", ForceAuthority:false, Authority:"user@example.com", Path:"/µ/path", ForceQuery:false, Query:"q=€", ForceFragment:false, Fragment:"frag1"}
}

func ExampleIRI_String_common() {
	value := iri.IRI{Scheme: "https", ForceAuthority: false, Authority: "user@example.com", Path: "/sub/path", ForceQuery: false, Query: "q=1", ForceFragment: false, Fragment: "frag1"}
	fmt.Printf("%s", value)
	// Output: https://user@example.com/sub/path?q=1#frag1
}

Origin

The code in this library is forked off from https://github.com/google/xtoproto/rdf/iri @4cad7286ebfcd65dfec376912eb3b7a03c531c9b

The code from xtoproto itself is derived from https://github.com/golang/go/blob/master/src/net/url/url.go , which is why the LICENSE file contains extra information.

A separate repository was created to avoid adding a dependency to an unrelated large library, just for one small package, which should have been on its own to begin with.

Tag v0.1.0 contains the exact replication of the forked code.

LICENSE

Apache License 2.0, with notice from the Go language project. See LICENSE file.

Documentation

Overview

Package iri provides facilities for working with Internationalized Resource Identifiers as specified in RFC 3987.

RFC reference: https://www.ietf.org/rfc/rfc3987.html

Although conceptually an IRI is meant to be a generalized concept of a URL, type IRI and its functions cannot be used as a drop-in replacement of "net/url.URL". The standard Go implementation handles many corner cases and "real life" behaviour of existing systems. The implementation of this package is inspired by "net/url", yet follows more strictly the RFC specifications.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type IRI

type IRI struct {
	Scheme         string
	ForceAuthority bool // append a double-slash ('//') even if Authority is empty
	Authority      string
	Path           string
	ForceQuery     bool // append a query ('?') even if Query is empty
	Query          string
	ForceFragment  bool // append a fragment ('#') even if Fragment field is empty
	Fragment       string
}

An IRI (Internationalized Resource Identifier) is a Unicode string [UNICODE] that conforms to the syntax defined in RFC 3987.

This type is not a "drop-in" replacement for "net/uri.URI". See package comments for details.

See https://www.ietf.org/rfc/rfc3987.html

func NormalizePercentEncoding added in v0.2.0

func NormalizePercentEncoding(iri IRI) (IRI, error)

NormalizePercentEncoding returns an IRI that replaces any unnecessarily percent-escaped characters with unescaped characters.

RFC3987 discusses this normalization procedure in 5.3.2.3: https://www.ietf.org/rfc/rfc3987.html#section-5.3.2.3.

Example
package main

import (
	"fmt"

	"github.com/contomap/iri"
)

func main() {
	value, _ := iri.Parse("https://example.org/dog%20house/%c2%B5")
	result, _ := iri.NormalizePercentEncoding(value)
	fmt.Printf("%s", result.Path)
}
Output:
/dog%20house/µ

func Parse

func Parse(s string) (IRI, error)

Parse parses a string into an IRI and checks that it conforms to RFC 3987.

It performs a coarse segmentation based on a regular expression to separate the components, and then verifies with detailed regular expressions whether the components are correct. Finally, any percent-encoding is verified - yet the returned IRI will have the original percent encoding maintained. If any of these steps produce an error, this function returns an error and an empty IRI.

Example (Empty)
package main

import (
	"fmt"

	"github.com/contomap/iri"
)

func main() {
	value, _ := iri.Parse("")
	fmt.Printf("%#v", value)
}
Output:
iri.IRI{Scheme:"", ForceAuthority:false, Authority:"", Path:"", ForceQuery:false, Query:"", ForceFragment:false, Fragment:""}
Example (EmptyComponents)
package main

import (
	"fmt"

	"github.com/contomap/iri"
)

func main() {
	value, _ := iri.Parse("//?#")
	fmt.Printf("%#v", value)
}
Output:
iri.IRI{Scheme:"", ForceAuthority:true, Authority:"", Path:"", ForceQuery:true, Query:"", ForceFragment:true, Fragment:""}
Example (Https)
package main

import (
	"fmt"

	"github.com/contomap/iri"
)

func main() {
	value, _ := iri.Parse("https://user@example.com/µ/path?q=€#frag1")
	fmt.Printf("%#v", value)
}
Output:
iri.IRI{Scheme:"https", ForceAuthority:false, Authority:"user@example.com", Path:"/µ/path", ForceQuery:false, Query:"q=€", ForceFragment:false, Fragment:"frag1"}
Example (Mailto)
package main

import (
	"fmt"

	"github.com/contomap/iri"
)

func main() {
	value, _ := iri.Parse("mailto:user@example.com")
	fmt.Printf("%#v", value)
}
Output:
iri.IRI{Scheme:"mailto", ForceAuthority:false, Authority:"", Path:"user@example.com", ForceQuery:false, Query:"", ForceFragment:false, Fragment:""}

func (IRI) ResolveReference

func (iri IRI) ResolveReference(other IRI) IRI

ResolveReference resolves an IRI reference to an absolute IRI from an absolute base IRI, per RFC 3986 Section 5.2. The IRI reference may be relative or absolute.

Example
package main

import (
	"fmt"

	"github.com/contomap/iri"
)

func main() {
	base, _ := iri.Parse("https://example.com/sub/path/µ?q=1#frag1")
	fmt.Printf("%s\n", base.ResolveReference(iri.IRI{Fragment: "frag2"}))
	fmt.Printf("%s\n", base.ResolveReference(iri.IRI{Path: ".."}))
	fmt.Printf("%s\n", base.ResolveReference(iri.IRI{}))
}
Output:
https://example.com/sub/path/µ?q=1#frag2
https://example.com/sub/
https://example.com/sub/path/µ?q=1

func (IRI) String

func (iri IRI) String() string

String reassembles the IRI into an IRI string. Any components that have been manually set must comply to the format; This function performs no further escaping.

Example (Common)
package main

import (
	"fmt"

	"github.com/contomap/iri"
)

func main() {
	value := iri.IRI{Scheme: "https", ForceAuthority: false, Authority: "user@example.com", Path: "/sub/path", ForceQuery: false, Query: "q=1", ForceFragment: false, Fragment: "frag1"}
	fmt.Printf("%s", value)
}
Output:
https://user@example.com/sub/path?q=1#frag1
Example (Empty)
package main

import (
	"fmt"

	"github.com/contomap/iri"
)

func main() {
	var value iri.IRI
	fmt.Printf("'%s'", value)
}
Output:
''
Example (EmptyComponents)
package main

import (
	"fmt"

	"github.com/contomap/iri"
)

func main() {
	value := iri.IRI{ForceAuthority: true, ForceQuery: true, ForceFragment: true}
	fmt.Printf("%s", value)
}
Output:
//?#

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL