relay_server/endpoints/
attachments.rs1use 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}