Fediverse-Enhancement-Proposal/feps/fep-6606.md -rw-r--r-- 7.3 KiB
fe2f26ebMarius Orcsik Adding first elements of how to use the query params in collection filtering 3 months ago

#authors: Marius Orcsik marius@federated.id status: DRAFT dateReceived:

#FEP-6606: ActivityPub client to server collections addressing conventions


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.


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:

// resources matching exactly "value"

// resources matching exactly "1" or "2"

// resources inversly matching "value1"

// resources inversly matching "1" and "2"

// resources fuzzy matching "fuzzy"

// resources fuzzy matching "one" or "two"

// resources matching empty element values

// resources matching all non empty element values

#Applicability for ActivityPub IRIs

We will define how we are going to apply this new defined schema for URL query paramters to ActivityPub collections.

We will assume an ActivityPub collection base IRI follows the following pattern:


Where example.com is the host of the ActivityPub service, ActorName is an identifier for an actor on this service, and outbox identifies the collection we want to load.

The response to a GET request to this IRI could return something like:

    "@context": "https://www.w3.org/ns/activitystreams",
    "id": "https://example.com/ActorName/outbox",
    "type": "OrderedCollection",
    "updated": "2021-04-09T08:16:05Z",
    "first": "https://example.com/ActorName/outbox?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 key names corresponding to the different property names of a valid ActivityPub object.



// will return only activities with the type `Delete` that exist in the
// ActorName's `outbox` collection


// will return only activities containing a summary property that contains
// the "test example" text.

#Starting assumptions

#Objects collections:

An objects collection represents any collection that contains only ActivityPub Objects. The ActivityPub specification names the following ones as such: following, followers, liked.

#Activities collections:

An activities collection represents any collection that contains only ActivityPub Activities. The ActivityPub spec names the following ones as such: outbox, inbox, likes, shares, replies.

#Addressing grammar

We will start with the assumption that collections are externally addressable:

Eg: https://example.com/~jdoe/outbox

This IRI represents the Outbox collection of the Actor with ID https://example.com/~jdoe.

However this collection oftentimes contains a multitude of types of activities: Create, Update, Like, etc.

If a client wants to represent this collection, it will probably need a method of filtering the contents.

We will be using a simple key, value pair of URL query parameters to let the server know what items we are interested in.


The grammar described in this document represents a simplified version of the mechanism that FedBOX services use for their C2S addressing.


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.