Skip to content

Commit

Permalink
feat: add embedded-svc based http transport (getsentry#654)
Browse files Browse the repository at this point in the history
embedded-svc is used on esp32 for doing https
  • Loading branch information
madmo authored Apr 16, 2024
1 parent 0b4b06c commit 8c701e8
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
4 changes: 4 additions & 0 deletions sentry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ ureq = ["dep:ureq", "httpdate"]
# transport settings
native-tls = ["dep:native-tls", "reqwest?/default-tls", "ureq?/native-tls"]
rustls = ["dep:rustls", "reqwest?/rustls-tls", "ureq?/tls", "webpki-roots"]
embedded-svc-http = ["dep:embedded-svc", "dep:esp-idf-svc"]

[dependencies]
sentry-core = { version = "0.32.3", path = "../sentry-core", features = [
Expand Down Expand Up @@ -82,6 +83,9 @@ rustls = { version = "0.21.2", optional = true, features = [
"dangerous_configuration",
] }
webpki-roots = { version = "0.25.1", optional = true }
embedded-svc = { version = "0.27.1", optional = true }
[target.'cfg(target_os = "espidf")'.dependencies]
esp-idf-svc = { version = "0.48.1", optional = true }

[dev-dependencies]
sentry-anyhow = { path = "../sentry-anyhow" }
Expand Down
64 changes: 64 additions & 0 deletions sentry/src/transports/embedded_svc_http.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::{sentry_debug, ClientOptions, Transport};
use embedded_svc::http::client::Client as HttpClient;
use esp_idf_svc::{http::client::EspHttpConnection, io::Write};

/// Transport using the embedded-svc http client
pub struct EmbeddedSVCHttpTransport {
options: ClientOptions,
}

impl EmbeddedSVCHttpTransport {
/// Creates a new transport
pub fn new(options: &ClientOptions) -> Self {
Self {
options: options.clone(),
}
}
}

impl EmbeddedSVCHttpTransport {
fn send_envelope(
&self,
envelope: sentry_core::Envelope,
) -> Result<(), Box<dyn std::error::Error>> {
let dsn = self
.options
.dsn
.as_ref()
.ok_or_else(|| "No DSN specified")?;
let user_agent = &self.options.user_agent;
let auth = dsn.to_auth(Some(user_agent)).to_string();
let headers = [("X-Sentry-Auth", auth.as_str())];
let url = dsn.envelope_api_url();

let mut body = Vec::new();
envelope.to_writer(&mut body)?;

let config = esp_idf_svc::http::client::Configuration {
use_global_ca_store: true,
crt_bundle_attach: Some(esp_idf_svc::sys::esp_crt_bundle_attach),
..Default::default()
};

let mut client = HttpClient::wrap(EspHttpConnection::new(&config)?);

let mut request = client.post(url.as_str(), &headers)?;
request.write_all(&body)?;
request.flush()?;
let mut response = request.submit()?;

// read the whole response
let mut buf = [0u8; 1024];
while response.read(&mut buf)? > 0 {}

Ok(())
}
}

impl Transport for EmbeddedSVCHttpTransport {
fn send_envelope(&self, envelope: sentry_core::Envelope) {
if let Err(err) = self.send_envelope(envelope) {
sentry_debug!("Failed to send envelope: {}", err);
}
}
}
21 changes: 21 additions & 0 deletions sentry/src/transports/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ mod reqwest;
#[cfg(feature = "reqwest")]
pub use self::reqwest::ReqwestHttpTransport;

#[cfg(all(target_os = "espidf", feature = "embedded-svc-http"))]
mod embedded_svc_http;
#[cfg(all(target_os = "espidf", feature = "embedded-svc-http"))]
pub use self::embedded_svc_http::EmbeddedSVCHttpTransport;

#[cfg(feature = "curl")]
mod curl;
#[cfg(feature = "curl")]
Expand All @@ -38,6 +43,7 @@ type DefaultTransport = ReqwestHttpTransport;

#[cfg(all(
feature = "curl",
not(all(target_os = "espidf", feature = "embedded-svc-http")),
not(feature = "reqwest"),
not(feature = "surf"),
not(feature = "ureq")
Expand All @@ -46,6 +52,7 @@ type DefaultTransport = CurlHttpTransport;

#[cfg(all(
feature = "surf",
not(all(target_os = "espidf", feature = "embedded-svc-http")),
not(feature = "reqwest"),
not(feature = "curl"),
not(feature = "ureq")
Expand All @@ -54,14 +61,26 @@ type DefaultTransport = SurfHttpTransport;

#[cfg(all(
feature = "ureq",
not(all(target_os = "espidf", feature = "embedded-svc-http")),
not(feature = "reqwest"),
not(feature = "curl"),
not(feature = "surf")
))]
type DefaultTransport = UreqHttpTransport;

#[cfg(all(
target_os = "espidf",
feature = "embedded-svc-http",
not(feature = "reqwest"),
not(feature = "curl"),
not(feature = "surf"),
not(feature = "ureq")
))]
type DefaultTransport = EmbeddedSVCHttpTransport;

/// The default http transport.
#[cfg(any(
all(target_os = "espidf", feature = "embedded-svc-http"),
feature = "reqwest",
feature = "curl",
feature = "surf",
Expand All @@ -80,6 +99,7 @@ pub struct DefaultTransportFactory;
impl TransportFactory for DefaultTransportFactory {
fn create_transport(&self, options: &ClientOptions) -> Arc<dyn Transport> {
#[cfg(any(
all(target_os = "espidf", feature = "embedded-svc-http"),
feature = "reqwest",
feature = "curl",
feature = "surf",
Expand All @@ -89,6 +109,7 @@ impl TransportFactory for DefaultTransportFactory {
Arc::new(HttpTransport::new(options))
}
#[cfg(not(any(
all(target_os = "espidf", feature = "embedded-svc-http"),
feature = "reqwest",
feature = "curl",
feature = "surf",
Expand Down

0 comments on commit 8c701e8

Please sign in to comment.