mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
reorganize client Request
This commit is contained in:
parent
9d690d3137
commit
4665a7ff6a
9 changed files with 164 additions and 115 deletions
|
|
@ -1,17 +1,17 @@
|
|||
pub mod driver;
|
||||
mod feature;
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
pub mod status;
|
||||
|
||||
// Children dependencies
|
||||
pub use driver::Driver;
|
||||
use feature::Feature;
|
||||
pub use request::Request;
|
||||
pub use response::Response;
|
||||
pub use status::Status;
|
||||
|
||||
// Global dependencies
|
||||
use crate::{tool::now, Profile};
|
||||
use gtk::{gio::Cancellable, prelude::CancellableExt};
|
||||
use gtk::{gio::Cancellable, glib::Priority, prelude::CancellableExt};
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
rc::Rc,
|
||||
|
|
@ -42,16 +42,15 @@ impl Client {
|
|||
|
||||
/// Begin new request
|
||||
/// * the `query` as string, to support system routes (e.g. `source:` prefix)
|
||||
pub fn request_async(&self, request: &str, callback: impl FnOnce(Response) + 'static) {
|
||||
pub fn request_async(&self, query: &str, callback: impl FnOnce(Response) + 'static) {
|
||||
// Update client status
|
||||
self.status.replace(Status::Request {
|
||||
time: now(),
|
||||
value: request.to_string(),
|
||||
value: query.to_string(),
|
||||
});
|
||||
|
||||
self.driver.feature_async(
|
||||
Feature::from_string(request),
|
||||
self.new_cancellable(),
|
||||
self.driver.request_async(
|
||||
Request::build(query, None, self.new_cancellable(), Priority::DEFAULT),
|
||||
callback,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,14 @@ pub mod status;
|
|||
pub use status::Status;
|
||||
|
||||
// Global dependencies
|
||||
use super::{feature::Request, response, response::Failure, Feature, Response};
|
||||
use crate::{tool::now, Profile};
|
||||
use gtk::{
|
||||
gio::{Cancellable, SocketClientEvent},
|
||||
prelude::SocketClientExt,
|
||||
use super::{
|
||||
request::{feature::Protocol, Feature},
|
||||
response,
|
||||
response::Failure,
|
||||
Request, Response,
|
||||
};
|
||||
use crate::{tool::now, Profile};
|
||||
use gtk::{gio::SocketClientEvent, prelude::SocketClientExt};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Driver {
|
||||
|
|
@ -61,19 +63,19 @@ impl Driver {
|
|||
|
||||
/// Make new async `Feature` request
|
||||
/// * return `Response` in callback function
|
||||
pub fn feature_async(
|
||||
&self,
|
||||
feature: Feature,
|
||||
cancellable: Cancellable,
|
||||
callback: impl FnOnce(Response) + 'static,
|
||||
) {
|
||||
match feature {
|
||||
Feature::Download { request } => match request {
|
||||
Request::Gemini { uri } => gemini::request_async(
|
||||
pub fn request_async(&self, request: Request, callback: impl FnOnce(Response) + 'static) {
|
||||
match request.feature {
|
||||
Feature::Download(protocol) => match protocol {
|
||||
Protocol::Gemini {
|
||||
uri,
|
||||
cancellable,
|
||||
priority,
|
||||
} => gemini::request_async(
|
||||
&self.profile,
|
||||
&self.gemini,
|
||||
uri.clone(),
|
||||
cancellable.clone(),
|
||||
priority,
|
||||
move |result| {
|
||||
callback(match result {
|
||||
Ok(response) => Response::Download {
|
||||
|
|
@ -91,24 +93,38 @@ impl Driver {
|
|||
message: "Download feature yet not supported for this request".to_string(),
|
||||
})), // @TODO or maybe panic as unexpected
|
||||
},
|
||||
Feature::Default { request } => match request {
|
||||
Request::Gemini { uri } => gemini::request_async(
|
||||
Feature::Default(protocol) => match protocol {
|
||||
Protocol::Gemini {
|
||||
uri,
|
||||
cancellable,
|
||||
priority,
|
||||
} => gemini::request_async(
|
||||
&self.profile,
|
||||
&self.gemini,
|
||||
uri.clone(),
|
||||
cancellable.clone(),
|
||||
move |result| gemini::handle(result, uri, cancellable, false, callback),
|
||||
priority,
|
||||
move |result| {
|
||||
gemini::handle(result, uri, cancellable, priority, false, callback)
|
||||
},
|
||||
),
|
||||
Request::Titan { .. } => todo!(),
|
||||
Request::Undefined => todo!(),
|
||||
Protocol::Titan { .. } => todo!(),
|
||||
Protocol::Unsupported => todo!(),
|
||||
},
|
||||
Feature::Source { request } => match request {
|
||||
Request::Gemini { uri } => gemini::request_async(
|
||||
Feature::Source(protocol) => match protocol {
|
||||
Protocol::Gemini {
|
||||
uri,
|
||||
cancellable,
|
||||
priority,
|
||||
} => gemini::request_async(
|
||||
&self.profile,
|
||||
&self.gemini,
|
||||
uri.clone(),
|
||||
cancellable.clone(),
|
||||
move |result| gemini::handle(result, uri, cancellable, true, callback),
|
||||
priority,
|
||||
move |result| {
|
||||
gemini::handle(result, uri, cancellable, priority, true, callback)
|
||||
},
|
||||
),
|
||||
_ => callback(Response::Failure(Failure::Error {
|
||||
message: "Source view feature yet not supported for this request".to_string(),
|
||||
|
|
|
|||
|
|
@ -14,12 +14,13 @@ pub fn request_async(
|
|||
client: &Rc<ggemini::Client>,
|
||||
uri: Uri,
|
||||
cancellable: Cancellable,
|
||||
priority: Priority,
|
||||
callback: impl FnOnce(Result<ggemini::client::Response, ggemini::client::Error>) + 'static,
|
||||
) {
|
||||
let request = uri.to_string();
|
||||
client.request_async(
|
||||
ggemini::client::Request::gemini(uri),
|
||||
Priority::DEFAULT,
|
||||
priority,
|
||||
cancellable,
|
||||
// Search for user certificate match request
|
||||
// * @TODO this feature does not support multi-protocol yet
|
||||
|
|
@ -40,6 +41,7 @@ pub fn handle(
|
|||
result: Result<ggemini::client::connection::Response, ggemini::client::Error>,
|
||||
base: Uri,
|
||||
cancellable: Cancellable,
|
||||
priority: Priority,
|
||||
is_source_request: bool, // @TODO yet partial implementation
|
||||
callback: impl FnOnce(Response) + 'static,
|
||||
) {
|
||||
|
|
@ -66,7 +68,7 @@ pub fn handle(
|
|||
Some(mime) => match mime.as_str() {
|
||||
"text/gemini" => Text::from_stream_async(
|
||||
response.connection.stream(),
|
||||
Priority::DEFAULT,
|
||||
priority,
|
||||
cancellable,
|
||||
move |result| match result {
|
||||
Ok(text) => callback(Response::TextGemini {
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
pub mod request;
|
||||
pub use request::Request;
|
||||
|
||||
/// Feature wrapper for client `Request`
|
||||
pub enum Feature {
|
||||
/// Common feature for protocol selected (e.g. browser view)
|
||||
Default { request: Request },
|
||||
/// Download request with externally selected method (e.g. to file)
|
||||
Download { request: Request },
|
||||
/// View request as the source (like `source-view`)
|
||||
Source { request: Request },
|
||||
}
|
||||
|
||||
impl Feature {
|
||||
// Constructors
|
||||
|
||||
/// Parse new `Self` from string
|
||||
pub fn from_string(query: &str) -> Self {
|
||||
if let Some(postfix) = query.strip_prefix("download:") {
|
||||
return Self::Download {
|
||||
request: Request::from_string(postfix),
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(postfix) = query.strip_prefix("source:") {
|
||||
return Self::Source {
|
||||
request: Request::from_string(postfix),
|
||||
};
|
||||
}
|
||||
|
||||
Self::Default {
|
||||
request: Request::from_string(query),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
mod search;
|
||||
|
||||
// Global dependencies
|
||||
use gtk::glib::{Uri, UriFlags};
|
||||
|
||||
pub enum Request {
|
||||
Gemini { uri: Uri },
|
||||
Titan { uri: Uri },
|
||||
Undefined,
|
||||
}
|
||||
|
||||
impl Request {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self` from parsable request string
|
||||
pub fn from_string(request: &str) -> Self {
|
||||
match Uri::parse(request, UriFlags::NONE) {
|
||||
Ok(uri) => match uri.scheme().as_str() {
|
||||
"gemini" => Self::Gemini { uri },
|
||||
"titan" => Self::Titan { uri },
|
||||
_ => Self::Undefined,
|
||||
},
|
||||
// Search request if the request could not be parsed as the valid [URI](https://docs.gtk.org/glib/struct.Uri.html)
|
||||
// * @TODO implement DNS resolver lookup before assign this option
|
||||
Err(_) => Self::Gemini {
|
||||
uri: search::tgls(request),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
//! Search providers [Uri](https://docs.gtk.org/glib/struct.Uri.html) asset
|
||||
|
||||
// Global dependencies
|
||||
use gtk::glib::{Uri, UriFlags};
|
||||
|
||||
/// Build TGLS [Uri](https://docs.gtk.org/glib/struct.Uri.html)
|
||||
pub fn tgls(query: &str) -> Uri {
|
||||
Uri::build(
|
||||
UriFlags::NONE,
|
||||
"gemini",
|
||||
None,
|
||||
Some("tlgs.one"),
|
||||
1965,
|
||||
"search",
|
||||
Some(&Uri::escape_string(query, None, false)), // @TODO is `escape_string` really wanted in `build` context?
|
||||
None,
|
||||
)
|
||||
}
|
||||
28
src/app/browser/window/tab/item/page/client/request.rs
Normal file
28
src/app/browser/window/tab/item/page/client/request.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
pub mod feature;
|
||||
pub use feature::Feature;
|
||||
|
||||
use gtk::{gio::Cancellable, glib::Priority};
|
||||
|
||||
/// Request data wrapper for `Client`
|
||||
pub struct Request {
|
||||
pub feature: Feature,
|
||||
/// Requests chain in order to process redirection rules
|
||||
pub referrer: Vec<Request>,
|
||||
}
|
||||
|
||||
impl Request {
|
||||
// Constructors
|
||||
|
||||
/// Build new `Self`
|
||||
pub fn build(
|
||||
query: &str,
|
||||
referrer: Option<Vec<Request>>,
|
||||
cancellable: Cancellable,
|
||||
priority: Priority,
|
||||
) -> Self {
|
||||
Self {
|
||||
feature: Feature::build(query, cancellable, priority),
|
||||
referrer: referrer.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
pub mod protocol;
|
||||
pub use protocol::Protocol;
|
||||
|
||||
use gtk::{gio::Cancellable, glib::Priority};
|
||||
|
||||
/// Feature wrapper for client `Request`
|
||||
pub enum Feature {
|
||||
Default(Protocol),
|
||||
Download(Protocol),
|
||||
Source(Protocol),
|
||||
// @TODO System(Action)
|
||||
}
|
||||
|
||||
impl Feature {
|
||||
// Constructors
|
||||
|
||||
/// Parse new `Self` from string
|
||||
pub fn build(query: &str, cancellable: Cancellable, priority: Priority) -> Self {
|
||||
if let Some(postfix) = query.strip_prefix("download:") {
|
||||
return Self::Download(Protocol::build(postfix, cancellable, priority));
|
||||
}
|
||||
|
||||
if let Some(postfix) = query.strip_prefix("source:") {
|
||||
return Self::Source(Protocol::build(postfix, cancellable, priority));
|
||||
}
|
||||
|
||||
Self::Default(Protocol::build(query, cancellable, priority))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
// Global dependencies
|
||||
use gtk::{
|
||||
gio::Cancellable,
|
||||
glib::{Priority, Uri, UriFlags},
|
||||
};
|
||||
|
||||
pub enum Protocol {
|
||||
Gemini {
|
||||
uri: Uri,
|
||||
cancellable: Cancellable,
|
||||
priority: Priority,
|
||||
},
|
||||
Titan {
|
||||
uri: Uri,
|
||||
cancellable: Cancellable,
|
||||
priority: Priority,
|
||||
},
|
||||
Unsupported,
|
||||
}
|
||||
|
||||
impl Protocol {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self` from parsable request string
|
||||
pub fn build(query: &str, cancellable: Cancellable, priority: Priority) -> Self {
|
||||
match Uri::parse(query, UriFlags::NONE) {
|
||||
Ok(uri) => match uri.scheme().as_str() {
|
||||
"gemini" => Self::Gemini {
|
||||
uri,
|
||||
cancellable,
|
||||
priority,
|
||||
},
|
||||
"titan" => Self::Titan {
|
||||
uri,
|
||||
cancellable,
|
||||
priority,
|
||||
},
|
||||
_ => Self::Unsupported,
|
||||
},
|
||||
// Search request if the request could not be parsed as the valid [URI](https://docs.gtk.org/glib/struct.Uri.html)
|
||||
// * @TODO implement DNS lookup before apply this option
|
||||
Err(_) => Self::Gemini {
|
||||
uri: Uri::build(
|
||||
UriFlags::NONE,
|
||||
"gemini",
|
||||
None,
|
||||
Some("tlgs.one"),
|
||||
1965,
|
||||
"search",
|
||||
Some(&Uri::escape_string(query, None, false)), // @TODO is `escape_string` really wanted in `build` context?
|
||||
None,
|
||||
),
|
||||
cancellable,
|
||||
priority,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue