MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / transform_body

Function transform_body

src/environmentd/src/http/webhook.rs:203–253  ·  view source on GitHub ↗

Transforms the body of a webhook request into a `Vec `.

(
    body: &[u8],
    format: &WebhookBodyFormat,
)

Source from the content-addressed store, hash-verified

201
202/// Transforms the body of a webhook request into a `Vec<BodyRow>`.
203fn transform_body(
204 body: &[u8],
205 format: &WebhookBodyFormat,
206) -> Result<Vec<BodyRow>, AppendWebhookError> {
207 let rows = match format {
208 WebhookBodyFormat::Bytes => {
209 vec![Row::pack_slice(&[Datum::Bytes(body)])]
210 }
211 WebhookBodyFormat::Text => {
212 let s = std::str::from_utf8(body)
213 .map_err(|m| AppendWebhookError::InvalidUtf8Body { msg: m.to_string() })?;
214 vec![Row::pack_slice(&[Datum::String(s)])]
215 }
216 WebhookBodyFormat::Json { array } => {
217 let objects = serde_json::Deserializer::from_slice(body)
218 // Automatically expand multiple JSON objects delimited by whitespace, e.g.
219 // newlines, into a single batch.
220 .into_iter::<serde_json::Value>()
221 // Optionally expand a JSON array into separate rows, if requested.
222 .flat_map(|value| match value {
223 Ok(serde_json::Value::Array(inners)) if *array => {
224 itertools::Either::Left(inners.into_iter().map(Result::Ok))
225 }
226 value => itertools::Either::Right(std::iter::once(value)),
227 })
228 .collect::<Result<Vec<_>, _>>()
229 .map_err(|m| AppendWebhookError::InvalidJsonBody { msg: m.to_string() })?;
230
231 // Note: `into_iter()` should be re-using the underlying allocation of the `objects`
232 // vector, and it's more readable to split these into separate iterators.
233 let rows = objects
234 .into_iter()
235 // Map a JSON object into a Row.
236 .map(|o| {
237 let row = Jsonb::from_serde_json(o)
238 .map_err(|m| AppendWebhookError::InvalidJsonBody { msg: m.to_string() })?
239 .into_row();
240 Ok::<_, AppendWebhookError>(row)
241 })
242 .collect::<Result<_, _>>()?;
243
244 rows
245 }
246 };
247
248 // A `Row` cannot describe its schema without unpacking it. To add some safety we wrap the
249 // returned `Row`s in a newtype to signify they already have the "body" column packed.
250 let body_rows = rows.into_iter().map(BodyRow).collect();
251
252 Ok(body_rows)
253}
254
255/// Pack the headers of a request into a [`Row`].
256fn pack_header(

Callers 1

pack_rowsFunction · 0.85

Calls 6

to_stringMethod · 0.45
flat_mapMethod · 0.45
mapMethod · 0.45
into_iterMethod · 0.45
into_rowMethod · 0.45
collectMethod · 0.45

Tested by

no test coverage detected