1use crate::makepad_micro_serde::*;
2use crate::makepad_live_id::*;
3use std::sync::mpsc::{channel, Receiver, Sender};
4use std::collections::BTreeMap;
5use std::str;
6
7#[derive(Clone, Debug)]
8pub struct NetworkResponseItem{
9 pub request_id: LiveId,
10 pub response: NetworkResponse,
11}
12
13pub type NetworkResponsesEvent = Vec<NetworkResponseItem>;
14
15#[derive(Clone, Debug)]
16pub struct HttpError{
17 pub message: String,
18 pub metadata_id: LiveId
19}
20
21
22#[derive(Clone, Debug)]
23pub struct HttpProgress{
24 pub loaded:u64,
25 pub total:u64,
26}
27
28#[derive(Clone, Debug)]
29pub enum NetworkResponse{
30 HttpRequestError(HttpError),
31 HttpResponse(HttpResponse),
32 HttpStreamResponse(HttpResponse),
33 HttpStreamComplete(HttpResponse),
34 HttpProgress(HttpProgress),
35}
36pub struct NetworkResponseChannel {
54 pub receiver: Receiver<NetworkResponseItem>,
55 pub sender: Sender<NetworkResponseItem>,
56}
57
58impl Default for NetworkResponseChannel {
59 fn default() -> Self {
60 let (sender, receiver) = channel();
61 Self {
62 sender,
63 receiver
64 }
65 }
66}
67
68
69#[derive(PartialEq, Debug)]
70pub struct HttpRequest {
71 pub metadata_id: LiveId,
72 pub url: String,
73 pub method: HttpMethod,
74 pub headers: BTreeMap<String, Vec<String>>,
75 pub ignore_ssl_cert: bool,
76 pub is_streaming: bool,
77 pub body: Option<Vec<u8>>,
78}
79
80#[derive(Debug)]
81pub struct SplitUrl<'a>{
82 pub proto: &'a str,
83 pub host: &'a str,
84 pub port: &'a str,
85 pub file: &'a str,
86 pub hash: &'a str,
87}
88
89impl HttpRequest {
90 pub fn new(url: String, method: HttpMethod) -> Self {
91 HttpRequest {
92 metadata_id: LiveId(0),
93 url,
94 method,
95 is_streaming: false,
96 ignore_ssl_cert: false,
97 headers: BTreeMap::new(),
98 body: None
99 }
100 }
101
102 pub fn split_url(&self)->SplitUrl{
103 let (proto, rest) = self.url.split_once("://").unwrap_or((&self.url, "http://"));
104 let (host, port, rest) = if let Some((host, rest)) = rest.split_once(":"){
105 let (port, rest) = rest.split_once("/").unwrap_or((rest, ""));
106 (host, port, rest)
107 }
108 else{
109 let (host, rest) = rest.split_once("/").unwrap_or((rest, ""));
110 (host,match proto{
111 "http"|"ws"=>"80",
112 "https"|"wss"=>"443",
113 _=>"80"
114 },rest)
115 };
116 let (file, hash) = rest.split_once("#").unwrap_or((rest, ""));
117 return SplitUrl{
118 proto,
119 host,
120 port,
121 file,
122 hash
123 }
124 }
125
126 pub fn set_ignore_ssl_cert(&mut self){
127 self.ignore_ssl_cert = true
128 }
129
130 pub fn set_is_streaming(&mut self){
131 self.is_streaming = true
132 }
133
134 pub fn set_metadata_id(&mut self, id: LiveId){
135 self.metadata_id = id;
136 }
137
138 pub fn set_header(&mut self, name: String, value: String) {
139 let entry = self.headers.entry(name).or_insert(Vec::new());
140 entry.push(value);
141 }
142
143 pub fn get_headers_string(&self) -> String {
144 let mut headers_string = String::new();
145 for (key, value) in self.headers.iter() {
146 headers_string.push_str(&format!("{}: {}\r\n", key, value.join(",")));
147 }
148 headers_string
149 }
150
151 pub fn set_body(&mut self, body: Vec<u8>) {
152 self.body = Some(body);
153 }
154
155 pub fn set_body_string(&mut self, v: &str) {
156 self.body = Some(v.as_bytes().to_vec());
157 }
158
159 pub fn set_json_body<T: SerJson>(&mut self, body: T) {
160 let json_body = body.serialize_json();
161 let serialized_body = json_body.into_bytes();
162 self.body = Some(serialized_body);
163 }
164
165 pub fn set_string_body(&mut self, body: String) {
166 self.body = Some(body.into_bytes());
167 }
168}
169
170#[derive(Debug, Clone)]
171pub struct HttpResponse {
172 pub metadata_id: LiveId,
173 pub status_code: u16,
174 pub headers: BTreeMap<String, Vec<String>>,
175 pub body: Option<Vec<u8>>,
176}
177
178impl HttpResponse {
179 pub fn new(metadata_id: LiveId, status_code: u16, string_headers: String, body: Option<Vec<u8>>) -> Self {
180 HttpResponse {
181 metadata_id,
182 status_code,
183 headers: HttpResponse::parse_headers(string_headers),
184 body
185 }
186 }
187
188 pub fn set_header(&mut self, name: String, value: String) {
189 let entry = self.headers.entry(name).or_insert(Vec::new());
190 entry.push(value);
191 }
192
193 pub fn get_body(&self) -> Option<&Vec<u8>> {
194 self.body.as_ref()
195 }
196
197 pub fn get_string_body(&self) -> Option<String> {
198 if let Some(body) = self.body.as_ref() {
199 if let Ok(utf8) = String::from_utf8(body.to_vec()){
200 return Some(utf8)
201 }
202 }
203 None
204 }
205
206 pub fn get_json_body<T: DeJson>(&self) -> Result<T, DeJsonErr> {
208 if let Some(body) = self.body.as_ref() {
209 let json = str::from_utf8(&body).unwrap();
210 DeJson::deserialize_json(&json)
211 } else {
212 Err(DeJsonErr{
213 msg:"No body present".to_string(),
214 line:0,
215 col:0
216 })
217 }
218 }
219
220 fn parse_headers(headers_string: String) -> BTreeMap<String, Vec<String>> {
221 let mut headers = BTreeMap::new();
222 for line in headers_string.lines() {
223 let mut split = line.split(":");
224 let key = split.next().unwrap();
225 let values = split.next().unwrap().to_string();
226 for val in values.split(",") {
227 let entry = headers.entry(key.to_string()).or_insert(Vec::new());
228 entry.push(val.to_string());
229 }
230 }
231 headers
232 }
233}
234
235#[derive(PartialEq, Debug)]
236pub enum HttpMethod{
237 GET,
238 HEAD,
239 POST,
240 PUT,
241 DELETE,
242 CONNECT,
243 OPTIONS,
244 TRACE,
245 PATCH
246}
247
248impl HttpMethod {
249 pub fn to_string(&self) -> &str {
250 match self {
251 Self::GET => "GET",
252 Self::HEAD => "HEAD",
253 Self::POST => "POST",
254 Self::PUT => "PUT",
255 Self::DELETE => "DELETE",
256 Self::CONNECT => "CONNECT",
257 Self::OPTIONS => "OPTIONS",
258 Self::TRACE => "TRACE",
259 Self::PATCH => "PATCH",
260 }
261 }
262}