Struct Resource

Source
pub struct Resource { /* private fields */ }
Expand description

Representation of the web resource that corresponds to the path segment component of the URI.

Implementations§

Source§

impl Resource

Source

pub fn new<P>(uri_pattern: P) -> Resource
where P: AsRef<str>,

Creates a new Resource that corresponds to the last path segment component of the given URI pattern.

Other components of the URI pattern (host and prefix path segments) will be used to find the resource’s place in the resource tree when it’s being added to another resource.

use argan::Resource;

let mut root = Resource::new("/");
let resource_2 = Resource::new("/resource_1/resource_2");

// When we add `resource_2` to the root, it won't be a direct child of the root.
// Instead, it will be added under `/resource_1`.
root.add_subresource(resource_2);
Source

pub fn host_is<P: AsRef<str>>(&self, host_pattern: P) -> bool

Retuns true if the given host pattern is the one the resource was created with.

use argan::Resource;

let resource_2 = Resource::new("http://example.com/resource_1/resource_2");
assert!(resource_2.host_is("http://example.com"));
assert!(resource_2.host_is("example.com"));
Source

pub fn is<P: AsRef<str>>(&self, pattern: P) -> bool

Retuns true if the given pattern is the resource’s pattern.

use argan::Resource;

let resource_2 = Resource::new("http://example.com/resource_1/resource_2");
assert!(resource_2.is("/resource_2"));
assert!(resource_2.is("resource_2"));
Source

pub fn add_subresource<R, const N: usize>(&mut self, new_resources: R)
where R: IntoArray<Resource, N>,

Adds the given resources to the current resource’s subtree.

use argan::Resource;

let mut resource_2 = Resource::new("/resource_1/resource_2");
let resource_3_0 = Resource::new("/resource_3_0");
let resource_4 = Resource::new("/resource_1/resource_2/resource_3_1/resource_4");

resource_2.add_subresource([resource_3_0, resource_4]);
§Panics
  • if the resource being added is a root resource
use argan::Resource;

let mut parent = Resource::new("/parent");
let root = Resource::new("/");

parent.add_subresource(root);
  • if the current resource’s URI doesn’t match the host and/or prefix path segments of the given resource
use argan::Resource;

let mut resource_2 = Resource::new("/resource_1/resource_2");

// resource_3 is supposed to belong to a host `example.com`.
let resource_3 = Resource::new("http://example.com/resource_1/resource_2/resource_3");

resource_2.add_subresource(resource_3);
  • if the resource or one of its subresources has a duplicate in the current resources’s subtree and both of them have some handler set or a middleware applied
use argan::{Resource, handler::HandlerSetter, http::Method};

let mut resource_1 = Resource::new("/resource_1");
let mut resource_3 = Resource::new("/resource_2/resource_3");
resource_3.set_handler_for(Method::GET.to(|| async {}));

resource_1.add_subresource(resource_3);

let mut resource_2 = Resource::new("/resource_2");
let mut resource_3 = Resource::new("/resource_3");
resource_3.set_handler_for(Method::POST.to(|| async {}));

resource_2.add_subresource(resource_3);

// This doesn't try to merge the handler sets of the duplicate resources.
resource_1.add_subresource(resource_2);
Source

pub fn add_subresource_under<P, R, const N: usize>( &mut self, relative_path_pattern: P, new_resources: R, )
where P: AsRef<str>, R: IntoArray<Resource, N>,

Adds the given resources under the prefix path segments relative to the current resource.

use argan::Resource;

let mut resource_1 = Resource::new("/resource_1");
let resource_3 = Resource::new("/resource_3");

resource_1.add_subresource_under("/resource_2", resource_3);

When a new resource has prefix URI components, it’s better to use add_subresource(). But the following also works:

let resource_4 = Resource::new("/resource_1/resource_2/resource_3/resource_4");

// Note that resource_1 may or may not have an existing subresource resource_2.
resource_1.add_subresource_under("/resource_2", resource_4);
§Panics
  • if the new resource’s URI components don’t match the current resource’s URI components and/or the given releative path pattern, respectively
use argan::Resource;

let mut resource_1 = Resource::new("/resource_1");
let resource_4 = Resource::new("/resource_1/resource_2/resource_3/resource_4");

resource_1.add_subresource_under("/some_resource", resource_4);

Other panic conditions are the same as add_subresource()’s conditions.

Source

pub fn subresource_mut<P>(&mut self, relative_path: P) -> &mut Resource
where P: AsRef<str>,

Returns the resource at the given relative path. If the resource doesn’t exist, it will be created.

The path is relative to the resource the method is called on.

use argan::Resource;

