aturi

package module
v0.0.0-...-e990af3 Latest Latest
Warning

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

Go to latest
Published: May 6, 2025 License: MIT Imports: 6 Imported by: 0

README

go-aturi

Package aturi provides tools for working with AT-URIs, for the Go programming language.

AT-URIs are used by the Bluesky network and its AT-protocol, and are defined at: https://atproto.com/specs/at-uri-scheme

Documention

Online documentation, which includes examples, can be found at: http://godoc.org/github.com/reiver/go-aturi

GoDoc

Examples

Here are some examples for using package aturi.

Validation Example

You can validate an AT-URI with code similar to the following:

import "github.com/reiver/go-aturi"

// ...

var atURI string = "at://did:plc:scewmn2pl3oz36mxme2b6czz"

// ...

err := aturi.Validate(atURI)
Split Example

You can split an AT-URI into its components with code similar to the following:

import "github.com/reiver/go-aturi"

// ...

var atURI string = "at://did:plc:scewmn2pl3oz36mxme2b6czz"

// ...

authority, collection, rkey, query, fragment, err := aturi.Split(atURI)

Join Example

You can create a normalized AT-URI with code similar to the following:

import "github.com/reiver/go-aturi"

// ...

var authority  string = "did:plc:scewmn2pl3oz36mxme2b6czz"
var collection string = "com.example.fooBar"
var rkey       string = "wxyz1234"
var query      string = ""
var fragment   string = ""

var atURI string = aturi.Join(authority, collection, rkey, query, fragment)

Import

To import package aturi use import code like the follownig:

import "github.com/reiver/go-aturi"

Installation

To install package aturi do the following:

GOPROXY=direct go get https://github.com/reiver/go-aturi

Author

Package aturi was written by Charles Iliya Krempeaux

See Also

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Join

func Join(authority string, collection string, rkey string, query string, fragment string) string

Join returns the AT-URI made up of the provided 'authority', 'collection', 'rkey', 'query', and 'fragment'.

I.e., you use Join to create an AT-URI.

Join will take care of the various complexities of properly creating a (normalized) AT-URI.

(Most people will set 'query' and 'fragment' to the empty string.)

Join normalizes the 'authority' and 'collection' before joining — by internally calling NormalizeAuthority and NormalizeCollection respectively. So, you do not need to call NormalizeAuthority and NormalizeCollection yourself, before passing the 'authority' and 'collection' to Join.

Join also sanitizes 'authority' before joining — by internally calling SanitizeAuthority.

Example (TypeA)
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var authority string = "did:plc:scewmn2pl3oz36mxme2b6czz"

	uri := aturi.Join(authority, "", "", "", "")

	fmt.Printf("uri: %s\n", uri)

}
Output:
uri: at://did:plc:scewmn2pl3oz36mxme2b6czz
Example (TypeB)
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var authority string = "did:plc:scewmn2pl3oz36mxme2b6czz"
	var collection string = "com.example.foorBar"

	uri := aturi.Join(authority, collection, "", "", "")

	fmt.Printf("uri: %s\n", uri)

}
Output:
uri: at://did:plc:scewmn2pl3oz36mxme2b6czz/com.example.foorBar
Example (TypeC)
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var authority string = "did:plc:scewmn2pl3oz36mxme2b6czz"
	var collection string = "com.example.foorBar"
	var rkey string = "3jui7kd54zh2y"

	uri := aturi.Join(authority, collection, rkey, "", "")

	fmt.Printf("uri: %s\n", uri)

}
Output:
uri: at://did:plc:scewmn2pl3oz36mxme2b6czz/com.example.foorBar/3jui7kd54zh2y

func Normalize

func Normalize(uri string) string

Normalize returns the normalized form of an AT-URI, as defined in: https://atproto.com/specs/at-uri-scheme

Normalize does NOT validate the AT-URI. To validate, call Validate.

An example of a non-normalized AT-URI would be:

at://VIDEO.archive.ORG/COM.Example.fooBar

Normalizing that non-normalized AT-URI would result in:

at://video.archive.org/com.example.fooBar

func NormalizeAuthority

