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

Responsible for configuring a resource and interacting with it.

Must be created through TestServer.

By default a resource’s method is GET and response is 200 Ok with empty body.

use http_test_server::TestServer;
use http_test_server::http::{Method, Status};

let server = TestServer::new().unwrap();
let resource = server.create_resource("/i-am-a-resource");

resource
    .status(Status::PartialContent)
    .method(Method::POST)
    .body("All good!");

To create resources with variable parts in the URL, you may use path and query parameters:

// matches /user/*/details?filter=*
let resource = server.create_resource("/user/{userId}/details?filter=*");
resource.body("All good for {path.userId} with filter {query.filter}!");

Note: I don’t think it’s a good idea to write mocks with complex behaviours. Usually, they are less maintainable and harder to track.

Instead, I would suggest creating one resource for each behaviour expected. Having said that, I’m not here to judge. Do whatever floats your boat! :)

Implementations§

source§

impl Resource

source

pub fn status(&self, status_code: Status) -> &Resource

Defines response’s HTTP Status .

Refer to custom_status for Statuses not covered by Status.

resource.status(Status::PartialContent);
source

pub fn custom_status(&self, status_code: u16, description: &str) -> &Resource

Defines a custom HTTP Status to response.

Use it to return HTTP statuses that are not covered by Status.

resource.custom_status(333, "Only Half Beast");
source

pub fn header(&self, header_name: &str, header_value: &str) -> &Resource

Defines response headers.

Call it multiple times to add multiple headers. If a header is defined twice only the late value is returned.

resource
    .header("Content-Type", "application/json")
    .header("Connection", "Keep-Alive");
source

pub fn query(&self, name: &str, value: &str) -> &Resource

Defines query parameters.

resource
    .query("filter", "*") // wildcard, matches any value
    .query("version", "1"); // only matches request with version == 1

This is equivalent to:

let resource = server.create_resource("/?filter=*&version=1");
source

pub fn body(&self, content: &'static str) -> &Resource

Defines response’s body.

If the response is a stream this value will be sent straight after connection.

Calling multiple times will overwrite the previous value.

resource.body("this is important!");

It’s possible to use path and query parameters in the response body by defining {path.<parameter_name>} or {query.<parameter_name>}:

let resource = server.create_resource("/user/{userId}?filter=*");
resource.body("Response for user: {path.userId} filter: {query.filter}");
source

pub fn body_fn( &self, builder: impl Fn(RequestParameters) -> String + Send + 'static ) -> &Resource

Defines function used to build the response’s body.

If the response is a stream value will be sent straight after connection.

Calling multiple times will overwrite the previous value.

let resource = server.create_resource("/character/{id}?version=*");
resource.body_fn(|params| {
    println!("version: {}", params.query.get("version").unwrap());

    match params.path.get("id").unwrap().as_str() {
        "Balrog" => r#"{ "message": "YOU SHALL NOT PASS!" }"#.to_string(),
        _ => r#"{ "message": "Fly, you fools!" }"#.to_string()
    }
});
source

pub fn method(&self, method: Method) -> &Resource

Defines HTTP method.

A resource will only respond to one method, however multiple resources with same URL and different methods can be created.

use http_test_server::http::Method;
let resource_put = server.create_resource("/i-am-a-resource");
let resource_post = server.create_resource("/i-am-a-resource");

resource_put.method(Method::PUT);
resource_post.method(Method::POST);
source

pub fn delay(&self, delay: Duration) -> &Resource

Defines delay to response after client connected

use std::time::Duration;

resource.delay(Duration::from_millis(500));
source

pub fn stream(&self) -> &Resource

Set response as stream, this means clients won’t be disconnected after body is sent and updates can be sent and received.

See also: send, send_line, stream_receiver.

let resource = server.create_resource("/stream");

resource.stream();

resource
    .send_line("some")
    .send_line("data")
    .close_open_connections();
source

pub fn send(&self, data: &str) -> &Resource

Send data to all connected clients.

See also: send_line, stream.

let resource = server.create_resource("/stream");

resource.stream();

resource
    .send("some")
    .send(" data");
source

pub fn send_line(&self, data: &str) -> &Resource

Send data to all connected clients. Same as send, but appends \n to data.

See also: stream

let resource = server.create_resource("/stream");

resource.stream();

resource
    .send_line("one line")
    .send_line("another line");
source

pub fn close_open_connections(&self)

Close all connections with clients.

See also: stream

let resource = server.create_resource("/stream");

resource.stream();

resource.close_open_connections();
source

pub fn open_connections_count(&self) -> usize

Number of clients connected to stream.

See also: stream

let resource = server.create_resource("/stream");

resource
    .stream()
    .close_open_connections();

assert_eq!(resource.open_connections_count(), 0);
source

pub fn stream_receiver(&self) -> Receiver<String>

Receives data sent from clients through stream.

See also: stream

let resource = server.create_resource("/stream");
let receiver = resource.stream().stream_receiver();

let new_message = receiver.recv().unwrap();

for message in receiver.iter() {
    println!("Client message: {}", message);
}
source

pub fn request_count(&self) -> u32

Number of requests received

assert_eq!(resource.request_count(), 0);

Trait Implementations§

source§

impl Clone for Resource

source§

fn clone(&self) -> Self

Returns a Resource copy that shares state with other copies.

This is useful when working with same Resource across threads.

1.0.0 · source§

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

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere 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, U> Into<U> for Twhere 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> ToOwned for Twhere T: Clone,

§

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 Twhere U: Into<T>,

§

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 Twhere U: TryFrom<T>,

§

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.