pub struct TestConn(/* private fields */);Expand description
A wrapper around a trillium::Conn for testing
Stability note: this may be replaced by an extension trait at some point.
Implementations§
Source§impl TestConn
impl TestConn
Sourcepub fn build<M>(
method: M,
path: impl Into<String>,
body: impl Into<Synthetic>,
) -> Self
pub fn build<M>( method: M, path: impl Into<String>, body: impl Into<Synthetic>, ) -> Self
constructs a new TestConn with the provided method, path, and body.
use trillium_testing::{TestConn, prelude::*};
let mut conn = TestConn::build("get", "/", "body");
assert_eq!(conn.method(), Method::Get);
assert_eq!(conn.path(), "/");
assert_eq!(conn.take_request_body_string(), "body");Sourcepub fn with_context(self, context: Arc<HttpContext>) -> Self
pub fn with_context(self, context: Arc<HttpContext>) -> Self
assigns a shared server config to this test conn
Sourcepub fn with_request_header(
self,
header_name: impl Into<HeaderName<'static>>,
header_value: impl Into<HeaderValues>,
) -> Self
pub fn with_request_header( self, header_name: impl Into<HeaderName<'static>>, header_value: impl Into<HeaderValues>, ) -> Self
chainable constructor to append a request header to the TestConn
use trillium_testing::TestConn;
let conn = TestConn::build("get", "/", "body").with_request_header("some-header", "value");
assert_eq!(conn.request_headers().get_str("some-header"), Some("value"));Sourcepub fn with_request_body(self, body: impl Into<Synthetic>) -> Self
pub fn with_request_body(self, body: impl Into<Synthetic>) -> Self
chainable constructor to replace the request body. this is useful
when chaining with a trillium_testing::methods
builder, as they do not provide a way to specify the body.
use trillium_testing::{TestConn, methods::post};
let mut conn = post("/").with_request_body("some body");
assert_eq!(conn.take_request_body_string(), "some body");
let mut conn = TestConn::build("post", "/", "some body").with_request_body("once told me");
assert_eq!(conn.take_request_body_string(), "once told me");Sourcepub fn with_peer_ip(self, ip: IpAddr) -> Self
pub fn with_peer_ip(self, ip: IpAddr) -> Self
sets the peer ip for this test conn
Sourcepub fn with_state<S>(self, state: S) -> Self
pub fn with_state<S>(self, state: S) -> Self
set state on the test conn
Sourcepub fn run(self, handler: &impl Handler) -> Self
pub fn run(self, handler: &impl Handler) -> Self
blocks on running this conn against a handler and finalizes
response headers. also aliased as TestConn::on
use trillium_testing::prelude::*;
async fn handler(conn: Conn) -> Conn {
conn.ok("hello trillium")
}
let conn = get("/").run(&handler);
assert_ok!(conn, "hello trillium", "content-length" => "14");Sourcepub async fn run_async(self, handler: &impl Handler) -> Self
pub async fn run_async(self, handler: &impl Handler) -> Self
runs this conn against a handler and finalizes response headers.
use trillium_testing::prelude::*;
async fn handler(conn: Conn) -> Conn {
conn.ok("hello trillium")
}
block_on(async move {
let conn = get("/").run_async(&handler).await;
assert_ok!(conn, "hello trillium", "content-length" => "14");
});Sourcepub fn on(self, handler: &impl Handler) -> Self
pub fn on(self, handler: &impl Handler) -> Self
blocks on running this conn against a handler and finalizes
response headers. also aliased as TestConn::run.
use trillium_testing::prelude::*;
async fn handler(conn: Conn) -> Conn {
conn.ok("hello trillium")
}
let conn = get("/").on(&handler);
assert_ok!(conn, "hello trillium", "content-length" => "14");Sourcepub fn take_response_body_string(&mut self) -> Option<String>
pub fn take_response_body_string(&mut self) -> Option<String>
Reads the response body to string and returns it, if set.
Sourcepub fn take_request_body_string(&mut self) -> String
pub fn take_request_body_string(&mut self) -> String
Reads the request body to string and returns it
Methods from Deref<Target = Conn>§
Sourcepub fn status(&self) -> Option<Status>
pub fn status(&self) -> Option<Status>
returns the response status for this Conn, if it has been set.
use trillium::Conn;
use trillium_testing::TestServer;
let handler = |mut conn: Conn| async move {
assert!(conn.status().is_none());
conn.set_status(200);
assert_eq!(conn.status().unwrap(), trillium_http::Status::Ok);
conn.ok("pass")
};
let app = TestServer::new(handler).await;
app.get("/").await.assert_ok();Sourcepub fn set_status(&mut self, status: impl TryInto<Status>) -> &mut Conn
pub fn set_status(&mut self, status: impl TryInto<Status>) -> &mut Conn
assigns a status to this response. see Conn::status for example usage
Sourcepub fn set_body(&mut self, body: impl Into<Body>) -> &mut Conn
pub fn set_body(&mut self, body: impl Into<Body>) -> &mut Conn
Sets the response body from any impl Into<Body>. Note that this does not set the response
status or halted.
See Body::new_streaming and Body::new_with_trailers to construct a body from an
AsyncRead or BodySource
use trillium::Conn;
use trillium_testing::TestServer;
let handler = |mut conn: Conn| async move {
conn.set_body("hello");
assert_eq!(conn.response_len(), Some(5));
conn.ok("pass")
};
let app = TestServer::new(handler).await;
app.get("/").await.assert_ok();Sourcepub fn take_response_body(&mut self) -> Option<Body>
pub fn take_response_body(&mut self) -> Option<Body>
Removes the response body from the Conn
use trillium::Conn;
use trillium_testing::TestServer;
let handler = |mut conn: Conn| async move {
conn.set_body("hello");
let body = conn.take_response_body().unwrap();
assert_eq!(body.len(), Some(5));
assert_eq!(conn.response_len(), None);
conn.ok("pass")
};
let app = TestServer::new(handler).await;
app.get("/").await.assert_ok();Sourcepub fn response_body(&self) -> Option<&Body>
pub fn response_body(&self) -> Option<&Body>
Borrows the response body from the Conn
use trillium::Conn;
use trillium_testing::TestServer;
let handler = |mut conn: Conn| async move {
conn.set_body("hello");
let body = conn.response_body().unwrap();
assert_eq!(body.len(), Some(5));
assert!(body.is_static());
assert_eq!(body.static_bytes(), Some(&b"hello"[..]));
conn.ok("pass")
};
let app = TestServer::new(handler).await;
app.get("/").await.assert_ok();Sourcepub fn state<T>(&self) -> Option<&T>
pub fn state<T>(&self) -> Option<&T>
Attempts to retrieve a &T from the state set
use trillium::Conn;
use trillium_testing::TestServer;
struct Hello;
let handler = |mut conn: Conn| async move {
assert!(conn.state::<Hello>().is_none());
conn.insert_state(Hello);
assert!(conn.state::<Hello>().is_some());
conn.ok("pass")
};
let app = TestServer::new(handler).await;
app.get("/").await.assert_ok();Sourcepub fn state_mut<T>(&mut self) -> Option<&mut T>
pub fn state_mut<T>(&mut self) -> Option<&mut T>
Attempts to retrieve a &mut T from the state set
Sourcepub fn insert_state<T>(&mut self, state: T) -> Option<T>
pub fn insert_state<T>(&mut self, state: T) -> Option<T>
Inserts a new type into the state set. See Conn::state
for an example.
Returns the previously-set instance of this type, if any
Sourcepub fn take_state<T>(&mut self) -> Option<T>
pub fn take_state<T>(&mut self) -> Option<T>
Removes a type from the state set and returns it, if present
Sourcepub fn state_entry<T>(&mut self) -> Entry<'_, T>
pub fn state_entry<T>(&mut self) -> Entry<'_, T>
Returns an Entry for the state typeset that can be used with functions like
Entry::or_insert, Entry::or_insert_with, Entry::and_modify, and others.
Attempts to borrow a T from the immutable shared state set
Sourcepub fn request_body(&mut self) -> RequestBody<'_>
pub fn request_body(&mut self) -> RequestBody<'_>
Returns a RequestBody that references this Conn. The Conn
retains all data and holds the singular transport, but the
RequestBody provides an interface to read body content.
If the request included an Expect: 100-continue header, the 100 Continue response is sent
lazily on the first read from the returned RequestBody.
See also: Conn::request_body_string for a convenience function
when the content is expected to be utf8.
§Examples
use trillium::Conn;
use trillium_testing::TestServer;
let handler = |mut conn: Conn| async move {
let request_body = conn.request_body();
assert_eq!(request_body.content_length(), Some(12));
assert_eq!(request_body.read_string().await.unwrap(), "request body");
conn.ok("pass")
};
let app = TestServer::new(handler).await;
app.post("/").with_body("request body").await.assert_ok();Sourcepub async fn request_body_string(&mut self) -> Result<String, Error>
pub async fn request_body_string(&mut self) -> Result<String, Error>
Convenience function to read the content of a request body as a String.
§Errors
This will return an error variant if either there is an IO failure on the underlying transport or if the body content is not a utf8 string.
§Examples
use trillium::Conn;
use trillium_testing::TestServer;
let handler = |mut conn: Conn| async move {
assert_eq!(conn.request_body_string().await.unwrap(), "request body");
conn.ok("pass")
};
let app = TestServer::new(handler).await;
app.post("/").with_body("request body").await.assert_ok();Sourcepub fn response_len(&self) -> Option<u64>
pub fn response_len(&self) -> Option<u64>
if there is a response body for this conn and it has a known fixed length, it is returned from this function
use trillium::Conn;
use trillium_testing::TestServer;
let handler = |mut conn: Conn| async move {
assert_eq!(conn.response_len(), None); // no body set yet
conn.set_body("hello");
assert_eq!(conn.response_len(), Some(5));
conn.ok("pass")
};
let app = TestServer::new(handler).await;
app.get("/").await.assert_ok();Sourcepub fn method(&self) -> Method
pub fn method(&self) -> Method
returns the request method for this conn.
use trillium::Conn;
use trillium_http::Method;
use trillium_testing::TestServer;
let handler = |conn: Conn| async move {
assert_eq!(conn.method(), Method::Get);
conn.ok("pass")
};
let app = TestServer::new(handler).await;
app.get("/").await.assert_ok();Sourcepub fn response_headers(&self) -> &Headers
pub fn response_headers(&self) -> &Headers
Borrow the response headers
Sourcepub fn response_headers_mut(&mut self) -> &mut Headers
pub fn response_headers_mut(&mut self) -> &mut Headers
Mutably borrow the response headers
Sourcepub fn request_headers(&self) -> &Headers
pub fn request_headers(&self) -> &Headers
Borrow the request headers
Sourcepub fn request_headers_mut(&mut self) -> &mut Headers
pub fn request_headers_mut(&mut self) -> &mut Headers
Mutably borrow request headers
Sourcepub fn request_trailers(&self) -> Option<&Headers>
pub fn request_trailers(&self) -> Option<&Headers>
Borrow the request trailers, if any
Trailers are only populated after reading a request body that includes trailers to completion.
Sourcepub fn insert_response_header(
&mut self,
header_name: impl Into<HeaderName<'static>>,
header_value: impl Into<HeaderValues>,
)
pub fn insert_response_header( &mut self, header_name: impl Into<HeaderName<'static>>, header_value: impl Into<HeaderValues>, )
Insert a header name and value/values into the response headers.
See also Headers::insert and Headers::append
For a slight performance improvement, use a KnownHeaderName.
Sourcepub fn path(&self) -> &str
pub fn path(&self) -> &str
returns the path for this request. note that this may not represent the entire http request path if running nested routers.
Sourcepub fn querystring(&self) -> &str
pub fn querystring(&self) -> &str
returns query part of the request path
use trillium::Conn;
use trillium_testing::TestServer;
let handler = |conn: Conn| async move {
let querystring = conn.querystring();
if querystring == "c&d=e" {
conn.ok("has query")
} else {
conn.ok("no query")
}
};
let app = TestServer::new(handler).await;
app.get("/a/b?c&d=e").await.assert_body("has query");
app.get("/a/b").await.assert_body("no query");§Parsing
Trillium does not include a querystring parsing library, as there is no universal standard for querystring encodings of arrays, but several library options exist, inluding:
QueryStrong (by the author of trillium)
serde_qs
querystring
serde_querystring
Sourcepub fn set_halted(&mut self, halted: bool) -> &mut Conn
pub fn set_halted(&mut self, halted: bool) -> &mut Conn
sets the halted attribute of this conn. see Conn::halt.
use trillium::Conn;
use trillium_testing::TestServer;
let handler = |mut conn: Conn| async move {
assert!(!conn.is_halted());
conn.set_halted(true);
assert!(conn.is_halted());
conn.ok("pass")
};
let app = TestServer::new(handler).await;
app.get("/").await.assert_ok();Sourcepub fn is_halted(&self) -> bool
pub fn is_halted(&self) -> bool
retrieves the halted state of this conn. see Conn::halt.
Sourcepub fn is_secure(&self) -> bool
pub fn is_secure(&self) -> bool
predicate function to indicate whether the connection is
secure. note that this does not necessarily indicate that the
transport itself is secure, as it may indicate that
trillium_http is behind a trusted reverse proxy that has
terminated tls and provided appropriate headers to indicate
this.
Sourcepub fn start_time(&self) -> Instant
pub fn start_time(&self) -> Instant
The Instant that the first header bytes for this conn were
received, before any processing or parsing has been performed.
Sourcepub fn peer_ip(&self) -> Option<IpAddr>
pub fn peer_ip(&self) -> Option<IpAddr>
retrieves the remote ip address for this conn, if available.
Sourcepub fn set_peer_ip(&mut self, peer_ip: Option<IpAddr>) -> &mut Conn
pub fn set_peer_ip(&mut self, peer_ip: Option<IpAddr>) -> &mut Conn
sets the remote ip address for this conn.
Sourcepub fn push_path(&mut self, path: String)
pub fn push_path(&mut self, path: String)
for router implementations. pushes a route segment onto the path
Sourcepub async fn cancel_on_disconnect<'a, Fut>(
&'a mut self,
fut: Fut,
) -> Option<<Fut as Future>::Output>
pub async fn cancel_on_disconnect<'a, Fut>( &'a mut self, fut: Fut, ) -> Option<<Fut as Future>::Output>
Cancels and drops the future if reading from the transport results in an error or empty read
If the client disconnects from the conn’s transport, this function will return None. If the future completes without disconnection, this future will return Some containing the output of the future.
The use of this method is not advised if your connected http client employs pipelining (rarely seen in the wild), as it will buffer an unbounded number of requests
Note that the inner future cannot borrow conn, so you will need to clone or take any information needed to execute the future prior to executing this method.
§Example
async fn something_slow_and_cancel_safe() -> String {
String::from("this was not actually slow")
}
async fn handler(mut conn: Conn) -> Conn {
match conn
.cancel_on_disconnect(async { something_slow_and_cancel_safe().await })
.await
{
Some(returned_body) => conn.ok(returned_body),
None => conn,
}
}Sourcepub async fn is_disconnected(&mut self) -> bool
pub async fn is_disconnected(&mut self) -> bool
Check if the transport is connected by testing attempting to read from the transport
§Example
This is best to use at appropriate points in a long-running handler, like:
async fn handler(mut conn: Conn) -> Conn {
for _ in 0..100 {
if conn.is_disconnected().await {
return conn;
}
something_slow_but_not_cancel_safe().await;
}
conn.ok("ok!")
}Sourcepub fn http_version(&self) -> Version
pub fn http_version(&self) -> Version
Returns the http version over which this Conn is being communicated
Sourcepub fn path_and_query(&self) -> &str
pub fn path_and_query(&self) -> &str
retrieves the combined path and any query