Protocol changes
The spaces concept allows clients to look up the space endpoints a user has access to and then do individual sync discoveries. Technically, we introduce an indirection that allows clients to rely on server provided URLs instead of hardcoded /webdav or /dav/files/{username} paths, that may change over time.
%%{init: {"sequence": { "showSequenceNumbers":true, "messageFontFamily":"courier", "messageFontWeight":"normal", "messageFontSize":"11"}}}%%
%% font weight is a css bug: https://github.com/mermaid-js/mermaid/issues/1976
%% edit this diagram by pasting it into eg. https://mermaid.live
sequenceDiagram
participant Client
participant Graph
participant SpaceA
participant SpaceB
links Client: {"web": "https://owncloud.dev/clients/web/", "RClone": "https://owncloud.dev/clients/rclone/"}
link Graph: Documentation @ https://owncloud.dev/extensions/graph/
Note left of Client: First, a clients looks
up the spaces a user has access to
opt space lookup
Client->>+Graph: GET /me/drives
Graph-->>-Client: 200 OK JSON list of spaces, say A, B and C,
each with a dedicated webDavURL, etag and quota
end
Note left of Client: Then it can do a parallel
sync discovery on spaces
whose etag changed
par Client to Space A
Client->>+SpaceA: PROPFIND {webDavURL for Space A}
SpaceA-->>-Client: 207 Multistatus PROPFIND response
and Client to Space B
Client->>+SpaceB: PROPFIND {webDavURL for space B}
SpaceB-->>-Client: 207 Multistatus PROPFIND response
end
The ocDAV service is responsible for translating ownCloud flavoured WebDAV into CS3 API calls.
General view
A PROPFIND finds its way to a storage provider like this:
%%{init: {"sequence": { "showSequenceNumbers":true, "messageFontFamily":"courier", "messageFontWeight":"normal", "messageFontSize":"11"}}}%%
%% font weight is a css bug: https://github.com/mermaid-js/mermaid/issues/1976
%% edit this diagram by pasting it into eg. https://mermaid.live
sequenceDiagram
participant Client
participant ocDAV
participant StorageProvider
Note right of Client: {spaceid} identifies the space
{relative/path} is relative to the space root
Client->>+ocDAV: PROPFIND /dav/space/{spaceid}/{relative/path}
Note right of ocDAV: translate ownCloud flavoured webdav
into CS3 API requests
ocDAV->>+StorageProvider: ListContainer({spaceid}, path: {relative/path})
StorageProvider-->>-ocDAV: []ResourceInfo
ocDAV-->>-Client: 207 Multistatus
While the above is a simplification to get an understanding of what needs to go where, there are several places where sharding can happen.
Proxy can do user based routing
The ocis proxy authenticates requests and can forward requests to different backends, depending on the logged-in user or cookies. For example multiple ocdav services can be configured to shard users based on username or affiliation.
%%{init: {"sequence": { "showSequenceNumbers":true, "messageFontFamily":"courier", "messageFontWeight":"normal", "messageFontSize":"11"}}}%%
%% font weight is a css bug: https://github.com/mermaid-js/mermaid/issues/1976
%% edit this diagram by pasting it into eg. https://mermaid.live
sequenceDiagram
participant Client
participant proxy
participant ocDAV1 as ocDAV [a-k]
participant ocDAV2 as ocDAV [l-z]
Note right of Client: {spaceid} identifies the space
{relative/path} is relative to the space root
Client->>+proxy: PROPFIND /dav/space/{spaceid}/{relative/path}
alt username starting with a-k
proxy->>+ocDAV1: PROPFIND /dav/space/{spaceid}/{relative/path}
Note right of ocDAV1: translate ownCloud flavoured webdav
into CS3 API requests
ocDAV1-->>-Client: 207 Multistatus
else username starting with l-z
proxy->>+ocDAV2: PROPFIND /dav/space/{spaceid}/{relative/path}
ocDAV2-->>-Client: 207 Multistatus
end
Gateway can do path or storage provider id based routing
The reva gateway acts as a facade to multiple storage providers that can be configured with the storage registry:
%%{init: {"sequence": { "showSequenceNumbers":true, "messageFontFamily":"courier", "messageFontWeight":"normal", "messageFontSize":"11"}}}%%
%% font weight is a css bug: https://github.com/mermaid-js/mermaid/issues/1976
%% edit this diagram by pasting it into eg. https://mermaid.live
sequenceDiagram
participant ocDAV
participant Gateway
participant StorageRegistry
participant StorageProvider1 as StorageProvider [a-k]
participant StorageProvider2 as StorageProvider [l-z]
Note right of ocDAV: translate ownCloud flavoured webdav
into CS3 API requests
ocDAV->>+Gateway: ListContainer({spaceid}, path: {relative/path})
Note right of Gateway: find address of the storage provider
that is responsible for the space
Gateway->>+StorageRegistry: ListStorageProviders({spaceid})
StorageRegistry-->>-Gateway: []ProviderInfo
Note right of Gateway: forward request to
correct storage provider
alt username starting with a-k
Gateway->>+StorageProvider1: ListContainer({spaceid}, path: {relative/path})
StorageProvider1-->>-Gateway: []ResourceInfo
else username starting with l-z
Gateway->>+StorageProvider2: ListContainer({spaceid}, path: {relative/path})
StorageProvider2-->>-Gateway: []ResourceInfo
end
Gateway-->>-ocDAV: []ResourceInfo
PROPFIND request against old webdav endpoints
To route a PROPFIND request against the old webdav endpoints like /dav/files/username, ocdav first has to build a CS3 namespace prefix, e.g. /users/{{.Id.OpaqueId}} to the users home.
%%{init: {"sequence": { "showSequenceNumbers":true, "messageFontFamily":"courier", "messageFontWeight":"normal", "messageFontSize":"11"}}}%%
%% font weight is a css bug: https://github.com/mermaid-js/mermaid/issues/1976
%% edit this diagram by pasting it into eg. https://mermaid.live
sequenceDiagram
participant Client
participant ocDAV
participant Gateway
opt old /dav/files/{username} endpoint with username and a path relative to the users home
Note right of Client: translate ownCloud flavoured webdav
into CS3 API requests
Client->>+ocDAV: PROPFIND /dav/files/{username}/{relative/path}
Note right of ocDAV: translate ownCloud flavoured webdav
into CS3 API requests
ocDAV->>+Gateway: GetUser({username})
Gateway-->>-ocDAV: User
Note right of ocDAV: build path prefix to user home
ocDAV->>+ocDAV: {namespace/prefix} = ApplyLayout({path layout}, User), eg. /users/e/einstein
Note right of ocDAV: look up the space responsible for a path
ocDAV->>+Gateway: ListStorageSpaces(path: {namespace/prefix}/{relative/path})
Gateway-->>-ocDAV: []StorageSpace
Note right of ocDAV: make actual request with space and relative path
ocDAV->>+Gateway: ListContainer({spaceid}, path: {relative/path})
Gateway-->>-ocDAV: []ResourceInfo
ocDAV-->>-Client: 207 Multistatus
end
Handling legacy global namespace webdav endpoints
The reason ocis uses a path based lookup instead of looking up the current users home using the user id and a space type filter is, because there are deployments that use a global namespace at the legacy /webdav endpoint. To support these use cases, the gateway allows looking up spaces using their mount path.
%%{init: {"sequence": { "showSequenceNumbers":true, "messageFontFamily":"courier", "messageFontWeight":"normal", "messageFontSize":"11"}}}%%
%% font weight is a css bug: https://github.com/mermaid-js/mermaid/issues/1976
%% edit this diagram by pasting it into eg. https://mermaid.live
sequenceDiagram
participant Client
participant ocDAV
participant Gateway
Note right of Client: translate ownCloud flavoured webdav
into CS3 API requests
alt old /dav/files/{username} endpoint with username and a path relative to the users home
Client->>+ocDAV: PROPFIND /dav/files/{username}/{relative/path}
Note right of ocDAV: look up {username} in URL path
ocDAV->>+Gateway: GetUser({username})
Gateway-->>-ocDAV: User
Note right of ocDAV:build namespace prefix to user home
ocDAV->>+ocDAV: {namespace/prefix} = ApplyLayout({namespace layout}, User), eg. /users/e/einstein
else legacy /webdav/ endpoint with a path relative to the users home
Client->>+ocDAV: PROPFIND /webdav/{relative/path}
Note right of ocDAV: use currently logged in user
ocDAV->>+ocDAV: ContextGetUser()
Note right of ocDAV: build namespace prefix to user home
ocDAV->>+ocDAV: {namespace/prefix} = ApplyLayout({namespace layout}, User), eg. /users/e/einstein
else legacy /webdav/ endpoint with a path relative to a global namespace
Client->>+ocDAV: PROPFIND /webdav/{relative/path}
Note right of ocDAV: omit namespace prefix by using empty layout template
ocDAV->>+ocDAV: {namespace/prefix} = ApplyLayout("/", u), always returns "/"
end
Note right of ocDAV: look up the space responsible for a path
ocDAV->>+Gateway: ListStorageSpaces(path: {namespace/prefix}/{relative/path})
Gateway-->>-ocDAV: []StorageSpace
Note right of ocDAV: make actual request with space and relative path
ocDAV->>+Gateway: ListContainer({spaceid}, path: {relative/path})
Gateway-->>-ocDAV: []ResourceInfo
ocDAV-->>-Client: 207 Multistatus