WebDavClient

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::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::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: &str) -> Result<Uri, Error>

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

path MUST NOT be percent-encoded, except for any reserved characters.

§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<C::Error>>

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 request_raw( &self, request: Request<String>, ) -> Result<(Parts, Bytes), RequestError<C::Error>>

Send a raw request to the server.

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

This is a lower-level API. Prefer using WebDavClient::request with the Requests API instead.

§Errors

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

Source

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

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 request<R>( &self, request: R, ) -> Result<R::Response, R::Error<C::Error>>

Execute a typed DAV request.

Provides a type-safe way to execute WebDAV operations using typed requests and response types. Each request type implements the crate::requests::DavRequest trait, and can therefore:

  • Serialise itself into an HTTP request.
  • Parse the HTTP response into a typed response.
§Example
use libdav::dav::GetEtag;

let response = webdav.request(
    GetEtag::new("/calendar/event.ics")
).await?;

println!("Etag: {}", response.etag);
§Errors

Returns an error if:

  • The request cannot be prepared (e.g., invalid parameters).
  • The HTTP request fails.
  • The response cannot be parsed.

Trait Implementations§

Source§

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

Source§

fn clone(&self) -> WebDavClient<C>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
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>

§

impl<C> !UnwindSafe for WebDavClient<C>

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. 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