func NormalizeAuthority(value string) string

NormalizeAuthority returns the normalized form of an AT-URI 'authority', as defined in: https://atproto.com/specs/at-uri-scheme

The AT-URI 'authority' (such as "example.com") is part of an AT-URI (such as "at://example.com").

In simple language, you can think of an AT-URI 'authority' as being either an Internet domain-name (ex: "example.com") or a DID (ex: "did:plc:scewmn2pl3oz36mxme2b6czz").

An example of a non-normalized AT-URI 'authority' would be "Example.COM". Normalizing that non-normalized AT-URI 'authority' would result in "example.com".

NormalizeAuthority will leave any potential 'userinfo' in the 'authority' as is.

Note that if you want to normalize a whole AT-URI rather than just an 'authority', then instead use Normalize.

Example
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var authority string = "Example.COM"

	normalizedAuthority := aturi.NormalizeAuthority(authority)

	fmt.Printf("original authority:   %s\n", authority)
	fmt.Printf("normalized authority: %s\n", normalizedAuthority)

}
Output:
original authority:   Example.COM
normalized authority: example.com

func NormalizeCollection

func NormalizeCollection(value string) string

NormalizeCollection returns the normalized form of an AT-URI collection, as defined in: https://atproto.com/specs/at-uri-scheme

An AT-URI collection is an NSID, as defined at: https://atproto.com/specs/nsid

The AT-URI collection (such as "com.example.fooBar") is part of an AT-URI (such as "at://archive.org/com.example.fooBar/123").

An example of a non-normalized AT-URI collection would be "COM.Example.fooBar". Normalizing that non-normalized AT-URI collection would result in "com.example.fooBar".

Note that if you want to normalize a whole AT-URI rather than just a collection, then instead use Normalize.

Example
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var collection string = "COM.Example.fooBar"

	normalizedCollection := aturi.NormalizeCollection(collection)

	fmt.Printf("original collection:   %s\n", collection)
	fmt.Printf("normalized collection: %s\n", normalizedCollection)

}
Output:
original collection:   COM.Example.fooBar
normalized collection: com.example.fooBar

func SanitizeAuthority

func SanitizeAuthority(authority string) string

SanitizeAuthority sanitizes an 'authority'.

(An 'authority' is part of an AT-URI.)

Note that SanitizeAuthority does NOT normalize the 'authority'. To normalize the 'authority' use NormalizeAuthority.

Example
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var authority string = "JoeBlow:Pass123@Example.COM"

	sanitizedAuthority := aturi.SanitizeAuthority(authority)

	fmt.Printf("original authority: %s\n", authority)
	fmt.Printf("sanitized authority:                %s\n", sanitizedAuthority)

}
Output:
original authority: JoeBlow:Pass123@Example.COM
sanitized authority:                Example.COM

func Split

func Split(uri string) (authority string, collection string, rkey string, query string, fragment string, err error)

Split returns the 'authority', 'collection', 'rkey', 'query', and 'fragment' of at AT-URI.

A 'collection' is an NSID (Namespaced Identifier).

For example:

var uri string = "at://did:plc:scewmn2pl3oz36mxme2b6czz/com.example.foorBar/3jui7kd54zh2y"

authority, collection, rkey, query, fragment, err := aturi.Split(uri)
if nil != err {
	return err
}

// authority  == "did:plc:scewmn2pl3oz36mxme2b6czz"
// collection == "com.example.foorBar"
// rkey       == "3jui7kd54zh2y"
// query      == ""
// fragment   == ""

Split does NOT normalize the returned values. If you are not sure whether to use Split or SplitAndNormalize or SplitAndNormalizeAndValidate, use SplitAndNormalizeAndValidate.

Example
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var uri string = "at://did:plc:scewmn2pl3oz36mxme2b6czz/com.example.foorBar/3jui7kd54zh2y"

	authority, collection, rkey, query, fragment, err := aturi.Split(uri)
	if nil != err {
		fmt.Printf("ERROR: problem splitting AT-URI: %s\n", err)
		return
	}

	fmt.Printf("authority:  %q\n", authority)
	fmt.Printf("collection: %q\n", collection)
	fmt.Printf("rkey:       %q\n", rkey)
	fmt.Printf("query:      %q\n", query)
	fmt.Printf("fragment:   %q\n", fragment)

}
Output:
authority:  "did:plc:scewmn2pl3oz36mxme2b6czz"
collection: "com.example.foorBar"
rkey:       "3jui7kd54zh2y"
query:      ""
fragment:   ""

