Skip to main content

HttpHandler

Struct HttpHandler 

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

The handler that bridges McpRouter to the real Dispatcher.

The port trait belongs to the router, so this type implements it and declares nothing. There is no second “how to answer a request” here — only Dispatcher with an HTTP envelope around it.

Implementations§

Source§

impl HttpHandler

Source

pub const fn new( dispatcher: Arc<Dispatcher>, sessions: Arc<SessionStore<HttpSession>>, ceiling: ProtocolVersion, ) -> Self

A handler over dispatcher and sessions, gated at ceiling.

Source

pub const fn ceiling(&self) -> ProtocolVersion

The revision a session is gated with before it is negotiated.

Trait Implementations§

Source§

impl Debug for HttpHandler

Source§

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

Prints the ceiling and nothing else.

Handwritten because the store it holds is a table of session ids, and this project does not put a full session id in a log line. A derived Debug would make a {:?} in a log statement a way around that.

Source§

impl RequestHandler<HttpSession> for HttpHandler

Source§

fn unsessioned(&self, body: &[u8], headers: &HeaderMap) -> Unsessioned

What a body means when the request named no session.

Three arms, and which one a body falls in is a wire-format question this method can answer on its own:

  • initialize opens a session. It is the only method that does.
  • A body whose params._meta names PROTOCOL_VERSION_KEY is a SEP-2575 stateless request. It carries its own revision and its own capabilities, so it needs no session and is served against its own profile.
  • Anything else is a stateful call missing its header, which the router answers with a 400 and never hands here — so returning Unsessioned::NeedsSession for it is not a guess, it is the arm that produces that 400.

The version key is what makes a body self-describing, and it is the only member that can: capabilities without a revision would not say which gates the answer is read against.

This runs on every sessionless POST, so the check is a lookup and not a parse — a full RequestMeta::read would decode the whole body only for a caller with a session header to throw it away.

Source§

fn dispatch( &self, call: Inbound<'_, HttpSession>, ) -> impl Future<Output = Result<Response, Refusal>> + Send

Runs one request, and answers it.

The refusal channel is a Refusal: there is no other, and an adapter that cannot answer a request has exactly one honest way to say so. Note that a protocol refusal — an unknown method, a tool that does not exist — is not one. Those are answered in the body with a JSON-RPC error object, because the peer asked a well-formed question and the answer is that no such thing exists.

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<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<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
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 = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

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