# Response

> The server sends exactly one response: the byte 0 alone, Serving, after which the scope stays open until the client stops it or the container ends; or the byte 1 followed by an error as one JSON value, and the response finish.

Canonical: https://protocol.diverge.network/2.3.0/endpoints/containers-fuse-serve/response/
Specification revision: 2.3.0

The server sends exactly one response on the scope, and sends it
before it serves any channel.

```text
[0]                  serving: the proxy serves the directory, and the asks are answered
[1][error JSON …]    not served
```

- **The sequence.** Exactly one response, first. After a response
  whose payload is exactly the one byte `0`, the scope stays open:
  the server sends no other response on the scope, answers every
  channel the client opens as [Client Channels](/2.3.0/endpoints/containers-fuse-serve/client/) states,
  and sends the response finish after the last answer when the client
  stops or the container ends. After a response whose first byte is
  `1`, the response finish follows the response, and no frame
  follows the finish. A response finish that no response precedes
  states that the request was not served, as [Endpoints](/2.3.0/endpoints/)
  provides.
- **Serving.** The server sends the byte `0` only after the proxy of
  the container has answered `Serving` on the
  [filesystem::fuse_serve](/2.3.0/container-proxy-endpoints/filesystem-fuse-serve/) scope the server
  opened for the request.
- **The error.** A payload whose first byte is `1` carries an error
  after that byte, running to the end of the payload. The error is
  exactly one JSON value, in the form defined on the
  [volumes::list response](/2.3.0/endpoints/volumes-list/response/) page.
  An id that names no container the client is running is answered
  with exactly `{"kind":"missing"}`; a directory the proxy refused is
  answered with the error the proxy sent, verbatim. This revision
  prescribes nothing else about its content.
- **Malformed.** A payload with no byte, a payload whose first byte
  is none of `0` and `1`, a payload whose first byte is `0` and
  that has a byte after it, and a payload whose bytes after `1` are
  not one JSON value are malformed.

The response is defined by `diverge-sdk-rs/src/provider/endpoints/containers/fuse_serve/server/response/frame.rs`:

```rust
//! What a server's response frame carries for a container FUSE serve.

use std::fmt;

use crate::wire::decode::Decode;
use crate::wire::encode::{Encode, Writer};
use crate::shared::error::Error;

/// The subtree is served, or the news that it will not be.
///
/// A payload leads with one byte saying which — `0` for
/// [`Serving`](Self::Serving), `1` for [`Error`](Self::Error) — and
/// the rest is that variant's own JSON, of which only the error has
/// any.
///
/// # How the scope runs
///
/// | the scope | means |
/// |-----------|-------|
/// | a serving, then quiet, and stays open | the proxy serves the subtree, and every ask the caller opens is answered on its channel |
/// | a serving, then a finish | the caller stopped, or the container ended |
/// | an error, then a finish | it was not served: no container of the caller's runs under the id, the path is not a directory of it, or the proxy refused |
///
/// Exactly one response, first. Nothing else comes on channel `0`;
/// the answers to asks come on the asks' channels.
#[derive(Debug, Clone, PartialEq)]
pub enum Frame {
    /// The proxy serves the subtree, and asks may be opened. Tag `0`.
    Serving,
    /// A failure. Tag `1`.
    ///
    /// `{"kind":"missing"}` for an id under which no container of the
    /// caller's runs — whether somebody else's does is not said —
    /// and otherwise the proxy's own words for the path. See
    /// [`shared::error::Error`](crate::shared::error::Error) for why
    /// it says so little.
    Error(Error),
}

/// Tag for [`Frame::Serving`].
const SERVING: u8 = 0;

/// Tag for [`Frame::Error`].
const ERROR: u8 = 1;

impl Encode for Frame {
    /// The ordinary JSON failure, from the half that has one.
    type Error = serde_json::Error;

    // Spelled out rather than `Self::Error`: this enum has a variant
    // called `Error`, so the associated type is ambiguous by that name.
    fn encode(&self, out: &mut Writer<'_>) -> Result<(), serde_json::Error> {
        match self {
            Frame::Serving => {
                out.extend_from_slice(&[SERVING]);
                Ok(())
            }
            Frame::Error(error) => {
                out.extend_from_slice(&[ERROR]);
                error.encode(out)
            }
        }
    }
}

impl Decode<'_> for Frame {
    /// Three ways to fail, and one of them is a parse.
    type Error = FrameError;

    // Spelled out for the same reason as `encode` above.
    fn decode(bytes: &[u8]) -> Result<Self, FrameError> {
        let (tag, rest) = bytes.split_first().ok_or(FrameError::Empty)?;
        match *tag {
            SERVING => Ok(Frame::Serving),
            ERROR => Error::decode(rest).map(Frame::Error).map_err(FrameError::Error),
            tag => Err(FrameError::UnknownTag(tag)),
        }
    }
}

/// A container FUSE serve response frame that could not be read.
#[derive(Debug)]
pub enum FrameError {
    /// No bytes at all, so not even a tag.
    Empty,
    /// A tag that is none of this frame's two.
    UnknownTag(u8),
    /// The error did not parse.
    Error(serde_json::Error),
}

impl fmt::Display for FrameError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FrameError::Empty => f.write_str("container FUSE serve response frame is empty"),
            FrameError::UnknownTag(tag) => write!(f, "unknown container FUSE serve response frame tag {tag}"),
            FrameError::Error(error) => write!(f, "container FUSE serve error did not parse: {error}"),
        }
    }
}

impl std::error::Error for FrameError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            FrameError::Error(error) => Some(error),
            FrameError::Empty | FrameError::UnknownTag(_) => None,
        }
    }
}
```
