mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-04-01 17:15:28 +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;
|
pub mod driver;
|
||||||
mod feature;
|
pub mod request;
|
||||||
pub mod response;
|
pub mod response;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
|
|
||||||
// Children dependencies
|
// Children dependencies
|
||||||
pub use driver::Driver;
|
pub use driver::Driver;
|
||||||
use feature::Feature;
|
pub use request::Request;
|
||||||
pub use response::Response;
|
pub use response::Response;
|
||||||
pub use status::Status;
|
pub use status::Status;
|
||||||
|
|
||||||
// Global dependencies
|
// Global dependencies
|
||||||
use crate::{tool::now, Profile};
|
use crate::{tool::now, Profile};
|
||||||
use gtk::{gio::Cancellable, prelude::CancellableExt};
|
use gtk::{gio::Cancellable, glib::Priority, prelude::CancellableExt};
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
|
@ -42,16 +42,15 @@ impl Client {
|
||||||
|
|
||||||
/// Begin new request
|
/// Begin new request
|
||||||
/// * the `query` as string, to support system routes (e.g. `source:` prefix)
|
/// * 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
|
// Update client status
|
||||||
self.status.replace(Status::Request {
|
self.status.replace(Status::Request {
|
||||||
time: now(),
|
time: now(),
|
||||||
value: request.to_string(),
|
value: query.to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
self.driver.feature_async(
|
self.driver.request_async(
|
||||||
Feature::from_string(request),
|
Request::build(query, None, self.new_cancellable(), Priority::DEFAULT),
|
||||||
self.new_cancellable(),
|
|
||||||
callback,
|
callback,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,14 @@ pub mod status;
|
||||||
pub use status::Status;
|
pub use status::Status;
|
||||||
|
|
||||||
// Global dependencies
|
// Global dependencies
|
||||||
use super::{feature::Request, response, response::Failure, Feature, Response};
|
use super::{
|
||||||
use crate::{tool::now, Profile};
|
request::{feature::Protocol, Feature},
|
||||||
use gtk::{
|
response,
|
||||||
gio::{Cancellable, SocketClientEvent},
|
response::Failure,
|
||||||
prelude::SocketClientExt,
|
Request, Response,
|
||||||
};
|
};
|
||||||
|
use crate::{tool::now, Profile};
|
||||||
|
use gtk::{gio::SocketClientEvent, prelude::SocketClientExt};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct Driver {
|
pub struct Driver {
|
||||||
|
|
@ -61,19 +63,19 @@ impl Driver {
|
||||||
|
|
||||||
/// Make new async `Feature` request
|
/// Make new async `Feature` request
|
||||||
/// * return `Response` in callback function
|
/// * return `Response` in callback function
|
||||||
pub fn feature_async(
|
pub fn request_async(&self, request: Request, callback: impl FnOnce(Response) + 'static) {
|
||||||
&self,
|
match request.feature {
|
||||||
feature: Feature,
|
Feature::Download(protocol) => match protocol {
|
||||||
cancellable: Cancellable,
|
Protocol::Gemini {
|
||||||
callback: impl FnOnce(Response) + 'static,
|
uri,
|
||||||
) {
|
cancellable,
|
||||||
match feature {
|
priority,
|
||||||
Feature::Download { request } => match request {
|
} => gemini::request_async(
|
||||||
Request::Gemini { uri } => gemini::request_async(
|
|
||||||
&self.profile,
|
&self.profile,
|
||||||
&self.gemini,
|
&self.gemini,
|
||||||
uri.clone(),
|
uri.clone(),
|
||||||
cancellable.clone(),
|
cancellable.clone(),
|
||||||
|
priority,
|
||||||
move |result| {
|
move |result| {
|
||||||
callback(match result {
|
callback(match result {
|
||||||
Ok(response) => Response::Download {
|
Ok(response) => Response::Download {
|
||||||
|
|
@ -91,24 +93,38 @@ impl Driver {
|
||||||
message: "Download feature yet not supported for this request".to_string(),
|
message: "Download feature yet not supported for this request".to_string(),
|
||||||
})), // @TODO or maybe panic as unexpected
|
})), // @TODO or maybe panic as unexpected
|
||||||
},
|
},
|
||||||
Feature::Default { request } => match request {
|
Feature::Default(protocol) => match protocol {
|
||||||
Request::Gemini { uri } => gemini::request_async(
|
Protocol::Gemini {
|
||||||
|
uri,
|
||||||
|
cancellable,
|
||||||
|
priority,
|
||||||
|
} => gemini::request_async(
|
||||||
&self.profile,
|
&self.profile,
|
||||||
&self.gemini,
|
&self.gemini,
|
||||||
uri.clone(),
|
uri.clone(),
|
||||||
cancellable.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!(),
|
Protocol::Titan { .. } => todo!(),
|
||||||
Request::Undefined => todo!(),
|
Protocol::Unsupported => todo!(),
|
||||||
},
|
},
|
||||||
Feature::Source { request } => match request {
|
Feature::Source(protocol) => match protocol {
|
||||||
Request::Gemini { uri } => gemini::request_async(
|
Protocol::Gemini {
|
||||||
|
uri,
|
||||||
|
cancellable,
|
||||||
|
priority,
|
||||||
|
} => gemini::request_async(
|
||||||
&self.profile,
|
&self.profile,
|
||||||
&self.gemini,
|
&self.gemini,
|
||||||
uri.clone(),
|
uri.clone(),
|
||||||
cancellable.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 {
|
_ => callback(Response::Failure(Failure::Error {
|
||||||
message: "Source view feature yet not supported for this request".to_string(),
|
message: "Source view feature yet not supported for this request".to_string(),
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,13 @@ pub fn request_async(
|
||||||
client: &Rc<ggemini::Client>,
|
client: &Rc<ggemini::Client>,
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
cancellable: Cancellable,
|
cancellable: Cancellable,
|
||||||
|
priority: Priority,
|
||||||
callback: impl FnOnce(Result<ggemini::client::Response, ggemini::client::Error>) + 'static,
|
callback: impl FnOnce(Result<ggemini::client::Response, ggemini::client::Error>) + 'static,
|
||||||
) {
|
) {
|
||||||
let request = uri.to_string();
|
let request = uri.to_string();
|
||||||
client.request_async(
|
client.request_async(
|
||||||
ggemini::client::Request::gemini(uri),
|
ggemini::client::Request::gemini(uri),
|
||||||
Priority::DEFAULT,
|
priority,
|
||||||
cancellable,
|
cancellable,
|
||||||
// Search for user certificate match request
|
// Search for user certificate match request
|
||||||
// * @TODO this feature does not support multi-protocol yet
|
// * @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>,
|
result: Result<ggemini::client::connection::Response, ggemini::client::Error>,
|
||||||
base: Uri,
|
base: Uri,
|
||||||
cancellable: Cancellable,
|
cancellable: Cancellable,
|
||||||
|
priority: Priority,
|
||||||
is_source_request: bool, // @TODO yet partial implementation
|
is_source_request: bool, // @TODO yet partial implementation
|
||||||
callback: impl FnOnce(Response) + 'static,
|
callback: impl FnOnce(Response) + 'static,
|
||||||
) {
|
) {
|
||||||
|
|
@ -66,7 +68,7 @@ pub fn handle(
|
||||||
Some(mime) => match mime.as_str() {
|
Some(mime) => match mime.as_str() {
|
||||||
"text/gemini" => Text::from_stream_async(
|
"text/gemini" => Text::from_stream_async(
|
||||||
response.connection.stream(),
|
response.connection.stream(),
|
||||||
Priority::DEFAULT,
|
priority,
|
||||||
cancellable,
|
cancellable,
|
||||||
move |result| match result {
|
move |result| match result {
|
||||||
Ok(text) => callback(Response::TextGemini {
|
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