Liking cljdoc? Tell your friends :D

dk.simongray.webdav.server

A Ring handler that serves a backend of your own over WebDAV: classes 1 and 2 of RFC 4918, with the conditional requests of RFC 9110 and the Prefer header of RFC 8144.

A backend is a map of functions. Each one takes a path, a vector of decoded segments below the root of the share (see the paths namespace), and can return a promise in ClojureScript:

  • :resource, the resource map of the path, or nil when nothing is there
  • :children, the resource maps of the members of a collection, each with its :name
  • :content, the body of a document, as a string, bytes or (on the JVM) an InputStream
  • :put!, which writes a document and returns its new resource map
  • :mkcol!, which makes a collection
  • :delete!, which deletes a resource and its members
  • :props, the elements of the dead properties of a resource
  • :patch-props!, which applies the operations of a PROPPATCH, all or none
  • :copy! and :move!, which also take the destination path, and :copy! a map of the :depth (0 or :infinity)

Only :resource is required. Without :children the handler won't list a collection, neither for PROPFIND nor as the page of links that a GET of one answers, and without :put!, :mkcol! or :delete! it refuses those methods. Without :copy! and :move! it copies with the other functions, and moves by copying and deleting.

A :put! takes the body and a map of its :content-type. The body is a stream, which fails with a refusal of 413 once more than :max-bytes are read from it, so a backend can write it to a file as it comes, but should read it all before it replaces anything. On the JVM it's an InputStream, and in ClojureScript a ReadableStream. To keep the whole body in memory, read it with body-bytes. For a conditional request, the map also has the :if-etag, the :etag of the resource map that the handler checked (nil when nothing was there), so that a backend that can write conditionally refuses a document that changed since. A :patch-props! takes the operations in order: [:set element] and [:remove name].

The functions that write return nil. When :delete!, :copy! or :move! can't change some members, they can return a map of those paths to a status each, and :patch-props! can return a map of the names it refused to a status each. To refuse a whole request, a function throws an ex-info whose data has the status as :dk.simongray.webdav/status. It can add the names of preconditions as :dk.simongray.webdav/error, which the handler writes as a DAV:error body.

A resource map can have these keys:

  • :collection?, true for a collection
  • :etag, an entity tag or any value to quote as one, e.g. a version
  • :last-modified and :created, instants
  • :content-type, :content-length and :content-language
  • :resource-type, the names of more elements of DAV:resourcetype, e.g. [:cal/calendar]

With :locks, an atom of the lock table, the handler takes LOCK and UNLOCK too (class 2). A write to what a lock covers then has to submit the lock's token in an If header, as the principal that took it. The table is a map of locks by token, which the handler keeps itself, and an expired lock simply stops counting. It lives in memory, since locks last minutes, so several processes that serve one share must share the atom.

A Ring handler that serves a backend of your own over WebDAV: classes 1
and 2 of RFC 4918, with the conditional requests of RFC 9110 and the
Prefer header of RFC 8144.

A backend is a map of functions. Each one takes a path, a vector of
decoded segments below the root of the share (see the paths namespace),
and can return a promise in ClojureScript:

- :resource, the resource map of the path, or nil when nothing is there
- :children, the resource maps of the members of a collection, each
  with its :name
- :content, the body of a document, as a string, bytes or (on the JVM)
  an InputStream
- :put!, which writes a document and returns its new resource map
- :mkcol!, which makes a collection
- :delete!, which deletes a resource and its members
- :props, the elements of the dead properties of a resource
- :patch-props!, which applies the operations of a PROPPATCH, all or
  none
- :copy! and :move!, which also take the destination path, and :copy! a
  map of the :depth (0 or :infinity)

Only :resource is required. Without :children the handler won't list a
collection, neither for PROPFIND nor as the page of links that a GET of
one answers, and without :put!, :mkcol! or :delete! it refuses those
methods. Without :copy! and :move! it copies with the other functions,
and moves by copying and deleting.

A :put! takes the body and a map of its :content-type. The body is a
stream, which fails with a refusal of 413 once more than :max-bytes are
read from it, so a backend can write it to a file as it comes, but
should read it all before it replaces anything. On the JVM it's an
InputStream, and in ClojureScript a ReadableStream. To keep the whole
body in memory, read it with body-bytes. For a conditional request,
the map also has the :if-etag, the :etag of the resource map that the
handler checked (nil when nothing was there), so that a backend that
can write conditionally refuses a document that changed since. A
:patch-props! takes the operations in order: [:set element] and
[:remove name].

The functions that write return nil. When :delete!, :copy! or :move!
can't change some members, they can return a map of those paths to a
status each, and :patch-props! can return a map of the names it refused
to a status each. To refuse a whole request, a function throws an
ex-info whose data has the status as :dk.simongray.webdav/status. It can
add the names of preconditions as :dk.simongray.webdav/error, which the
handler writes as a DAV:error body.

A resource map can have these keys:

- :collection?, true for a collection
- :etag, an entity tag or any value to quote as one, e.g. a version
- :last-modified and :created, instants
- :content-type, :content-length and :content-language
- :resource-type, the names of more elements of DAV:resourcetype, e.g.
  [:cal/calendar]

With :locks, an atom of the lock table, the handler takes LOCK and
UNLOCK too (class 2). A write to what a lock covers then has to submit
the lock's token in an If header, as the principal that took it. The
table is a map of locks by token, which the handler keeps itself, and
an expired lock simply stops counting. It lives in memory, since locks
last minutes, so several processes that serve one share must share the
atom.
raw docstring

body-bytesclj/s

(body-bytes body)

The bytes of the body that :put! takes, read to its end: on the JVM at once, and in ClojureScript a promise. It fails with the refusal of a body past :max-bytes, which the handler then answers.

