makepad_platform/event/
network.rs

1use crate::makepad_micro_serde::*;
2use crate::makepad_live_id::*;
3use std::sync::mpsc::{channel, Receiver, Sender};
4use std::collections::BTreeMap;
5use std::str;
6use crate::event::Event;
7
8#[derive(Clone, Debug)]
9pub struct NetworkResponseEvent {
10    pub request_id: LiveId,
11    pub response: NetworkResponse,
12}
13
14#[derive(Clone, Debug)]
15pub enum NetworkResponse{
16    HttpRequestError(String),
17    HttpResponse(HttpResponse),
18    HttpProgress{loaded:u32, total:u32},
19    WebSocketClose,
20    WebSocketOpen,
21    WebSocketError(String),
22    WebSocketString(String),
23    WebSocketBinary(Vec<u8>)
24}
25
26pub struct NetworkResponseIter<I> {
27    iter: Option<I>,
28}
29
30impl<I> Iterator for NetworkResponseIter<I> where I: Iterator {
31    type Item = I::Item;
32    
33    fn next(&mut self) -> Option<I::Item> {
34        match &mut self.iter{
35            None=>None,
36            Some(v)=>v.next()
37        }
38    }
39}
40
41impl Event{
42    pub fn network_responses(&self) -> NetworkResponseIter<std::slice::Iter<'_, NetworkResponseEvent>>{
43        match self{
44            Event::NetworkResponses(responses)=>{
45                NetworkResponseIter{
46                    iter:Some(responses.iter())
47                }
48            }
49            _=>{
50                // return empty thing
51                NetworkResponseIter{iter:None}
52            }
53        } 
54    }
55}
56
57pub struct NetworkResponseChannel {
58    pub receiver: Receiver<NetworkResponseEvent>,
59    pub sender: Sender<NetworkResponseEvent>,
60}
61
62impl Default for NetworkResponseChannel {
63    fn default() -> Self {
64        let (sender, receiver) = channel();
65        Self {
66            sender,
67            receiver
68        }
69    }
70}
71
72
73#[derive(PartialEq, Debug)]
74pub struct HttpRequest {
75    pub metadata_id: LiveId,
76    pub url: String,
77    pub method: HttpMethod,
78    pub headers: BTreeMap<String, Vec<String>>,
79    pub body: Option<Vec<u8>>,
80}
81
82impl HttpRequest { 
83    pub fn new(url: String, method: HttpMethod) -> Self {
84        HttpRequest {
85            metadata_id: LiveId(0),
86            url,
87            method,
88            headers: BTreeMap::new(),
89            body: None
90        }
91    }
92    
93    pub fn set_metadata_id(&mut self, id: LiveId){
94        self.metadata_id = id;
95    }
96    
97    pub fn set_header(&mut self, name: String, value: String) {
98        let entry = self.headers.entry(name).or_insert(Vec::new());
99        entry.push(value);
100    }
101
102    pub fn get_headers_string(&self) -> String {
103        let mut headers_string = String::new();
104        for (key, value) in self.headers.iter() {
105            headers_string.push_str(&format!("{}: {}\r\n", key, value.join(",")));
106        }
107        headers_string
108    }
109
110    pub fn set_body(&mut self, body: Vec<u8>) {
111        self.body = Some(body);
112    }
113
114    pub fn set_body_string(&mut self, v: &str) {
115        self.body = Some(v.as_bytes().to_vec());
116    }
117
118    pub fn set_json_body<T: SerJson>(&mut self, body: T) {
119       let json_body = body.serialize_json();
120       let serialized_body = json_body.into_bytes();
121       self.body = Some(serialized_body); 
122    }
123
124    pub fn set_string_body(&mut self, body: String) {
125        self.body = Some(body.into_bytes());
126    }
127}
128
129#[derive(Debug, Clone)]
130pub struct HttpResponse {
131    pub metadata_id: LiveId,
132    pub status_code: u16,
133    pub headers: BTreeMap<String, Vec<String>>,
134    pub body: Option<Vec<u8>>,
135}
136
137impl HttpResponse {
138    pub fn new(metadata_id: LiveId, status_code: u16, string_headers: String, body: Option<Vec<u8>>) -> Self {
139        HttpResponse {
140            metadata_id,
141            status_code,
142            headers: HttpResponse::parse_headers(string_headers),
143            body
144        }
145    }
146
147    pub fn set_header(&mut self, name: String, value: String) {
148        let entry = self.headers.entry(name).or_insert(Vec::new());
149        entry.push(value);
150    }
151
152    pub fn get_body(&self) -> Option<&Vec<u8>> {
153        self.body.as_ref()
154    }
155
156    pub fn get_string_body(&self) -> Option<String> {
157        if let Some(body) = self.body.as_ref() {
158            if let Ok(utf8) = String::from_utf8(body.to_vec()){
159                return Some(utf8)
160            }
161        }
162        None
163    }
164
165    // Todo: a more generic function that supports serialization into rust structs from other MIME types
166    pub fn get_json_body<T: DeJson>(&self) -> Result<T, DeJsonErr> { 
167        if let Some(body) = self.body.as_ref() {
168            let json = str::from_utf8(&body).unwrap();
169            DeJson::deserialize_json(&json)
170        } else {
171            Err(DeJsonErr{
172                msg:"No body present".to_string(),
173                line:0,
174                col:0
175            })
176        }
177    }
178
179    fn parse_headers(headers_string: String) -> BTreeMap<String, Vec<String>> {
180        let mut headers = BTreeMap::new();
181        for line in headers_string.lines() {
182            let mut split = line.split(":");
183            let key = split.next().unwrap();
184            let values = split.next().unwrap().to_string();
185            for val in values.split(",") {
186                let entry = headers.entry(key.to_string()).or_insert(Vec::new());
187                entry.push(val.to_string());
188            }
189        }
190        headers
191    }
192}
193
194#[derive(PartialEq, Debug)]
195pub enum HttpMethod{
196    GET,
197    HEAD,
198    POST,
199    PUT,
200    DELETE,
201    CONNECT,
202    OPTIONS,
203    TRACE,
204    PATCH
205}
206
207impl HttpMethod {
208    pub fn to_string(&self) -> &str {
209        match self {
210            Self::GET => "GET",
211            Self::HEAD => "HEAD",
212            Self::POST => "POST",
213            Self::PUT => "PUT",
214            Self::DELETE => "DELETE",
215            Self::CONNECT => "CONNECT",
216            Self::OPTIONS => "OPTIONS",
217            Self::TRACE => "TRACE",
218            Self::PATCH => "PATCH",
219        }
220    }
221}