Skip to main content

Call

Struct Call 

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

Per-request context: the single object a handler receives (Ktor-style).

A Call bundles the request method, URI, headers, captured path parameters, the (buffered) body, a handle to shared application state, and a per-call extension map. Handlers receive it either directly (|c: Call| async { ... }) or indirectly through extractors such as Path and Query, which read from the Call for you.

Read-only accessors (method, uri, path, header, query, param) borrow &self; body consumption (receive_bytes, receive_text) takes &mut self. The insert/get pair passes typed values between middleware and downstream handlers.

Construct one with Call::new in unit tests; in production the engine and the TestClient build it for you.

use churust_core::Call;
use http::{HeaderMap, Method};
use bytes::Bytes;

let call = Call::new(
    Method::GET,
    "/search?q=rust".parse().unwrap(),
    HeaderMap::new(),
    Bytes::new(),
);
assert_eq!(call.method(), &Method::GET);
assert_eq!(call.path(), "/search");
assert_eq!(call.query("q").as_deref(), Some("rust"));

Implementations§

Source§

impl Call

Source

pub fn new(method: Method, uri: Uri, headers: HeaderMap, body: Bytes) -> Self

Construct a Call from already-parsed request parts (used by the engine and the test harness alike).

Source

pub fn method(&self) -> &Method

The request HTTP method.

Source

pub fn uri(&self) -> &Uri

The full request URI (path, query, and any authority).

Source

pub fn path(&self) -> &str

The request path, without the query string (e.g. /users/42).

Source

pub fn headers(&self) -> &HeaderMap

The full request header map.

Source

pub fn header(&self, name: &str) -> Option<&str>

The value of header name as a UTF-8 string, or None if the header is absent or its value is not valid UTF-8. Header name matching is case-insensitive.

use churust_core::Call;
use http::{HeaderMap, Method, header::ACCEPT, HeaderValue};
use bytes::Bytes;

let mut headers = HeaderMap::new();
headers.insert(ACCEPT, HeaderValue::from_static("application/json"));
let call = Call::new(Method::GET, "/".parse().unwrap(), headers, Bytes::new());
assert_eq!(call.header("accept"), Some("application/json"));
assert_eq!(call.header("x-missing"), None);
Source

pub fn query_string(&self) -> &str

The raw query string with the leading ? stripped, or "" if there is none. To deserialize the whole query into a struct, prefer the Query extractor.

use churust_core::Call;
use http::{HeaderMap, Method};
use bytes::Bytes;

let call = Call::new(Method::GET, "/s?a=1&b=2".parse().unwrap(), HeaderMap::new(), Bytes::new());
assert_eq!(call.query_string(), "a=1&b=2");
Source

pub fn query(&self, key: &str) -> Option<String>

The first value for query key key, percent- and +-decoded, or None if the key is absent.

use churust_core::Call;
use http::{HeaderMap, Method};
use bytes::Bytes;

let call = Call::new(Method::GET, "/s?q=hello+world".parse().unwrap(), HeaderMap::new(), Bytes::new());
assert_eq!(call.query("q").as_deref(), Some("hello world"));
assert_eq!(call.query("missing"), None);
Source

pub fn state<T: Send + Sync + 'static>(&self) -> Option<Arc<T>>

A shared handle to application state of type T, or None if no value of that type was registered with AppBuilder::state. For handler arguments, the State extractor is usually more convenient.

