relay_server/endpoints/
attachments.rs

1use axum::extract::Path;
2use axum::http::StatusCode;
3use axum::response::IntoResponse;
4use multer::Field;
5use relay_config::Config;
6use relay_event_schema::protocol::EventId;
7use serde::Deserialize;
8
9use crate::endpoints::common::{self, BadStoreRequest};
10use crate::envelope::{AttachmentType, Envelope, Item};
11use crate::extractors::RequestMeta;
12use crate::service::ServiceState;
13use crate::utils::{AttachmentStrategy, ConstrainedMultipart, read_attachment_bytes_into_item};
14
15#[derive(Debug, Deserialize)]
16pub struct AttachmentPath {
17    event_id: EventId,
18}
19
20struct AttachmentsAttachmentStrategy;
21
22impl AttachmentStrategy for AttachmentsAttachmentStrategy {
23    fn infer_type(&self, _: &Field) -> AttachmentType {
24        AttachmentType::default()
25    }
26
27    fn add_to_item(
28        &self,
29        field: Field<'static>,
30        item: Item,
31        config: &Config,
32    ) -> impl Future<Output = Result<Option<Item>, multer::Error>> + Send {
33        read_attachment_bytes_into_item(field, item, config, false)
34    }
35}
36
37async fn extract_envelope(
38    meta: RequestMeta,
39    path: AttachmentPath,
40    multipart: ConstrainedMultipart,
41    config: &Config,
42) -> Result<Box<Envelope>, BadStoreRequest> {
43    let items = multipart
44        .items(config, AttachmentsAttachmentStrategy)
45        .await?;
46
47    let mut envelope = Envelope::from_request(Some(path.event_id), meta);
48    for item in items {
49        envelope.add_item(item);
50    }
51
52    Ok(envelope)
53}
54
55pub async fn handle(
56    state: ServiceState,
57    meta: RequestMeta,
58    Path(path): Path<AttachmentPath>,
59    multipart: ConstrainedMultipart,
60) -> axum::response::Result<impl IntoResponse> {
61    let envelope = extract_envelope(meta, path, multipart, state.config()).await?;
62    common::handle_envelope(&state, envelope)
63        .await?
64        .ignore_rate_limits();
65    Ok(StatusCode::CREATED)
66}