func SplitAndNormalize

func SplitAndNormalize(uri string) (authority string, collection string, rkey string, query string, fragment string, err error)

SplitAndNormalize returns the 'authority', 'collection', 'rkey', 'query', and 'fragment' of at AT-URI.

A 'collection' is an NSID (Namespaced Identifier).

For example:

var uri string = "at://did:plc:scewmn2pl3oz36mxme2b6czz/com.example.foorBar/3jui7kd54zh2y"

authority, collection, rkey, query, fragment, err := aturi.SplitAndNormalize(uri)
if nil != err {
	return err
}

// authority  == "did:plc:scewmn2pl3oz36mxme2b6czz"
// collection == "com.example.foorBar"
// rkey       == "3jui7kd54zh2y"
// query      == ""
// fragment   == ""

SplitAndNormalize normalizes the returned values. If you are not sure whether to use Split or SpliAndNormalize or SplitAndNormalizeAndValidate, use SplitAndNormalizeAndValidate.

func SplitAndNormalizeAndValidate

func SplitAndNormalizeAndValidate(uri string) (authority string, collection string, rkey string, query string, fragment string, err error)

SplitAndNormalizeAndValidate returns the 'authority', 'collection', 'rkey', 'query', and 'fragment' of at AT-URI.

A 'collection' is an NSID (Namespaced Identifier).

For example:

var uri string = "at://did:plc:scewmn2pl3oz36mxme2b6czz/com.example.foorBar/3jui7kd54zh2y"

authority, collection, rkey, query, fragment, err := aturi.SplitAndNormalizeAndValidate(uri)
if nil != err {
	return err
}

// authority  == "did:plc:scewmn2pl3oz36mxme2b6czz"
// collection == "com.example.foorBar"
// rkey       == "3jui7kd54zh2y"
// query      == ""
// fragment   == ""

SplitAndNormalize normalizes the returned values. SplitAndNormalizeAndValidate also validates, and returns an error if it fails.

If you are not sure whether to use Split or [SpliAndNormalize] or SplitAndNormalizeAndValidate, use SplitAndNormalizeAndValidate.

func Validate

func Validate(uri string) error

Validate returns an error if the AT-URI is invalid. It returns nil if the AT-URI is valid.

The validation rules for an AT-URI are defined here: https://atproto.com/specs/at-uri-scheme

To validate a potential AT-URI more liberally, use one of the following: ValidateGenerically, ValidatePrefix, ValidateScheme.

To validate only the 'authority' and NOT the whole AT-URI, use NormalizeAuthority.

To validate only the 'collection' and NOT the whole AT-URI, use NormalizeCollection.

Example
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var atURI string = "at://archive.org/COM.Example.fooBar/3jui7kd54zh2y"

	err := aturi.Validate(atURI)

	fmt.Printf("AT-URI: %s\n", atURI)
	fmt.Printf("validation error: %s\n", err)

}
Output:
AT-URI: at://archive.org/COM.Example.fooBar/3jui7kd54zh2y
validation error: aturi: AT-URI "at://archive.org/COM.Example.fooBar/3jui7kd54zh2y" has a collection "COM.Example.fooBar" that is not a valid NSID: nsid: character №0 ('C') (U+0043) of domain-authority part №0 ("COM") of domain-authority ("COM.Example") of nsid ("COM.Example.fooBar") is not a digit ('0'-'9'), lower-case letter ('a'-'z'), or a hyphen ('-')

func ValidateAuthority

func ValidateAuthority(authority string) error

ValidateAuthority returns an error if the AT-URI 'authority' is invalid. It returns nil if the AT-URI authority is valid.

NOTE THAT THIS IS NOT VALIDATING AN AT-URI, BUT IS INSTEAD VALIDATING AN AT-URI 'authority'.

