libdav::dav

Struct WebDavClient

source
pub struct WebDavClient<C>
where C: Service<Request<String>, Response = Response<Incoming>> + Sync + Send + 'static,
{ pub base_url: Uri, /* private fields */ }
Expand description

Generic WebDAV client.

A WebDAV client that uses a parametrised http client C to perform the underlying HTTP requests.

An existing http client that can be used is hyper_util::client::legacy::Client, although any client which implements the trait bounds is acceptable. Essentially an http clients needs to implement tower::Service, taking a Request<Service> as input and returning a Response<Incoming>.

This means that the provided http client can simply be one that wraps around an existing one. These wrappers are called middleware in the Tower/Hyper ecosystem.

The most common and obvious example is one that adds an Authorization header to all outgoing requests:

use http::Uri;
use hyper_rustls::HttpsConnectorBuilder;
use hyper_util::{client::legacy::Client, rt::TokioExecutor};
use tower_http::auth::AddAuthorization;

let uri = Uri::try_from("https://example.com").unwrap();

let https_connector = HttpsConnectorBuilder::new()
    .with_native_roots()
    .unwrap()
    .https_or_http()
    .enable_http1()
    .build();
let http_client = Client::builder(TokioExecutor::new()).build(https_connector);
let auth_client = AddAuthorization::basic(http_client, "user", "secret");
let webdav = WebDavClient::new(uri, auth_client);

The concrete type of the client in the above example is somewhat complex. For this reason, application code will usually want to use an alias for the concrete type being used, and use this alias through all types and functions that handle the WebDAV client:

type MyClient = WebDavClient<AddAuthorization<Client<HttpsConnector<HttpConnector>, String>>>;

§Setting a custom User-Agent header

The following example uses a custom middleware which sets a specific User-Agent on each outgoing request:

use std::task::{Context, Poll};

use hyper::{
    header::{HeaderValue, USER_AGENT},
    Request, Response,
};
use tower::Service;

#[derive(Debug, Clone)]
pub struct UserAgent<S> {
    inner: S,
    user_agent: HeaderValue,
}

impl<S> UserAgent<S> {
    /// Add a custom User-Agent to outgoing requests.
    pub fn new(inner: S, user_agent: HeaderValue) -> UserAgent<S> {
        UserAgent { inner, user_agent }
    }
}

impl<S, Tx, Rx> Service<Request<Tx>> for UserAgent<S>
where
    S: Service<Request<Tx>, Response = Response<Rx>>,
{
    type Response = S::Response;
    type Error = S::Error;
    type Future = S::Future;

    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.inner.poll_ready(cx)
    }

    fn call(&mut self, mut req: Request<Tx>) -> Self::Future {
        req.headers_mut()
            .insert(USER_AGENT, self.user_agent.clone());
        self.inner.call(req)
    }
}

// Elsewhere in your codebase...
use http::Uri;
use hyper_rustls::HttpsConnectorBuilder;
use hyper_util::{client::legacy::Client, rt::TokioExecutor};
use tower_http::auth::AddAuthorization;

let uri = Uri::try_from("https://example.com").unwrap();

let https_connector = HttpsConnectorBuilder::new()
    .with_native_roots()
    .unwrap()
    .https_or_http()
    .enable_http1()
    .build();
let http_client = Client::builder(TokioExecutor::new()).build(https_connector);
let auth_client = UserAgent::new(http_client, "myapp/0.2.7".try_into().unwrap());
let webdav = WebDavClient::new(uri, auth_client);

For other generic middleware of this style, consult the tower-http crate.

Fields§

§base_url: Uri

Base URL to be used for all requests.

This is composed of the domain+port used for the server, plus the context path where WebDAV requests are served.

Implementations§

source§

impl<C> WebDavClient<C>
where C: Service<Request<String>, Response = Response<Incoming>> + Sync + Send, <C as Service<Request<String>>>::Error: Error + Send + Sync,

source

pub fn new(base_url: Uri, http_client: C) -> WebDavClient<C>

Builds a new WebDAV client.

source

pub fn base_url(&self) -> &Uri

Returns a URL pointing to the server’s context path.

source

pub fn relative_uri(&self, path: impl AsRef<str>) -> Result<Uri, Error>

Returns a new URI relative to the server’s root.

§Errors

If this client’s base_url is invalid or the provided path is not an acceptable path.

source

pub async fn find_current_user_principal( &self, ) -> Result<Option<Uri>, FindCurrentUserPrincipalError>

Resolves the current user’s principal resource.

First queries the base_url, then the root path on the same host.

Returns None if the response’s status code is 404 or if no principal was found.

§Errors

See FindCurrentUserPrincipalError

§See also

The DAV:current-user-principal property is defined in https://www.rfc-editor.org/rfc/rfc5397#section-3

source

pub async fn propfind( &self, url: &Uri, properties: &[&PropertyName<'_, '_>], depth: u8, ) -> Result<(Parts, Bytes), WebDavError>

Sends a PROPFIND request.

This is a shortcut for simple PROPFIND requests.

§Errors

If there are any network errors.

source

pub async fn request( &self, request: Request<String>, ) -> Result<(Parts, Bytes), RequestError>

Send a request to the server.

Sends a request, applying any necessary authentication and logging the response.

