Ниже показан английский оригинал.
Body
SQS bodies are text, so a payload SQS would refuse travels base64 with a marker attribute and is decoded again on receive.
SQS takes a narrower set of characters than UTF-8 in a body.
It refuses the control characters other than tab, line feed and carriage return, and the two non-characters at the end of the basic plane.
A payload that is such text, a JSON document for one, travels as it is.
Any other payload travels base64-encoded, with the attribute ruststream-payload-encoding set to base64: bytes that are not UTF-8, and equally valid UTF-8 with control characters, which a binary codec often emits.
The receiving side decodes the body again before the handler sees it. A handler receives the bytes the producer published, and the marker attribute never reaches its headers. The marker counts towards the ten attributes of a message, so a binary payload leaves nine for the service's own headers. SQS refuses an empty body, and so does the in-process account.
A handler that reads the bytes itself takes a #[derive(Deserialized)] newtype over &[u8], and no codec runs.
The type borrows the delivery's buffer, so nothing is copied.
Example
The handler stores thumbnails, raw image bytes that SQS would not take as text.
- Macros
- Manual
/// A thumbnail as the producer sent it: raw image bytes, read without a codec.
#[derive(Deserialized)]
struct Thumbnail<'a>(&'a [u8]);
#[subscriber(SqsQueue)]
async fn store(thumbnail: &Thumbnail<'_>) -> HandlerOutcome {
tracing::info!(bytes = thumbnail.0.len(), "thumbnail stored");
HandlerOutcome::ack()
}
/// A thumbnail as the producer sent it: raw image bytes, read without a codec.
struct Thumbnail<'a>(&'a [u8]);
impl Deserialized for Thumbnail<'_> {
type Output<'a> = Thumbnail<'a>;
type Error = Infallible;
fn from_payload(payload: &[u8]) -> Result<Thumbnail<'_>, Self::Error> {
Ok(Thumbnail(payload))
}
}
// Routes the type onto the lane of payloads that read themselves.
impl Input for Thumbnail<'_> {
type Axis = SoloDeserialized<Thumbnail<'static>>;
}
struct Store;
// For every lifetime of the payload it borrows.
impl<'p> Handle<Thumbnail<'p>> for Store {
fn handle(
&self,
thumbnail: &Thumbnail<'p>,
_outs: &(),
_ctx: &mut Context<'_>,
) -> impl Future<Output = Result<(), HandlerOutcome>> {
tracing::info!(bytes = thumbnail.0.len(), "thumbnail stored");
ready(Ok(()))
}
}