The bytes of the `body` that :put! takes, read to its end: on the JVM
at once, and in ClojureScript a promise. It fails with the refusal of a
body past :max-bytes, which the handler then answers.
sourceraw docstring

default-optionsclj/s

The default of each option of the handler:

  • :root, the path that the share is served at, /
  • :hosts, the names of the hosts of the share besides those of the Host and X-Forwarded-Host headers, e.g. its public name behind a proxy that rewrites both; a COPY or a MOVE to any other host gets a 502
  • :max-bytes, the most that the body of a PUT can hold, 1 GB
  • :max-xml-bytes, the most that the XML body of a PROPFIND or a PROPPATCH can hold, and the dead properties of a resource as XML, 1 MB
  • :propfind-infinity?, whether PROPFIND answers at depth infinity on a collection, false
  • :namespaces, the aliases of namespaces in property names, from URI to alias, over xml/default-namespaces
  • :live-properties, the live properties of your own, a map from a name to a function of the request, the path and the resource map, which returns the value or nil when the resource has none
  • :compliance, the classes that the DAV header names after 1, e.g. ["calendar-access"]
  • :methods, the methods of your own, a map from a method, e.g. :report, to a function of the context of the request (see handler)
  • :locks, an atom of the lock table for class 2, e.g. (atom {}), or nil for class 1 alone
  • :max-lock-seconds, the longest that a lock lasts before its client refreshes it, an hour, whatever the Timeout header asks for
  • :max-locks, the most live locks that the lock table holds, 10,000
  • :principal, a function of the request that returns who sends it, e.g. the user that your login found, since only the principal that took a lock can use it; by default nobody, so any client can
  • :clock, a function of no arguments that returns the instant now
The default of each option of the handler:

- :root, the path that the share is served at, /
- :hosts, the names of the hosts of the share besides those of the
  Host and X-Forwarded-Host headers, e.g. its public name behind a
  proxy that rewrites both; a COPY or a MOVE to any other host gets a
  502
- :max-bytes, the most that the body of a PUT can hold, 1 GB
- :max-xml-bytes, the most that the XML body of a PROPFIND or a
  PROPPATCH can hold, and the dead properties of a resource as XML,
  1 MB
- :propfind-infinity?, whether PROPFIND answers at depth infinity on a
  collection, false
- :namespaces, the aliases of namespaces in property names, from URI to
  alias, over xml/default-namespaces
- :live-properties, the live properties of your own, a map from a name
  to a function of the request, the path and the resource map, which
  returns the value or nil when the resource has none
- :compliance, the classes that the DAV header names after 1, e.g.
  ["calendar-access"]
- :methods, the methods of your own, a map from a method, e.g. :report,
  to a function of the context of the request (see handler)
- :locks, an atom of the lock table for class 2, e.g. (atom {}), or nil
  for class 1 alone
- :max-lock-seconds, the longest that a lock lasts before its client
  refreshes it, an hour, whatever the Timeout header asks for
- :max-locks, the most live locks that the lock table holds, 10,000
- :principal, a function of the request that returns who sends it, e.g.
  the user that your login found, since only the principal that took a
  lock can use it; by default nobody, so any client can
- :clock, a function of no arguments that returns the instant now
sourceraw docstring

handlerclj/s

(handler backend)
(handler backend opts)

A Ring handler that serves the backend over WebDAV with the opts of default-options. The namespace's docstring describes a backend.

Mount it for the :root and every path below it. It checks no credentials, so mount it behind your login. Windows sends OPTIONS and PROPFIND to / and to each collection above the root before it maps a share, so route those to the handler too, which answers them as for a bare collection.

It takes the arguments of a synchronous and of an asynchronous handler. The body of a request can be a string, bytes or a stream: an InputStream on the JVM, and in ClojureScript a ReadableStream or a Node stream. In ClojureScript the handler returns a promise of the response, whose body is a string or bytes.

A function of :methods gets the context of the request: a map of the :request (with lower-case headers), the :path, the :resource map (nil when nothing is there), the :backend and the :opts. A live property can e.g. give the principal of the user that your login put in the request, for RFC 5397:

(server/handler backend
                {:root            "/dav/"
                 :live-properties {:dav/current-user-principal
                                   (fn [request _ _]
                                     [:dav/href {} (principal-href request)])}})
A Ring handler that serves the `backend` over WebDAV with the `opts` of
default-options. The namespace's docstring describes a backend.

Mount it for the :root and every path below it. It checks no
credentials, so mount it behind your login. Windows sends OPTIONS and
PROPFIND to / and to each collection above the root before it maps a
share, so route those to the handler too, which answers them as for a
bare collection.

It takes the arguments of a synchronous and of an asynchronous handler.
The body of a request can be a string, bytes or a stream: an
InputStream on the JVM, and in ClojureScript a ReadableStream or a Node
stream. In ClojureScript the handler returns a promise of the response,
whose body is a string or bytes.

A function of :methods gets the context of the request: a map of the
:request (with lower-case headers), the :path, the :resource map (nil
when nothing is there), the :backend and the :opts. A live property can
e.g. give the principal of the user that your login put in the request,
for RFC 5397:

    (server/handler backend
                    {:root            "/dav/"
                     :live-properties {:dav/current-user-principal
                                       (fn [request _ _]
                                         [:dav/href {} (principal-href request)])}})
sourceraw docstring

propstatsclj/s

(propstats ctx propfind path resource)

The propstats of the resource at path, whose map is resource, for the propfind, as xml/read-propfind returns it, in the context ctx of a request. A method of your own can use it, e.g. for a REPORT.

The propstats of the resource at `path`, whose map is `resource`, for
the `propfind`, as xml/read-propfind returns it, in the context `ctx`
of a request. A method of your own can use it, e.g. for a REPORT.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close