§Errors

Returns an error if the underlying http request fails or if streaming the response fails.

source

pub async fn get_property( &self, href: &str, property: &PropertyName<'_, '_>, ) -> Result<Option<String>, WebDavError>

Fetch a single property.

§Common properties
§Quirks

The namespace of the value in the response from the server is ignored. This is a workaround for an issue in cyrus-imapd.

§Errors
  • If there are any network errors or the response could not be parsed.
  • If the requested property is missing in the response.
§See also
source

pub async fn get_properties<'ptr, 'p>( &self, href: &str, properties: &[&'ptr PropertyName<'p, 'p>], ) -> Result<Vec<(&'ptr PropertyName<'p, 'p>, Option<String>)>, WebDavError>

Fetch multiple properties for a single resource.

Values in the returned Vec are in the same order as the properties parameter.

§Quirks

Same as WebDavClient::get_property.

§Errors
  • If there are any network errors or the response could not be parsed.
  • If the requested property is missing in the response.
§See also
source

pub async fn set_property( &self, href: &str, property: &PropertyName<'_, '_>, value: Option<&str>, ) -> Result<Option<String>, WebDavError>

Sends a PROPUPDATE query to the server.

Setting the value to None will remove the property. Returns the new value as returned by the server.

§Quirks

Same as WebDavClient::get_property.

§Errors

If there are any network errors or the response could not be parsed.

§See also
source

pub async fn find_context_path( &self, service: DiscoverableService, host: &str, port: u16, ) -> Result<Option<Uri>, ResolveContextPathError>

Resolve the default context path using a well-known path.

This only applies for servers supporting WebDAV extensions like CalDAV or CardDAV. Returns Ok(None) if the well-known path does not redirect to another location.

§Errors
  • If the provided scheme, host and port cannot be used to construct a valid URL.
  • If there are any network errors.
  • If the response is not an HTTP redirection.
  • If the Location header in the response is missing or invalid.
§See also
source

pub async fn list_resources( &self, collection_href: &str, ) -> Result<Vec<ListedResource>, WebDavError>

Enumerates resources in a collection

§Errors

If there are any network errors or the response could not be parsed.

source

pub async fn create_resource( &self, href: impl AsRef<str>, data: Vec<u8>, mime_type: impl AsRef<[u8]>, ) -> Result<Option<String>, WebDavError>

Creates a new resource

Returns an Etag if present in the response. If the Etag is not included, it must be requested in a follow-up request, and cannot be obtained race-free.

§Errors

If there are any network errors or the response could not be parsed.

source

pub async fn update_resource( &self, href: impl AsRef<str>, data: Vec<u8>, etag: impl AsRef<str>, mime_type: impl AsRef<[u8]>, ) -> Result<Option<String>, WebDavError>

Updates an existing resource

Returns an Etag if present in the response. If the Etag is not included, it must be requested in a follow-up request, and cannot be obtained race-free.

§Errors

If there are any network errors or the response could not be parsed.

source

pub async fn create_collection( &self, href: impl AsRef<str>, resourcetypes: &[&PropertyName<'_, '_>], ) -> Result<(), WebDavError>

Creates a collection under path href.

This function executes an Extended MKCOL.

Additional resource types may be specified via the resourcetypes argument. The DAV:collection resource type is implied and MUST NOT be specified.

§Errors

If there are any network errors or the response could not be parsed.

source

pub async fn delete( &self, href: impl AsRef<str>, etag: impl AsRef<str>, ) -> Result<(), WebDavError>

Deletes the resource at href.

The resource MAY be a collection. Because the implementation for deleting resources and collections is identical, this same function is used for both cases.

If the Etag does not match (i.e.: if the resource has been altered), the operation will fail and return an Error.

§Errors

If there are any network errors or the response could not be parsed.

source

pub async fn force_delete( &self, href: impl AsRef<str>, ) -> Result<(), WebDavError>

Force deletion of the resource at href.

This function does not guarantee that a resource or collection has not been modified since it was last read. Use this function with care.

The resource MAY be a collection. Because the implementation for deleting resources and collections is identical, this same function covers both cases.

§Errors

If there are any network errors or the response could not be parsed.

Trait Implementations§

source§

impl<C> Debug for WebDavClient<C>
where C: Service<Request<String>, Response = Response<Incoming>> + Sync + Send + 'static + Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<C> !Freeze for WebDavClient<C>

§

impl<C> !RefUnwindSafe for WebDavClient<C>

§

impl<C> Send for WebDavClient<C>

§

impl<C> Sync for WebDavClient<C>

§

impl<C> Unpin for WebDavClient<C>
where C: Unpin,

§

impl<C> UnwindSafe for WebDavClient<C>
where C: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<Source, Target> OctetsInto<Target> for Source
where Target: OctetsFrom<Source>,

source§

type Error = <Target as OctetsFrom<Source>>::Error

source§

fn try_octets_into( self, ) -> Result<Target, <Source as OctetsInto<Target>>::Error>

Performs the conversion.
source§

fn octets_into(self) -> Target
where Self::Error: Into<Infallible>,

Performs an infallible conversion.
source§

impl<T> Pointable for T

source§

const ALIGN: usize = _

The alignment of pointer.
source§

type Init = T

The type for initializers.
source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more