FEP-6606: ActivityPub client to server collections addressing conventions
Summary
This document tries to describe a simple set of conventions to better enable the adressing of [ActivityPub] objects on servers that support [Client to Server Interactions]. Its main purpose is to formalize a basic vocabulary for defining subsets of IRIs [RFC-3987] for collections in a way that can be generalized to both servers and clients. It builds upon the definition of query parametrs [RFC-3986], by introducing a set of additional operators that can be applied to values.
What we are trying to solve
The main reason that is often cited as making client to server interactions problematic is that the official specification leaves too much to the implementors' discretion. The fact that there is no proscribed method of filtering collections content is one of the stop gaps that prevents a wider adoption of C2S in services and clients.
Syntax
The following syntax is extracted form RFC-3986 section 3.4, and it formalizes the URL query parameters as representing any string that conforms to the restrictions below between the first "?" character and the end of the URL or a "#" character marking the start of the fragment part of the URL.
query = *( pchar / "/" / "?" )
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
As we can see this is not formal definition of the query string as a group of key and value pairs, but for our intended use, this is paramount.
So we will take this extra step ourselves and extend the definition to be:
query = *( query-pair [ qconcat ] )
query-pair = pname [ "=" ( pvalue ) ]
pname = 1*( pchar )
pvalue = *( pchar )
pchar = unreserved / pct-encoded / new-delims / ":" / "@"
qconcat = "&"
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
new-delims = "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / ";"
To allow for the operators that we want to append to the query values we extend this version with the following elements:
query-pair = p-name [ "=" ( [ p-operator ] p-value ) ]
p-operator = "!" / "~"
p-value = empty-value / *( pchar )
empty-value = "-"
The operator symbols are "!" and "~" that correspond to negation respectively fuzzy matching of the query value.
Explicitly, when encountering a URL parameter value that has a "!" symbol in front of it we mean it as "different than". Similarly when encountering a value prepended with the "~" symbol, we mean it as "similar with" in a textual manner.
Additionally we added a nil value symbol "-" that can be used for operations where the value to compare against is absent.
Please look at the following examples to see how these rules apply and compound with one another:
?element=value
// resources matching exactly "value"
?element=1&element=2
// resources matching exactly "1" or "2"
?element=!value1
// resources inversly matching "value1"
?element=!1&element=!2
// resources inversly matching "1" and "2"
?element=~fuzzy
// resources fuzzy matching "fuzzy"
?element=~one&element=~two
// resources fuzzy matching "one" or "two"
?element=-
// resources matching empty element values
?element=!-
// resources matching all non empty element values
Applicability for ActivityPub Collections
In this ection we will define how we are going to apply this newly defined schema to use URL query parameters to filter ActivityPub collections.
We will assume a random ActvityPub collection can be found at the folowing URL:
https://example.com/random-collection
The response to a GET request to this IRI could return something like:
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.com/random-collection",
"name": "Random Collection",
"type": "OrderedCollection",
"updated": "2021-04-09T08:16:05Z",
"first": "https://example.com/random-collection?maxItems=10",
"totalItems": 12,
"orderedItems": [ /* skipping items for brevity */ ]
}
The filtering for the elements in the collection will be done by using URL query parameters with the names corresponding to the different properties that we want to filter on for the objects in the collection.
Example:
https://example.com/random-collection?type=Place
// will return only objects with the type `Place` that exist in the
// Random Collection.
https://example.com/random-collection?summary=~test%20example
// will return only objects containing a summary property that contains
// the "test example" text.
実装
The grammar described in this document represents a simplified version of the mechanism that services using the [GoActivityPub] library use for their C2S addressing.
参考文献
- [RFC-3987] M. Duerst, M. Suignard Internationalized Resource Identifiers, 2005
- [RFC-3986] T. Berners-Lee Query component of URIs, 2005
- [ActivityPub] Christine Lemmer Webber, Jessica Tallon, ActivityPub, 2018
- [Client to Server Interactions] Christine Lemmer Webber, Jessica Tallon, ActivityPub, 2018
- [RFC-2119] S. Bradner, Key words for use in RFCs to Indicate Requirement Levels
- [GoActivityPub] M. Orcsik, Github
Copyright
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
To the extent possible under law, the authors of this Fediverse Enhancement Proposal have waived all copyright and related or neighboring rights to this work.