let mut resource_1 = Resource::new("/resource_1");
let resource_3 = resource_1.subresource_mut("/resource_2/resource_3");
§Panics
  • if the given path is empty
  • if the path contains only a slash / (root cannot be a subresource)
  • if the path doesn’t start with a slash /
  • if the resource has some handler set or middleware applied, and the given configuration symbols don’t match its configuration
use argan::{Resource, handler::HandlerSetter, http::Method};

let mut root = Resource::new("/");
root.subresource_mut("/resource_1 !*").set_handler_for([
  Method::GET.to(|| async {}),
  Method::POST.to(|| async {}),
]);

// ...

let resource_1 = root.subresource_mut("/resource_1");

For configuration symbols, see the crate documentation;

Source

pub fn set_extension<E: Clone + Send + Sync + 'static>(&mut self, extension: E)

Sets the given extension to the Resource. The extension is available to all handlers of the Resource and to all middleware that wraps these handlers in the NodeExtension field of the Args.

§Panics
  • if the Resource already has an extension set
Source

pub fn set_handler_for<H, const N: usize>(&mut self, handler_kinds: H)
where H: IntoArray<HandlerKind, N>,

Sets the method and mistargeted request handlers of the resource.

use argan::{Resource, handler::HandlerSetter, http::{Method, CustomMethod}};

let mut root = Resource::new("/");
root.set_handler_for(Method::GET.to(|| async {}));
root.subresource_mut("/resource_1/resource_2").set_handler_for([
  Method::GET.to(|| async {}),
  CustomMethod("LOCK").to(|| async {}),
]);
Source

pub fn wrap<L, const N: usize>(&mut self, layer_targets: L)
where L: IntoArray<LayerTarget<Self>, N>,

Adds middleware to be applied on the resource’s components, like request receiver, passer, and method and other kind of handlers.

Middlewares are applied when the resource is being converted into a service.

use argan::prelude::*;
use tower_http::compression::CompressionLayer;

#[derive(Clone)]
struct MiddlewareLayer;

impl<H> Layer<H> for MiddlewareLayer
where
  H: Handler + Clone + Send + Sync,
{
  type Handler = Middleware<H>;

  fn wrap(&self, handler: H) -> Self::Handler {
    Middleware(handler)
  }
}

#[derive(Clone)]
struct Middleware<H>(H);

impl<H> Handler for Middleware<H>
where
  H: BoxableHandler,
{
  type Response = Response;
  type Error = BoxedErrorResponse;
  type Future = BoxedFuture<Result<Self::Response, Self::Error>>;

  fn handle(&self, request_context: RequestContext, args: Args<'_, ()>) -> Self::Future {
    // ...

    let response_future = self.0.handle(request_context, args);

    Box::pin(async move {
      let response = response_future.await?;

      // ...

      Ok(response)
    })
  }
}

let mut resource = Resource::new("/resource");

resource.wrap([
  MistargetedRequest.handler_in(MiddlewareLayer),
  Method::GET.handler_in(CompressionLayer::new()),
]);

resource.set_handler_for(Method::GET.to(|| async {}));
Source

pub fn set_property<C, const N: usize>(&mut self, properties: C)
where C: IntoArray<NodeProperty<Self>, N>,

Sets the resource’s optional properties.

use argan::{Resource, common::node_properties::NodeCookieKey, data::cookies::Key};

let mut resource = Resource::new("/resource");

// Given `cookie::Key` will be available to all subresoruces unless some subresource
// or handler replaces it with its own `cookie::Key` while the request is being
// routed or handled.
resource.set_property(NodeCookieKey.to(Key::generate()));
Source

pub fn for_each_subresource<T, F>(&mut self, param: T, func: F) -> T
where F: FnMut(&mut T, &mut Resource) -> Iteration,

Calls the given function for each subresource with a mutable reference to the param.

The method goes through the subresources in a depth-first manner. If the function returns Iteration::Skip for any resource it’s called for, that resource’s subresources will be skipped. If the function retuns Iteration::Stop or all the subresources have been processed, the parameter is returned in its final state.

Source

pub fn into_service(self) -> ResourceService

Converts the Resource into a service.

This method ignores the parent resources. Thus, it should be called on the first resource in the resource tree.

Source

pub fn into_arc_service(self) -> ArcResourceService

Converts the Resource into a service that uses Arc internally.

This method ignores the parent resources. Thus, it should be called on the first resource in the resource tree.

Source

pub fn into_leaked_service(self) -> LeakedResourceService

Converts the Resource into a service with a leaked &'static.

This method ignores the parent resources. Thus, it should be called on the first resource in the resource tree.

Trait Implementations§

Source§

impl Debug for Resource

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Display for Resource

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

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<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. 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