use churust_core::{Churust, Call, TestClient};
#[derive(Clone)]
struct AppName(&'static str);

let app = Churust::server()
    .state(AppName("churust"))
    .routing(|r| {
        r.get("/", |c: Call| async move {
            format!("app={}", c.state::<AppName>().unwrap().0)
        });
    })
    .build();
let res = TestClient::new(app).get("/").send().await;
assert_eq!(res.text(), "app=churust");
Source

pub fn params_iter(&self) -> impl Iterator<Item = (&str, &str)>

Iterate over the captured path parameters as (name, value) pairs. Iteration order is unspecified (the parameters are stored in a hash map).

Source

pub fn param_raw(&self, name: &str) -> Option<&str>

The raw, unparsed value of path parameter name, or None if the route has no such parameter. Use param to parse it into a typed value.

Source

pub fn param<T>(&self, name: &str) -> Result<T>
where T: FromStr, T::Err: Display,

Parse path parameter name into T.

Returns a 400 Bad Request Error if the parameter is missing or fails to parse.

use churust_core::{Churust, Call, TestClient};
let app = Churust::server()
    .routing(|r| {
        r.get("/users/{id}", |c: Call| async move {
            let id: u64 = c.param("id")?;
            Ok::<_, churust_core::Error>(format!("user {id}"))
        });
    })
    .build();
let res = TestClient::new(app).get("/users/42").send().await;
assert_eq!(res.text(), "user 42");
Source

pub async fn receive_bytes(&mut self) -> Bytes

Take the request body as raw Bytes, leaving the call’s body empty.

This consumes the body: a second call returns an empty buffer. It is async to leave room for future streaming bodies.

use churust_core::Call;
use http::{HeaderMap, Method};
use bytes::Bytes;
let mut call = Call::new(Method::POST, "/".parse().unwrap(), HeaderMap::new(), Bytes::from("data"));
assert_eq!(&call.receive_bytes().await[..], b"data");
assert!(call.receive_bytes().await.is_empty()); // already consumed
Source

pub async fn receive_text(&mut self) -> Result<String>

Take the request body decoded as UTF-8, consuming it.

Returns a 400 Bad Request Error if the body is not valid UTF-8.

use churust_core::Call;
use http::{HeaderMap, Method};
use bytes::Bytes;
let mut call = Call::new(Method::POST, "/".parse().unwrap(), HeaderMap::new(), Bytes::from("ping"));
assert_eq!(call.receive_text().await.unwrap(), "ping");
Source

pub fn insert<T: Clone + Send + Sync + 'static>(&mut self, value: T)

Insert a per-call typed value into the call’s extension map, keyed by its type. Typically used by a middleware to attach context (e.g. an authenticated principal) that a downstream extractor or handler reads via get. Inserting a second value of the same type replaces the first.

use churust_core::Call;
use http::{HeaderMap, Method};
use bytes::Bytes;

#[derive(Clone, PartialEq, Debug)]
struct UserId(u32);

let mut call = Call::new(Method::GET, "/".parse().unwrap(), HeaderMap::new(), Bytes::new());
call.insert(UserId(7));
assert_eq!(call.get::<UserId>(), Some(UserId(7)));
Source

pub fn get<T: Clone + Send + Sync + 'static>(&self) -> Option<T>

Get a clone of the per-call value of type T previously stored with insert, or None if none was stored.

use churust_core::Call;
use http::{HeaderMap, Method};
use bytes::Bytes;

let call = Call::new(Method::GET, "/".parse().unwrap(), HeaderMap::new(), Bytes::new());
assert_eq!(call.get::<u32>(), None);
Source

pub fn respond_text(&self, body: impl Into<String>) -> Response

Build a 200 OK text/plain Response — a shorthand for Response::text.

use churust_core::Call;
use http::{HeaderMap, Method};
use bytes::Bytes;

let call = Call::new(Method::GET, "/".parse().unwrap(), HeaderMap::new(), Bytes::new());
let res = call.respond_text("ok");
assert_eq!(res.body.as_slice(), Some(&b"ok"[..]));
Source

pub fn respond_status(&self, status: StatusCode) -> Response

Build an empty-bodied Response with the given status — a shorthand for Response::new.

use churust_core::Call;
use http::{HeaderMap, Method, StatusCode};
use bytes::Bytes;

let call = Call::new(Method::GET, "/".parse().unwrap(), HeaderMap::new(), Bytes::new());
assert_eq!(call.respond_status(StatusCode::ACCEPTED).status, StatusCode::ACCEPTED);

Trait Implementations§

Source§

impl Debug for Call

Source§

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

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

impl FromCall for Call

The whole Call as the final argument (Ktor call-style base case). NOTE: deliberately NOT FromCallParts — that would conflict with the blanket impl above.

Source§

fn from_call<'async_trait>( call: Call, ) -> Pin<Box<dyn Future<Output = Result<Self>> + Send + 'async_trait>>
where Self: 'async_trait,

Build Self by consuming the call, or return an Error (which the handler renders as the response).

Auto Trait Implementations§

§

impl !Freeze for Call

§

impl !RefUnwindSafe for Call

§

impl !UnwindSafe for Call

§

impl Send for Call

§

impl Sync for Call

§

impl Unpin for Call

§

impl UnsafeUnpin for Call

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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