1#![feature(impl_trait_in_assoc_type)]
2
3use serde::{Deserialize, Serialize};
4use thiserror::Error;
5use tokio::io;
6use tosic_http::prelude::HttpResponse;
7use tosic_http::server::builder::HttpServerBuilder;
8use tosic_http_macro::get;
9use tracing::dispatcher::SetGlobalDefaultError;
10
11mod logger {
12 use crate::HttpServerError;
13 #[cfg(feature = "log-subscriber")]
14 use tracing::level_filters::LevelFilter;
15 #[cfg(feature = "log-subscriber")]
16 use tracing_subscriber::fmt::format::FmtSpan;
17 #[cfg(feature = "log-subscriber")]
18 use tracing_subscriber::fmt::Layer as FmtLayer;
19 #[cfg(feature = "log-subscriber")]
20 use tracing_subscriber::layer::SubscriberExt;
21 #[cfg(feature = "log-subscriber")]
22 use tracing_subscriber::{EnvFilter, Layer, Registry};
23
24 #[cfg(feature = "log-subscriber")]
25 pub fn init_tracing() -> Result<(), HttpServerError> {
26 let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
27 #[cfg(not(debug_assertions))]
28 let level = LevelFilter::INFO;
29
30 #[cfg(debug_assertions)]
31 let level = LevelFilter::DEBUG;
32
33 EnvFilter::builder()
34 .with_default_directive(level.into())
35 .from_env_lossy()
36 });
37 let def_layer = FmtLayer::new()
38 .with_line_number(true)
39 .with_span_events(FmtSpan::CLOSE)
40 .with_level(true)
41 .with_target(true)
42 .with_thread_names(true)
43 .with_thread_ids(true)
44 .compact()
45 .with_filter(filter);
46
47 let subscriber = Registry::default().with(def_layer);
48
49 tracing::subscriber::set_global_default(subscriber)?;
50
51 Ok(())
52 }
53
54 #[cfg(all(feature = "console-subscriber", not(feature = "log-subscriber")))]
55 pub fn init_tracing() -> Result<(), HttpServerError> {
56 console_subscriber::init();
57
58 Ok(())
59 }
60}
61
62#[derive(Debug, Error)]
63enum HttpServerError {
64 #[error(transparent)]
65 Tracing(#[from] SetGlobalDefaultError),
66 #[error(transparent)]
67 Io(#[from] io::Error),
68}
69
70#[derive(Debug, Serialize, Deserialize)]
71pub struct Device {
72 pub id: i32,
73 pub mac: String,
74 pub firmware: String,
75}
76
77#[get("/api/devices")]
78async fn devices() -> HttpResponse {
79 let devices = [
80 Device {
81 id: 1,
82 mac: String::from("5F-33-CC-1F-43-82"),
83 firmware: String::from("2.1.6"),
84 },
85 Device {
86 id: 2,
87 mac: String::from("EF-2B-C4-F5-D6-34"),
88 firmware: String::from("2.1.5"),
89 },
90 Device {
91 id: 3,
92 mac: String::from("62-46-13-B7-B3-A1"),
93 firmware: String::from("3.0.0"),
94 },
95 Device {
96 id: 4,
97 mac: String::from("96-A8-DE-5B-77-14"),
98 firmware: String::from("1.0.1"),
99 },
100 Device {
101 id: 5,
102 mac: String::from("7E-3B-62-A6-09-12"),
103 firmware: String::from("3.5.6"),
104 },
105 ];
106
107 HttpResponse::Ok().json(&devices)
108}
109
110#[tokio::main]
111async fn main() -> Result<(), HttpServerError> {
112 logger::init_tracing()?;
113
114 let server = HttpServerBuilder::default()
115 .bind("0.0.0.0:4221")
116 .service(devices)
117 .build()
118 .await?;
119
120 match server.serve().await {
121 Ok(_) => (),
122 Err(e) => panic!("Failed to serve: {}", e),
123 }
124
125 Ok(())
126}