---
title: "Protocol changes"
date: 2022-05-17T08:46:00+01:00
weight: 30
geekdocRepo: https://github.com/owncloud/ocis
geekdocEditPath: edit/master/docs/architecture
geekdocFilePath: protocol-changes.md
---
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.
## Space discovery
{{}}
%%{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
{{}}
### New /dav/spaces/{spaceid} endpoint with spaceid and a relative path
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
{{}}
### Old /dav/files/{username} endpoint with username and a path relative to the users home
**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
{{}}