walker_extras/visitors/send/
csaf.rs1use super::*;
2use crate::csaf::{
3 retrieve::{RetrievalContext, RetrievedAdvisory, RetrievedVisitor},
4 validation::{ValidatedAdvisory, ValidatedVisitor, ValidationContext, ValidationError},
5};
6use csaf_walker::{discover::DiscoveredAdvisory, source::Source};
7use walker_common::retrieve::RetrievalError;
8
9#[derive(Debug, thiserror::Error)]
10pub enum SendRetrievedAdvisoryError<S: Source> {
11 #[error(transparent)]
12 Store(#[from] SendError),
13 #[error(transparent)]
14 Retrieval(#[from] RetrievalError<DiscoveredAdvisory, S>),
15}
16
17impl<S: Source> RetrievedVisitor<S> for SendVisitor {
18 type Error = SendRetrievedAdvisoryError<S>;
19 type Context = ();
20
21 async fn visit_context(&self, _: &RetrievalContext<'_>) -> Result<Self::Context, Self::Error> {
22 Ok(())
23 }
24
25 async fn visit_advisory(
26 &self,
27 _context: &Self::Context,
28 result: Result<RetrievedAdvisory, RetrievalError<DiscoveredAdvisory, S>>,
29 ) -> Result<(), Self::Error> {
30 self.send_retrieved_advisory(result?).await?;
31 Ok(())
32 }
33}
34
35#[allow(clippy::large_enum_variant)]
36#[derive(Debug, thiserror::Error)]
37pub enum SendValidatedAdvisoryError<S: Source> {
38 #[error(transparent)]
39 Store(#[from] SendError),
40 #[error(transparent)]
41 Validation(#[from] ValidationError<S>),
42}
43
44impl<S: Source> ValidatedVisitor<S> for SendVisitor {
45 type Error = SendValidatedAdvisoryError<S>;
46 type Context = ();
47
48 async fn visit_context(&self, _: &ValidationContext<'_>) -> Result<Self::Context, Self::Error> {
49 Ok(())
50 }
51
52 async fn visit_advisory(
53 &self,
54 _context: &Self::Context,
55 result: Result<ValidatedAdvisory, ValidationError<S>>,
56 ) -> Result<(), Self::Error> {
57 self.send_retrieved_advisory(result?.retrieved).await?;
58 Ok(())
59 }
60}
61
62impl SendVisitor {
63 async fn send_retrieved_advisory(&self, advisory: RetrievedAdvisory) -> Result<(), SendError> {
64 log::debug!(
65 "Sending: {} (modified: {:?})",
66 advisory.url,
67 advisory.metadata.last_modification
68 );
69
70 let RetrievedAdvisory {
71 data,
72 discovered: DiscoveredAdvisory { url, .. },
73 ..
74 } = advisory;
75
76 self.send_json(url.as_str(), data).await
77 }
78
79 pub async fn send_json(&self, name: &str, data: Bytes) -> Result<(), SendError> {
80 self.send(name, data, |request| {
81 request.header(header::CONTENT_TYPE, "application/json")
82 })
83 .await
84 }
85}