The validation rules for an AT-URI are defined here: https://atproto.com/specs/at-uri-scheme

Example
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var authority string = "user:pass@archive.org"

	err := aturi.ValidateAuthority(authority)

	fmt.Printf("authority: %s\n", authority)
	fmt.Printf("validation error: %s\n", err)

}
Output:
authority: user:pass@archive.org
validation error: aturi: authority may not have an "@" in it

func ValidateCollection

func ValidateCollection(collection string) error

ValidateCollection returns an error if the AT-URI 'collection' is invalid. It returns nil if the AT-URI collection is valid.

NOTE THAT THIS IS NOT VALIDATING AN AT-URI, BUT IS INSTEAD VALIDATING AN AT-URI 'collection'.

The validation rules for an AT-URI are defined here: https://atproto.com/specs/at-uri-scheme

An AT-URI 'collection' must be an NSID, and its validation rules are defined at: https://atproto.com/specs/nsid

Example
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var collection string = "COM.Example.fooBar"

	err := aturi.ValidateCollection(collection)

	fmt.Printf("collection (i.e., NSID): %s\n", collection)
	fmt.Printf("validation error: %s\n", err)

}
Output:
collection (i.e., NSID): COM.Example.fooBar
validation error: nsid: character №0 ('C') (U+0043) of domain-authority part №0 ("COM") of domain-authority ("COM.Example") of nsid ("COM.Example.fooBar") is not a digit ('0'-'9'), lower-case letter ('a'-'z'), or a hyphen ('-')

func ValidateGenerically

func ValidateGenerically(uri string) error

ValidateGenerically only validates an AT-URI very generically.

So, it checks to see if the URI starts with "at://", and make sure that the AT-URI is not more than 8192 bytes long (i.e., 8 kilobytes long). And, that is it.

You would use ValidateGenerically if you wanted to be very liberal in what you accept as a valid AT-URI, while still enforcing the length limit.

ValidateGenerically calls ValidatePrefix internally.

For a more thorough validation of the whole AT-URI instead use Validate.

func ValidatePrefix

func ValidatePrefix(uri string) error

ValidatePrefix only validates the prefix (i.e., "at://") of a potential AT-URI.

So, it checks to see if the URI starts with "at://". And, that is it.

You would use ValidatePrefix if you wanted to be very liberal in what you accept as a valid AT-URI, including accepting an empty 'authority'. I.e., this does a bit more than ValidatePrefix.

ValidatePrefix calls ValidateScheme internally.

For a more thorough validation of the whole AT-URI instead use Validate.

Alternatively, to validate a bit more than ValidatePrefix, without being as thorough as Validate, instead use ValidateGenerically.

Example
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var uri string = "at:example.com"

	err := aturi.ValidatePrefix(uri)

	fmt.Printf("error: %s\n", err)

}
Output:
error: aturi: AT-URI "at:example.com" is not valid because it does not have "//" after "at:"

func ValidateScheme

func ValidateScheme(uri string) error

ValidateScheme only validates the scheme of a potential AT-URI.

So, it checks to see if the URI starts with "at:". And, that is it.

You would use ValidateScheme if you wanted to be very liberal in what you accept as a valid AT-URI, including not caring if the AT-URI has an 'authority' or not. I.e., this is the minimum amount of validation you can do to validate an AT-URI.

Note that you are passing ValidateScheme the whole URI, and not just the scheme.

For a more thorough validation of the whole AT-URI instead use Validate.

Alternatively, to validate a bit more than ValidateScheme, without being as thorough as Validate, instead use ValidatePrefix.

Example
package main

import (
	"fmt"

	"github.com/reiver/go-aturi"
)

func main() {

	var uri string = "http://example.com/once/twice/thrice/fource.html"

	err := aturi.ValidateScheme(uri)

	fmt.Printf("error: %s\n", err)

}
Output:
error: aturi: URI "http://example.com/once/twice/thrice/fource.html" is not an AT-URI because it does not begin with "at:"

Types

This section is empty.

Jump to

Keyboard shortcuts

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