mirror of https://github.com/rwf2/Rocket.git
Document new 'local' structures.
This commit is contained in:
parent
03127f4dae
commit
050a2c6461
|
@ -6,10 +6,45 @@ use crate::rocket::{Rocket, Cargo};
|
||||||
use crate::http::{Method, private::CookieJar};
|
use crate::http::{Method, private::CookieJar};
|
||||||
use crate::error::LaunchError;
|
use crate::error::LaunchError;
|
||||||
|
|
||||||
|
struct_client! { [
|
||||||
|
///
|
||||||
|
/// ### Synchronization
|
||||||
|
///
|
||||||
|
/// While `Client` implements `Sync`, using it in a multithreaded environment
|
||||||
|
/// while tracking cookies can result in surprising, non-deterministic behavior.
|
||||||
|
/// This is because while cookie modifications are serialized, the exact
|
||||||
|
/// ordering depends on when requests are dispatched. Specifically, when cookie
|
||||||
|
/// tracking is enabled, all request dispatches are serialized, which in-turn
|
||||||
|
/// serializes modifications to the internally tracked cookies.
|
||||||
|
///
|
||||||
|
/// If possible, refrain from sharing a single instance of `Client` across
|
||||||
|
/// multiple threads. Instead, prefer to create a unique instance of `Client`
|
||||||
|
/// per thread. If it's not possible, ensure that either you are not depending
|
||||||
|
/// on cookies, the ordering of their modifications, or both, or have arranged
|
||||||
|
/// for dispatches to occur in a deterministic ordering.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// The following snippet creates a `Client` from a `Rocket` instance and
|
||||||
|
/// dispatches a local request to `POST /` with a body of `Hello, world!`.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::local::asynchronous::Client;
|
||||||
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
/// let rocket = rocket::ignite();
|
||||||
|
/// let client = Client::new(rocket).await.expect("valid rocket");
|
||||||
|
/// let response = client.post("/")
|
||||||
|
/// .body("Hello, world!")
|
||||||
|
/// .dispatch().await;
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
|
]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
cargo: Cargo,
|
cargo: Cargo,
|
||||||
pub(crate) cookies: Option<RwLock<CookieJar>>,
|
pub(crate) cookies: Option<RwLock<CookieJar>>,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub(crate) async fn _new(
|
pub(crate) async fn _new(
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
//! Structures for asynchronous local dispatching of requests, primarily for
|
||||||
|
//! testing.
|
||||||
|
//!
|
||||||
|
//! This module contains the `asynchronous` variant of the `local` API: it can
|
||||||
|
//! be used with `#[rocket::async_test]` or another asynchronous test harness.
|
||||||
|
|
||||||
mod client;
|
mod client;
|
||||||
mod request;
|
mod request;
|
||||||
mod response;
|
mod response;
|
||||||
|
|
|
@ -5,12 +5,33 @@ use crate::http::{Status, Method, uri::Origin, ext::IntoOwned};
|
||||||
|
|
||||||
use super::{Client, LocalResponse};
|
use super::{Client, LocalResponse};
|
||||||
|
|
||||||
|
struct_request! { [
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// The following snippet uses the available builder methods to construct a
|
||||||
|
/// `POST` request to `/` with a JSON body:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::local::asynchronous::{Client, LocalRequest};
|
||||||
|
/// use rocket::http::{ContentType, Cookie};
|
||||||
|
///
|
||||||
|
/// # rocket::async_test(async {
|
||||||
|
/// let client = Client::new(rocket::ignite()).await.expect("valid rocket");
|
||||||
|
/// let req = client.post("/")
|
||||||
|
/// .header(ContentType::JSON)
|
||||||
|
/// .remote("127.0.0.1:8000".parse().unwrap())
|
||||||
|
/// .cookie(Cookie::new("name", "value"))
|
||||||
|
/// .body(r#"{ "value": 42 }"#);
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
|
]
|
||||||
pub struct LocalRequest<'c> {
|
pub struct LocalRequest<'c> {
|
||||||
client: &'c Client,
|
client: &'c Client,
|
||||||
request: Request<'c>,
|
request: Request<'c>,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
uri: Cow<'c, str>,
|
uri: Cow<'c, str>,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'c> LocalRequest<'c> {
|
impl<'c> LocalRequest<'c> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use crate::{Request, Response};
|
use crate::{Request, Response};
|
||||||
|
|
||||||
|
struct_response! {
|
||||||
pub struct LocalResponse<'c> {
|
pub struct LocalResponse<'c> {
|
||||||
pub(in super) _request: Request<'c>,
|
pub(in super) _request: Request<'c>,
|
||||||
pub(in super) inner: Response<'c>,
|
pub(in super) inner: Response<'c>,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'c> LocalResponse<'c> {
|
impl<'c> LocalResponse<'c> {
|
||||||
fn _response(&self) -> &Response<'c> {
|
fn _response(&self) -> &Response<'c> {
|
||||||
|
|
|
@ -5,10 +5,28 @@ use crate::http::Method;
|
||||||
use crate::local::{asynchronous, blocking::LocalRequest};
|
use crate::local::{asynchronous, blocking::LocalRequest};
|
||||||
use crate::rocket::{Rocket, Cargo};
|
use crate::rocket::{Rocket, Cargo};
|
||||||
|
|
||||||
|
struct_client! { [
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// The following snippet creates a `Client` from a `Rocket` instance and
|
||||||
|
/// dispatches a local request to `POST /` with a body of `Hello, world!`.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::local::blocking::Client;
|
||||||
|
///
|
||||||
|
/// let rocket = rocket::ignite();
|
||||||
|
/// let client = Client::new(rocket).expect("valid rocket");
|
||||||
|
/// let response = client.post("/")
|
||||||
|
/// .body("Hello, world!")
|
||||||
|
/// .dispatch();
|
||||||
|
/// ```
|
||||||
|
]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
pub(crate) inner: asynchronous::Client,
|
pub(crate) inner: asynchronous::Client,
|
||||||
runtime: RefCell<tokio::runtime::Runtime>,
|
runtime: RefCell<tokio::runtime::Runtime>,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
fn _new(rocket: Rocket, tracked: bool) -> Result<Client, LaunchError> {
|
fn _new(rocket: Rocket, tracked: bool) -> Result<Client, LaunchError> {
|
||||||
|
|
|
@ -1,103 +1,9 @@
|
||||||
// TODO: Explain difference from async Client
|
//! Structures for blocking local dispatching of requests, primarily for
|
||||||
|
//! testing.
|
||||||
//!
|
//!
|
||||||
//! Structures for local dispatching of requests, primarily for testing.
|
//! This module contains the `blocking` variant of the `local` API: it can be
|
||||||
//!
|
//! used in Rust's synchronous `#[test]` harness. This is accomplished by
|
||||||
//! This module allows for simple request dispatching against a local,
|
//! starting and running an interal asynchronous Runtime as needed.
|
||||||
//! non-networked instance of Rocket. The primary use of this module is to unit
|
|
||||||
//! and integration test Rocket applications by crafting requests, dispatching
|
|
||||||
//! them, and verifying the response.
|
|
||||||
//!
|
|
||||||
//! # Usage
|
|
||||||
//!
|
|
||||||
//! This module contains a [`Client`] structure that is used to create
|
|
||||||
//! [`LocalRequest`] structures that can be dispatched against a given
|
|
||||||
//! [`Rocket`](crate::Rocket) instance. Usage is straightforward:
|
|
||||||
//!
|
|
||||||
//! 1. Construct a `Rocket` instance that represents the application.
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! let rocket = rocket::ignite();
|
|
||||||
//! # let _ = rocket;
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! 2. Construct a `Client` using the `Rocket` instance.
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! # use rocket::local::blocking::Client;
|
|
||||||
//! # let rocket = rocket::ignite();
|
|
||||||
//! let client = Client::new(rocket).expect("valid rocket instance");
|
|
||||||
//! # let _ = client;
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! 3. Construct requests using the `Client` instance.
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! # use rocket::local::blocking::Client;
|
|
||||||
//! # let rocket = rocket::ignite();
|
|
||||||
//! # let client = Client::new(rocket).unwrap();
|
|
||||||
//! let req = client.get("/");
|
|
||||||
//! # let _ = req;
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! 3. Dispatch the request to retrieve the response.
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! # use rocket::local::blocking::Client;
|
|
||||||
//! # let rocket = rocket::ignite();
|
|
||||||
//! # let client = Client::new(rocket).unwrap();
|
|
||||||
//! # let req = client.get("/");
|
|
||||||
//! let response = req.dispatch();
|
|
||||||
//! # let _ = response;
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! All together and in idiomatic fashion, this might look like:
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! use rocket::local::blocking::Client;
|
|
||||||
//!
|
|
||||||
//! let client = Client::new(rocket::ignite()).expect("valid rocket");
|
|
||||||
//! let response = client.post("/")
|
|
||||||
//! .body("Hello, world!")
|
|
||||||
//! .dispatch();
|
|
||||||
//! # let _ = response;
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! # Unit/Integration Testing
|
|
||||||
//!
|
|
||||||
//! This module can be used to test a Rocket application by constructing
|
|
||||||
//! requests via `Client` and validating the resulting response. As an example,
|
|
||||||
//! consider the following complete "Hello, world!" application, with testing.
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! #![feature(proc_macro_hygiene)]
|
|
||||||
//!
|
|
||||||
//! #[macro_use] extern crate rocket;
|
|
||||||
//!
|
|
||||||
//! #[get("/")]
|
|
||||||
//! fn hello() -> &'static str {
|
|
||||||
//! "Hello, world!"
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! # fn main() { }
|
|
||||||
//! #[cfg(test)]
|
|
||||||
//! mod test {
|
|
||||||
//! use super::{rocket, hello};
|
|
||||||
//! use rocket::local::blocking::Client;
|
|
||||||
//!
|
|
||||||
//! fn test_hello_world() {
|
|
||||||
//! // Construct a client to use for dispatching requests.
|
|
||||||
//! let rocket = rocket::ignite().mount("/", routes![hello]);
|
|
||||||
//! let client = Client::new(rocket).expect("valid rocket instance");
|
|
||||||
//!
|
|
||||||
//! // Dispatch a request to 'GET /' and validate the response.
|
|
||||||
//! let mut response = client.get("/").dispatch();
|
|
||||||
//! assert_eq!(response.into_string(), Some("Hello, world!".into()));
|
|
||||||
//! }
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! [`Client`]: crate::local::blocking::Client
|
|
||||||
//! [`LocalRequest`]: crate::local::blocking::LocalRequest
|
|
||||||
|
|
||||||
mod client;
|
mod client;
|
||||||
mod request;
|
mod request;
|
||||||
|
|
|
@ -3,11 +3,31 @@ use std::borrow::Cow;
|
||||||
use crate::{Request, http::Method, local::asynchronous};
|
use crate::{Request, http::Method, local::asynchronous};
|
||||||
|
|
||||||
use super::{Client, LocalResponse};
|
use super::{Client, LocalResponse};
|
||||||
|
|
||||||
|
struct_request! { [
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// The following snippet uses the available builder methods to construct a
|
||||||
|
/// `POST` request to `/` with a JSON body:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::local::blocking::{Client, LocalRequest};
|
||||||
|
/// use rocket::http::{ContentType, Cookie};
|
||||||
|
///
|
||||||
|
/// let client = Client::new(rocket::ignite()).expect("valid rocket");
|
||||||
|
/// let req = client.post("/")
|
||||||
|
/// .header(ContentType::JSON)
|
||||||
|
/// .remote("127.0.0.1:8000".parse().unwrap())
|
||||||
|
/// .cookie(Cookie::new("name", "value"))
|
||||||
|
/// .body(r#"{ "value": 42 }"#);
|
||||||
|
/// ```
|
||||||
|
]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct LocalRequest<'c> {
|
pub struct LocalRequest<'c> {
|
||||||
inner: asynchronous::LocalRequest<'c>,
|
inner: asynchronous::LocalRequest<'c>,
|
||||||
client: &'c Client,
|
client: &'c Client,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'c> LocalRequest<'c> {
|
impl<'c> LocalRequest<'c> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -2,10 +2,12 @@ use crate::{Response, local::asynchronous};
|
||||||
|
|
||||||
use super::Client;
|
use super::Client;
|
||||||
|
|
||||||
|
struct_response! {
|
||||||
pub struct LocalResponse<'c> {
|
pub struct LocalResponse<'c> {
|
||||||
pub(in super) inner: asynchronous::LocalResponse<'c>,
|
pub(in super) inner: asynchronous::LocalResponse<'c>,
|
||||||
pub(in super) client: &'c Client,
|
pub(in super) client: &'c Client,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'c> LocalResponse<'c> {
|
impl<'c> LocalResponse<'c> {
|
||||||
fn _response(&self) -> &Response<'c> {
|
fn _response(&self) -> &Response<'c> {
|
||||||
|
|
|
@ -1,66 +1,40 @@
|
||||||
//! A structure to construct requests for local dispatching.
|
macro_rules! struct_client {
|
||||||
//!
|
([$(#[$attr:meta])*] $item:item) =>
|
||||||
//! # Usage
|
{
|
||||||
//!
|
/// A structure to construct requests for local dispatching.
|
||||||
//! A `Client` is constructed via the [`new()`] or [`untracked()`] methods from
|
///
|
||||||
//! an already constructed `Rocket` instance. Once a value of `Client` has been
|
/// # Usage
|
||||||
//! constructed, the [`LocalRequest`] constructor methods ([`get()`], [`put()`],
|
///
|
||||||
//! [`post()`], and so on) can be used to create a `LocalRequest` for
|
/// A `Client` is constructed via the [`new()`] or [`untracked()`] methods from
|
||||||
//! dispatching.
|
/// an already constructed `Rocket` instance. Once a value of `Client` has been
|
||||||
//!
|
/// constructed, the [`LocalRequest`] constructor methods ([`get()`], [`put()`],
|
||||||
//! See the [top-level documentation](crate::local) for more usage information.
|
/// [`post()`], and so on) can be used to create a `LocalRequest` for
|
||||||
//!
|
/// dispatching.
|
||||||
//! ## Cookie Tracking
|
///
|
||||||
//!
|
/// See the [top-level documentation](crate::local) for more usage information.
|
||||||
//! A `Client` constructed using [`new()`] propagates cookie changes made by
|
///
|
||||||
//! responses to previously dispatched requests. In other words, if a previously
|
/// ## Cookie Tracking
|
||||||
//! dispatched request resulted in a response that adds a cookie, any future
|
///
|
||||||
//! requests will contain that cookie. Similarly, cookies removed by a response
|
/// A `Client` constructed using [`new()`] propagates cookie changes made by
|
||||||
//! won't be propagated further.
|
/// responses to previously dispatched requests. In other words, if a previously
|
||||||
//!
|
/// dispatched request resulted in a response that adds a cookie, any future
|
||||||
//! This is typically the desired mode of operation for a `Client` as it removes
|
/// requests will contain that cookie. Similarly, cookies removed by a response
|
||||||
//! the burden of manually tracking cookies. Under some circumstances, however,
|
/// won't be propagated further.
|
||||||
//! disabling this tracking may be desired. In these cases, use the
|
///
|
||||||
//! [`untracked()`](Client::untracked()) constructor to create a `Client` that
|
/// This is typically the desired mode of operation for a `Client` as it removes
|
||||||
//! _will not_ track cookies.
|
/// the burden of manually tracking cookies. Under some circumstances, however,
|
||||||
//!
|
/// disabling this tracking may be desired. In these cases, use the
|
||||||
//! ### Synchronization
|
/// [`untracked()`](Client::untracked()) constructor to create a `Client` that
|
||||||
//!
|
/// _will not_ track cookies.
|
||||||
//! While `Client` implements `Sync`, using it in a multithreaded environment
|
$(#[$attr])*
|
||||||
//! while tracking cookies can result in surprising, non-deterministic behavior.
|
///
|
||||||
//! This is because while cookie modifications are serialized, the exact
|
/// [`new()`]: #method.new
|
||||||
//! ordering depends on when requests are dispatched. Specifically, when cookie
|
/// [`untracked()`]: #method.untracked
|
||||||
//! tracking is enabled, all request dispatches are serialized, which in-turn
|
/// [`get()`]: #method.get
|
||||||
//! serializes modifications to the internally tracked cookies.
|
/// [`put()`]: #method.put
|
||||||
//!
|
/// [`post()`]: #method.post
|
||||||
//! If possible, refrain from sharing a single instance of `Client` across
|
$item
|
||||||
//! multiple threads. Instead, prefer to create a unique instance of `Client`
|
}}
|
||||||
//! per thread. If it's not possible, ensure that either you are not depending
|
|
||||||
//! on cookies, the ordering of their modifications, or both, or have arranged
|
|
||||||
//! for dispatches to occur in a deterministic ordering.
|
|
||||||
//!
|
|
||||||
//! ## Example
|
|
||||||
//!
|
|
||||||
//! The following snippet creates a `Client` from a `Rocket` instance and
|
|
||||||
//! dispatches a local request to `POST /` with a body of `Hello, world!`.
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! use rocket::local::asynchronous::Client;
|
|
||||||
//!
|
|
||||||
//! # rocket::async_test(async {
|
|
||||||
//! let rocket = rocket::ignite();
|
|
||||||
//! let client = Client::new(rocket).await.expect("valid rocket");
|
|
||||||
//! let response = client.post("/")
|
|
||||||
//! .body("Hello, world!")
|
|
||||||
//! .dispatch().await;
|
|
||||||
//! # });
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! [`new()`]: #method.new
|
|
||||||
//! [`untracked()`]: #method.untracked
|
|
||||||
//! [`get()`]: #method.get
|
|
||||||
//! [`put()`]: #method.put
|
|
||||||
//! [`post()`]: #method.post
|
|
||||||
|
|
||||||
macro_rules! req_method {
|
macro_rules! req_method {
|
||||||
($import:literal, $NAME:literal, $f:ident, $method:expr) => (
|
($import:literal, $NAME:literal, $f:ident, $method:expr) => (
|
||||||
|
|
|
@ -7,7 +7,14 @@
|
||||||
//!
|
//!
|
||||||
//! # Usage
|
//! # Usage
|
||||||
//!
|
//!
|
||||||
//! This module contains a [`Client`] structure that is used to create
|
//! This module contains two variants of the local API: [`asynchronous`] and
|
||||||
|
//! [`blocking`]. The primary difference between the two is in usage: the
|
||||||
|
//! `asynchronous` API requires an asynchronous test entry point such as
|
||||||
|
//! `#[rocket::async_test]`, while the `blocking` API can be used with
|
||||||
|
//! `#[test]`. Additionally, several methods in the `asynchronous` API are
|
||||||
|
//! `async` and must therefore be `await`ed.
|
||||||
|
//!
|
||||||
|
//! Both APIs include a [`Client`] structure that is used to create
|
||||||
//! [`LocalRequest`] structures that can be dispatched against a given
|
//! [`LocalRequest`] structures that can be dispatched against a given
|
||||||
//! [`Rocket`](crate::Rocket) instance. Usage is straightforward:
|
//! [`Rocket`](crate::Rocket) instance. Usage is straightforward:
|
||||||
//!
|
//!
|
||||||
|
@ -104,7 +111,7 @@
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! [`Client`]: crate::local::asynchronous::Client
|
//! [`Client`]: crate::local::asynchronous::Client
|
||||||
//! [`LocalRequest`]: crate::local::LocalRequest
|
//! [`LocalRequest`]: crate::local::asynchronous::LocalRequest
|
||||||
|
|
||||||
#[macro_use] mod client;
|
#[macro_use] mod client;
|
||||||
#[macro_use] mod request;
|
#[macro_use] mod request;
|
||||||
|
|
|
@ -1,62 +1,38 @@
|
||||||
//! A structure representing a local request as created by [`Client`].
|
macro_rules! struct_request {
|
||||||
//!
|
([$(#[$attr:meta])*] $item:item) =>
|
||||||
//! # Usage
|
{
|
||||||
//!
|
/// A structure representing a local request as created by [`Client`].
|
||||||
//! A `LocalRequest` value is constructed via method constructors on [`Client`].
|
///
|
||||||
//! Headers can be added via the [`header`] builder method and the
|
/// # Usage
|
||||||
//! [`add_header`] method. Cookies can be added via the [`cookie`] builder
|
///
|
||||||
//! method. The remote IP address can be set via the [`remote`] builder method.
|
/// A `LocalRequest` value is constructed via method constructors on [`Client`].
|
||||||
//! The body of the request can be set via the [`body`] builder method or
|
/// Headers can be added via the [`header`] builder method and the
|
||||||
//! [`set_body`] method.
|
/// [`add_header`] method. Cookies can be added via the [`cookie`] builder
|
||||||
//!
|
/// method. The remote IP address can be set via the [`remote`] builder method.
|
||||||
//! ## Example
|
/// The body of the request can be set via the [`body`] builder method or
|
||||||
//!
|
/// [`set_body`] method.
|
||||||
//! The following snippet uses the available builder methods to construct a
|
///
|
||||||
//! `POST` request to `/` with a JSON body:
|
$(#[$attr])*
|
||||||
//!
|
///
|
||||||
//! ```rust
|
/// # Dispatching
|
||||||
//! use rocket::local::asynchronous::Client;
|
///
|
||||||
//! use rocket::http::{ContentType, Cookie};
|
/// A `LocalRequest` is dispatched by calling [`dispatch`].
|
||||||
//!
|
/// The `LocalRequest` is consumed and a response is returned.
|
||||||
//! # rocket::async_test(async {
|
///
|
||||||
//! let client = Client::new(rocket::ignite()).await.expect("valid rocket");
|
/// Note that `LocalRequest` implements `Clone`. As such, if the
|
||||||
//! let req = client.post("/")
|
/// same request needs to be dispatched multiple times, the request can first be
|
||||||
//! .header(ContentType::JSON)
|
/// cloned and then dispatched: `request.clone().dispatch()`.
|
||||||
//! .remote("127.0.0.1:8000".parse().unwrap())
|
///
|
||||||
//! .cookie(Cookie::new("name", "value"))
|
/// [`Client`]: super::Client
|
||||||
//! .body(r#"{ "value": 42 }"#);
|
/// [`header`]: #method.header
|
||||||
//! # });
|
/// [`add_header`]: #method.add_header
|
||||||
//! ```
|
/// [`cookie`]: #method.cookie
|
||||||
//!
|
/// [`remote`]: #method.remote
|
||||||
//! # Dispatching
|
/// [`body`]: #method.body
|
||||||
//!
|
/// [`set_body`]: #method.set_body
|
||||||
//! A `LocalRequest` can be dispatched in one of two ways:
|
/// [`dispatch`]: #method.dispatch
|
||||||
//!
|
$item
|
||||||
//! 1. [`dispatch`]
|
}}
|
||||||
//!
|
|
||||||
//! This method should always be preferred. The `LocalRequest` is consumed
|
|
||||||
//! and a response is returned.
|
|
||||||
//!
|
|
||||||
//! 2. [`mut_dispatch`]
|
|
||||||
//!
|
|
||||||
//! This method should _only_ be used when either it is known that the
|
|
||||||
//! application will not modify the request, or it is desired to see
|
|
||||||
//! modifications to the request. No cloning occurs, and the request is not
|
|
||||||
//! consumed.
|
|
||||||
//!
|
|
||||||
//! Additionally, note that `LocalRequest` implements `Clone`. As such, if the
|
|
||||||
//! same request needs to be dispatched multiple times, the request can first be
|
|
||||||
//! cloned and then dispatched: `request.clone().dispatch()`.
|
|
||||||
//!
|
|
||||||
//! [`Client`]: crate::local::asynchronous::Client
|
|
||||||
//! [`header`]: #method.header
|
|
||||||
//! [`add_header`]: #method.add_header
|
|
||||||
//! [`cookie`]: #method.cookie
|
|
||||||
//! [`remote`]: #method.remote
|
|
||||||
//! [`body`]: #method.body
|
|
||||||
//! [`set_body`]: #method.set_body
|
|
||||||
//! [`dispatch`]: #method.dispatch
|
|
||||||
//! [`mut_dispatch`]: #method.mut_dispatch
|
|
||||||
|
|
||||||
macro_rules! impl_request {
|
macro_rules! impl_request {
|
||||||
($import:literal $(@$prefix:tt $suffix:tt)? $name:ident) =>
|
($import:literal $(@$prefix:tt $suffix:tt)? $name:ident) =>
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
//! A structure representing a response from dispatching a local request.
|
macro_rules! struct_response {
|
||||||
//!
|
($item:item) =>
|
||||||
//! This structure is a thin wrapper around [`Response`]. It implements no
|
{
|
||||||
//! methods of its own; all functionality is exposed via the [`Deref`] and
|
/// A structure representing a response from dispatching a local request.
|
||||||
//! [`DerefMut`] implementations with a target of `Response`. In other words,
|
///
|
||||||
//! when invoking methods, a `LocalResponse` can be treated exactly as if it
|
/// This structure is a thin wrapper around [`Response`]. It implements no
|
||||||
//! were a `Response`.
|
/// methods of its own; all functionality is exposed via the [`Deref`]
|
||||||
|
/// implementation with a target of `Response`. In other words, when
|
||||||
|
/// invoking methods, a `LocalResponse` can be treated exactly as if it were
|
||||||
|
/// a (read-only) `Response`.
|
||||||
|
///
|
||||||
|
/// [`Deref`]: std::ops::Deref
|
||||||
|
$item
|
||||||
|
}}
|
||||||
|
|
||||||
macro_rules! impl_response {
|
macro_rules! impl_response {
|
||||||
($import:literal $(@$prefix:tt $suffix:tt)? $name:ident) =>
|
($import:literal $(@$prefix:tt $suffix:tt)? $name:ident) =>
|
||||||
|
|
Loading…
Reference in New Issue