From f65f1720043a43bf66012eec3ac1e9ed525bf617 Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 22:02:08 +0900 Subject: [PATCH 01/16] allow the endpoint to return json_preview --- src/cli.rs | 1 + src/server/endpoint.rs | 44 ++++++++++++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index a54925a..5a526bd 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -61,6 +61,7 @@ impl TestConfig { self.limit_posts, !self.compact_output, self.base.clone(), + false, ) } } diff --git a/src/server/endpoint.rs b/src/server/endpoint.rs index f9ee10a..ca27118 100644 --- a/src/server/endpoint.rs +++ b/src/server/endpoint.rs @@ -6,12 +6,14 @@ use std::time::Duration; use axum::body::Body; use axum::response::IntoResponse; +use axum::Json; use axum_macros::FromRequestParts; use http::header::HOST; use http::StatusCode; use mime::Mime; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use serde_json::json; use tower::Service; use url::Url; @@ -87,6 +89,8 @@ pub struct EndpointParam { pretty_print: bool, /// The url base of the feed, used for resolving relative urls base: Option, + /// Include a json preview of the feed in the response + include_json_preview: bool, } impl EndpointParam { @@ -96,6 +100,7 @@ impl EndpointParam { limit_posts: Option, pretty_print: bool, base: Option, + include_json_preview: bool, ) -> Self { Self { source, @@ -103,6 +108,7 @@ impl EndpointParam { limit_posts, pretty_print, base, + include_json_preview, } } @@ -113,6 +119,7 @@ impl EndpointParam { limit_posts: Self::parse_limit_posts(req), pretty_print: Self::parse_pretty_print(req), base: Self::get_base(req), + include_json_preview: Self::parse_include_json_preview(req), } } @@ -134,6 +141,12 @@ impl EndpointParam { .unwrap_or(false) } + fn parse_include_json_preview(req: &Request) -> bool { + Self::get_query(req, "include_json_preview") + .map(|x| x == "1" || x == "true") + .unwrap_or(false) + } + fn get_base(req: &Request) -> Option { let host = req .headers() @@ -163,8 +176,9 @@ impl EndpointParam { #[derive(Clone)] pub struct EndpointOutcome { - feed_xml: String, + content: String, content_type: Mime, + json_preview: Option, } impl EndpointOutcome { @@ -172,31 +186,37 @@ impl EndpointOutcome { let content_type = content_type.parse().expect("invalid content_type"); Self { - feed_xml, + content: feed_xml, content_type, + json_preview: None, } } pub fn prettify(&mut self) { - if let Ok(xml) = self.feed_xml.parse::() { - self.feed_xml = xml.to_string_pretty(); + if let Ok(xml) = self.content.parse::() { + self.content = xml.to_string_pretty(); } } pub fn feed_xml(&self) -> &str { - &self.feed_xml + &self.content } } impl IntoResponse for EndpointOutcome { fn into_response(self) -> axum::response::Response { - let mut resp = Response::new(Body::from(self.feed_xml)); - resp.headers_mut().insert( - "content-type", - http::header::HeaderValue::from_str(self.content_type.as_ref()) - .expect("invalid content_type"), - ); - resp + match self.json_preview { + Some(json_preview) => Json(json!( { + "content": self.content, + "content_type": self.content_type.to_string(), + "json_preview": json_preview, + })) + .into_response(), + None => { + let headers = [("content-type", self.content_type.to_string())]; + (StatusCode::OK, headers, self.content).into_response() + } + } } } From c1d6baae627b0987b7d1e6230a6de430fc9395f2 Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 22:03:50 +0900 Subject: [PATCH 02/16] Revert "allow the endpoint to return json_preview" This reverts commit f65f1720043a43bf66012eec3ac1e9ed525bf617. --- src/cli.rs | 1 - src/server/endpoint.rs | 44 ++++++++++++------------------------------ 2 files changed, 12 insertions(+), 33 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 5a526bd..a54925a 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -61,7 +61,6 @@ impl TestConfig { self.limit_posts, !self.compact_output, self.base.clone(), - false, ) } } diff --git a/src/server/endpoint.rs b/src/server/endpoint.rs index ca27118..f9ee10a 100644 --- a/src/server/endpoint.rs +++ b/src/server/endpoint.rs @@ -6,14 +6,12 @@ use std::time::Duration; use axum::body::Body; use axum::response::IntoResponse; -use axum::Json; use axum_macros::FromRequestParts; use http::header::HOST; use http::StatusCode; use mime::Mime; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use serde_json::json; use tower::Service; use url::Url; @@ -89,8 +87,6 @@ pub struct EndpointParam { pretty_print: bool, /// The url base of the feed, used for resolving relative urls base: Option, - /// Include a json preview of the feed in the response - include_json_preview: bool, } impl EndpointParam { @@ -100,7 +96,6 @@ impl EndpointParam { limit_posts: Option, pretty_print: bool, base: Option, - include_json_preview: bool, ) -> Self { Self { source, @@ -108,7 +103,6 @@ impl EndpointParam { limit_posts, pretty_print, base, - include_json_preview, } } @@ -119,7 +113,6 @@ impl EndpointParam { limit_posts: Self::parse_limit_posts(req), pretty_print: Self::parse_pretty_print(req), base: Self::get_base(req), - include_json_preview: Self::parse_include_json_preview(req), } } @@ -141,12 +134,6 @@ impl EndpointParam { .unwrap_or(false) } - fn parse_include_json_preview(req: &Request) -> bool { - Self::get_query(req, "include_json_preview") - .map(|x| x == "1" || x == "true") - .unwrap_or(false) - } - fn get_base(req: &Request) -> Option { let host = req .headers() @@ -176,9 +163,8 @@ impl EndpointParam { #[derive(Clone)] pub struct EndpointOutcome { - content: String, + feed_xml: String, content_type: Mime, - json_preview: Option, } impl EndpointOutcome { @@ -186,37 +172,31 @@ impl EndpointOutcome { let content_type = content_type.parse().expect("invalid content_type"); Self { - content: feed_xml, + feed_xml, content_type, - json_preview: None, } } pub fn prettify(&mut self) { - if let Ok(xml) = self.content.parse::() { - self.content = xml.to_string_pretty(); + if let Ok(xml) = self.feed_xml.parse::() { + self.feed_xml = xml.to_string_pretty(); } } pub fn feed_xml(&self) -> &str { - &self.content + &self.feed_xml } } impl IntoResponse for EndpointOutcome { fn into_response(self) -> axum::response::Response { - match self.json_preview { - Some(json_preview) => Json(json!( { - "content": self.content, - "content_type": self.content_type.to_string(), - "json_preview": json_preview, - })) - .into_response(), - None => { - let headers = [("content-type", self.content_type.to_string())]; - (StatusCode::OK, headers, self.content).into_response() - } - } + let mut resp = Response::new(Body::from(self.feed_xml)); + resp.headers_mut().insert( + "content-type", + http::header::HeaderValue::from_str(self.content_type.as_ref()) + .expect("invalid content_type"), + ); + resp } } From f57db49c42a8ba2a0b9b700f472195bdce345bf3 Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 22:27:49 +0900 Subject: [PATCH 03/16] implement FromRequestParts for EndpointParam --- src/server/endpoint.rs | 101 +++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/src/server/endpoint.rs b/src/server/endpoint.rs index f9ee10a..f965fc0 100644 --- a/src/server/endpoint.rs +++ b/src/server/endpoint.rs @@ -4,10 +4,13 @@ use std::pin::Pin; use std::sync::Arc; use std::time::Duration; +use async_trait::async_trait; use axum::body::Body; +use axum::extract::{FromRequestParts, Query}; use axum::response::IntoResponse; -use axum_macros::FromRequestParts; +use axum::RequestExt; use http::header::HOST; +use http::request::Parts; use http::StatusCode; use mime::Mime; use schemars::JsonSchema; @@ -77,18 +80,48 @@ pub struct EndpointService { client: Arc, } -#[derive(Clone, Default, Deserialize)] +#[derive(Clone, Debug, Default, Deserialize)] pub struct EndpointParam { + #[serde(default)] source: Option, /// Only process the initial N filter steps + #[serde(default)] limit_filters: Option, /// Limit the number of items in the feed + #[serde(default)] limit_posts: Option, + #[serde( + default, + alias = "pp", + deserialize_with = "deserialize_bool_in_query" + )] pretty_print: bool, /// The url base of the feed, used for resolving relative urls + #[serde(skip)] base: Option, } +#[async_trait] +impl FromRequestParts for EndpointParam +where + S: Send + Sync, +{ + type Rejection = Infallible; + + async fn from_request_parts( + parts: &mut Parts, + state: &S, + ) -> Result { + let Query(mut param) = Query::::from_request_parts(parts, state) + .await + .unwrap_or_default(); + + param.base = Self::get_base(parts); + dbg!(¶m); + Ok(param) + } +} + impl EndpointParam { pub fn new( source: Option, @@ -106,43 +139,15 @@ impl EndpointParam { } } - fn from_request(req: &Request) -> Self { - Self { - source: Self::parse_source(req), - limit_filters: Self::parse_limit_filters(req), - limit_posts: Self::parse_limit_posts(req), - pretty_print: Self::parse_pretty_print(req), - base: Self::get_base(req), - } - } - - fn parse_source(req: &Request) -> Option { - Self::get_query(req, "source").and_then(|x| Url::parse(&x).ok()) - } - - fn parse_limit_filters(req: &Request) -> Option { - Self::get_query(req, "limit_filters").and_then(|x| x.parse::().ok()) - } - - fn parse_limit_posts(req: &Request) -> Option { - Self::get_query(req, "limit_posts").and_then(|x| x.parse::().ok()) - } - - fn parse_pretty_print(req: &Request) -> bool { - Self::get_query(req, "pp") - .map(|x| x == "1" || x == "true") - .unwrap_or(false) - } - - fn get_base(req: &Request) -> Option { + fn get_base(req: &Parts) -> Option { let host = req - .headers() + .headers .get("X-Forwarded-Host") - .or_else(|| req.headers().get(HOST)) + .or_else(|| req.headers.get(HOST)) .and_then(|x| x.to_str().ok())?; let proto = req - .headers() + .headers .get("X-Forwarded-Proto") .and_then(|x| x.to_str().ok()) .unwrap_or("http"); @@ -151,14 +156,6 @@ impl EndpointParam { let base = base.parse().ok()?; Some(base) } - - fn get_query(req: &Request, name: &str) -> Option { - let url = Url::parse(&format!("http://placeholder{}", &req.uri())).ok()?; - url - .query_pairs() - .find_map(|(k, v)| (k == name).then_some(v)) - .map(|x| x.to_string()) - } } #[derive(Clone)] @@ -235,10 +232,12 @@ impl Service for EndpointService { Service::::poll_ready(self, _cx).map_err(|_| unreachable!()) } - fn call(&mut self, req: Request) -> Self::Future { + fn call(&mut self, mut req: Request) -> Self::Future { let this = self.clone(); - let param = EndpointParam::from_request(&req); - let fut = async { this.call_internal(param).await }; + let fut = async move { + let param = req.extract_parts().await.unwrap(); + this.call_internal(param).await + }; let fut = async { let err = |e: Error| { (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response() @@ -350,7 +349,11 @@ impl EndpointService { } } -// Add more fields depending on what you need from the request in the -// filters. -#[derive(Default, FromRequestParts)] -pub struct RequestContext {} +fn deserialize_bool_in_query<'de, D>(de: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let s = String::deserialize(de)?; + let b = s == "1" || s == "true"; + Ok(b) +} From 110a9a3ac7886a3c6fb804581577d0fa13986492 Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 22:50:27 +0900 Subject: [PATCH 04/16] implement IntoResponse for Feed --- src/cli.rs | 8 ++--- src/feed.rs | 69 +++++++++++++++++++++++++++++++++--------- src/server.rs | 2 +- src/server/endpoint.rs | 62 +++---------------------------------- 4 files changed, 61 insertions(+), 80 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index a54925a..eb6212b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -42,9 +42,6 @@ struct TestConfig { /// Limit the number of items in the feed #[clap(long, short('n'))] limit_posts: Option, - /// Whether to compact the XML output (opposite of pretty-print) - #[clap(long, short)] - compact_output: bool, /// Don't print XML output (Useful for checking console.log in JS filters) #[clap(long, short)] quiet: bool, @@ -59,7 +56,6 @@ impl TestConfig { self.source.as_ref().cloned(), self.limit_filters, self.limit_posts, - !self.compact_output, self.base.clone(), ) } @@ -119,12 +115,12 @@ async fn test_endpoint(feed_defn: RootConfig, test_config: &TestConfig) { .await .expect("failed to build endpoint service"); let endpoint_param = test_config.to_endpoint_param(); - let outcome = endpoint_service + let feed = endpoint_service .call(endpoint_param) .await .expect("failed to call endpoint service"); if !test_config.quiet { - println!("{}", outcome.feed_xml()); + println!("{}", feed.serialize(true).expect("failed serializing feed")); } } diff --git a/src/feed.rs b/src/feed.rs index f4066a5..e935406 100644 --- a/src/feed.rs +++ b/src/feed.rs @@ -6,7 +6,6 @@ use url::Url; use crate::html::convert_relative_url; use crate::html::html_body; -use crate::server::EndpointOutcome; use crate::source::FromScratch; use crate::util::Error; use crate::util::Result; @@ -56,6 +55,50 @@ impl Feed { .or_else(|_| Feed::from_atom_content(content)) } + pub fn content_type(&self) -> &'static str { + match self { + Feed::Rss(_) => "application/rss+xml", + Feed::Atom(_) => "application/atom+xml", + } + } + + pub fn serialize(&self, pretty: bool) -> Result { + let mut buffer = vec![]; + + match self { + Feed::Rss(channel) => { + if pretty { + channel.pretty_write_to(&mut buffer, b' ', 2)?; + } else { + channel.write_to(&mut buffer)?; + } + } + Feed::Atom(feed) => { + let mut conf = atom_syndication::WriteConfig { + indent_size: None, + write_document_declaration: true, + }; + + if pretty { + conf.indent_size = Some(2); + } + + feed.write_with_config(&mut buffer, conf)?; + } + }; + + let s = String::from_utf8_lossy(&buffer).into_owned(); + Ok(s) + } + + pub fn to_json(&self, pretty: bool) -> String { + if pretty { + serde_json::to_string_pretty(self).expect("failed to serialize feed") + } else { + serde_json::to_string(self).expect("failed to serialize feed") + } + } + #[allow(clippy::field_reassign_with_default)] pub fn from_html_content(content: &str, url: &Url) -> Result { let item = Post::from_html_content(content, url)?; @@ -70,20 +113,6 @@ impl Feed { Ok(feed) } - pub fn into_outcome(self) -> Result { - match self { - Feed::Rss(channel) => { - let body = channel.to_string(); - Ok(EndpointOutcome::new(body, "application/rss+xml")) - } - Feed::Atom(mut feed) => { - fix_escaping_in_extension_attr(&mut feed); - let body = feed.to_string(); - Ok(EndpointOutcome::new(body, "application/atom+xml")) - } - } - } - pub fn take_posts(&mut self) -> Vec { match self { Feed::Rss(channel) => { @@ -480,3 +509,13 @@ fn rss_item_timestamp(item: &rss::Item) -> Option { Some(date.timestamp()) } + +impl axum::response::IntoResponse for Feed { + fn into_response(self) -> axum::response::Response { + let content = self.serialize(true).expect("failed serializing feed"); + let content_type = self.content_type(); + let headers = [("content-type", content_type)]; + + (http::StatusCode::OK, headers, content).into_response() + } +} diff --git a/src/server.rs b/src/server.rs index 94c40da..df7326c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -16,7 +16,7 @@ use crate::{ cli::RootConfig, util::{ConfigError, Result}, }; -pub use endpoint::{EndpointConfig, EndpointOutcome, EndpointParam}; +pub use endpoint::{EndpointConfig, EndpointParam}; use self::feed_service::FeedService; diff --git a/src/server/endpoint.rs b/src/server/endpoint.rs index f965fc0..2e52fa3 100644 --- a/src/server/endpoint.rs +++ b/src/server/endpoint.rs @@ -12,13 +12,13 @@ use axum::RequestExt; use http::header::HOST; use http::request::Parts; use http::StatusCode; -use mime::Mime; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use tower::Service; use url::Url; use crate::client::{Client, ClientConfig}; +use crate::feed::Feed; use crate::filter::FilterContext; use crate::filter_pipeline::{FilterPipeline, FilterPipelineConfig}; use crate::source::{Source, SourceConfig}; @@ -90,12 +90,6 @@ pub struct EndpointParam { /// Limit the number of items in the feed #[serde(default)] limit_posts: Option, - #[serde( - default, - alias = "pp", - deserialize_with = "deserialize_bool_in_query" - )] - pretty_print: bool, /// The url base of the feed, used for resolving relative urls #[serde(skip)] base: Option, @@ -127,14 +121,12 @@ impl EndpointParam { source: Option, limit_filters: Option, limit_posts: Option, - pretty_print: bool, base: Option, ) -> Self { Self { source, limit_filters, limit_posts, - pretty_print, base, } } @@ -158,47 +150,8 @@ impl EndpointParam { } } -#[derive(Clone)] -pub struct EndpointOutcome { - feed_xml: String, - content_type: Mime, -} - -impl EndpointOutcome { - pub fn new(feed_xml: String, content_type: &str) -> Self { - let content_type = content_type.parse().expect("invalid content_type"); - - Self { - feed_xml, - content_type, - } - } - - pub fn prettify(&mut self) { - if let Ok(xml) = self.feed_xml.parse::() { - self.feed_xml = xml.to_string_pretty(); - } - } - - pub fn feed_xml(&self) -> &str { - &self.feed_xml - } -} - -impl IntoResponse for EndpointOutcome { - fn into_response(self) -> axum::response::Response { - let mut resp = Response::new(Body::from(self.feed_xml)); - resp.headers_mut().insert( - "content-type", - http::header::HeaderValue::from_str(self.content_type.as_ref()) - .expect("invalid content_type"), - ); - resp - } -} - impl Service for EndpointService { - type Response = EndpointOutcome; + type Response = Feed; type Error = Error; type Future = Pin> + Send>>; @@ -275,10 +228,7 @@ impl EndpointService { }) } - async fn call_internal( - self, - param: EndpointParam, - ) -> Result { + async fn call_internal(self, param: EndpointParam) -> Result { let source = self.find_source(¶m.source)?; let feed = source .fetch_feed(Some(&self.client), param.base.as_ref()) @@ -299,11 +249,7 @@ impl EndpointService { feed.set_posts(posts); } - let mut outcome = feed.into_outcome()?; - if param.pretty_print { - outcome.prettify(); - } - Ok(outcome) + Ok(feed) } fn find_source(&self, param: &Option) -> Result { From be3e684dc24fcc99704afd05ddbd66ea90cff1c6 Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 22:53:48 +0900 Subject: [PATCH 05/16] fix escaping for atom feed --- src/feed.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/feed.rs b/src/feed.rs index e935406..d1e0e02 100644 --- a/src/feed.rs +++ b/src/feed.rs @@ -74,6 +74,8 @@ impl Feed { } } Feed::Atom(feed) => { + let mut feed = feed.clone(); + fix_escaping_in_extension_attr(&mut feed); let mut conf = atom_syndication::WriteConfig { indent_size: None, write_document_declaration: true, From 9a83130f3c355aa6a6026a6274ee9c3148615ae1 Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 22:54:09 +0900 Subject: [PATCH 06/16] remove unneeded xmlem dependency Since now pretty printing incur no extra cost, I have removed the flag to enable pretty printing. Feed will be serialized pretty-printed by default. --- Cargo.lock | 530 +++-------------------------------------- Cargo.toml | 1 - src/server/endpoint.rs | 9 - 3 files changed, 32 insertions(+), 508 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a64bb78..a83bba1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b" dependencies = [ "cfg-if", - "getrandom 0.2.12", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -157,7 +157,7 @@ dependencies = [ "derive_builder", "diligent-date-parser", "never", - "quick-xml 0.30.0", + "quick-xml", "serde", ] @@ -182,7 +182,7 @@ dependencies = [ "http-body-util", "hyper 1.2.0", "hyper-util", - "itoa 1.0.10", + "itoa", "matchit", "memchr", "mime", @@ -377,12 +377,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "convert_case" version = "0.6.0" @@ -436,23 +430,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "cssparser" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db8599a9761b371751fbf13e076fa03c6e1a78f8c5288e6ab9467f10a2322c1" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa 0.4.8", - "matches", - "phf 0.8.0", - "proc-macro2", - "quote", - "smallvec", - "syn 1.0.109", -] - [[package]] name = "cssparser" version = "0.31.2" @@ -461,7 +438,7 @@ checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" dependencies = [ "cssparser-macros", "dtoa-short", - "itoa 1.0.10", + "itoa", "phf 0.11.2", "smallvec", ] @@ -554,10 +531,8 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case 0.4.0", "proc-macro2", "quote", - "rustc_version", "syn 1.0.109", ] @@ -821,17 +796,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.12" @@ -840,7 +804,7 @@ checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -967,7 +931,7 @@ checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", - "itoa 1.0.10", + "itoa", ] [[package]] @@ -978,7 +942,7 @@ checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" dependencies = [ "bytes", "fnv", - "itoa 1.0.10", + "itoa", ] [[package]] @@ -1042,7 +1006,7 @@ dependencies = [ "http-body 0.4.6", "httparse", "httpdate", - "itoa 1.0.10", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -1065,7 +1029,7 @@ dependencies = [ "http-body 1.0.0", "httparse", "httpdate", - "itoa 1.0.10", + "itoa", "pin-project-lite", "smallvec", "tokio", @@ -1218,12 +1182,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - [[package]] name = "itoa" version = "1.0.10" @@ -1325,7 +1283,7 @@ checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" dependencies = [ "log", "phf 0.10.1", - "phf_codegen 0.10.0", + "phf_codegen", "string_cache", "string_cache_codegen", "tendril", @@ -1349,12 +1307,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "matchit" version = "0.7.3" @@ -1396,7 +1348,7 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -1412,12 +1364,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - [[package]] name = "nom" version = "7.1.3" @@ -1530,17 +1476,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "phf" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" -dependencies = [ - "phf_macros 0.8.0", - "phf_shared 0.8.0", - "proc-macro-hack", -] - [[package]] name = "phf" version = "0.10.1" @@ -1556,20 +1491,10 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", + "phf_macros", "phf_shared 0.11.2", ] -[[package]] -name = "phf_codegen" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", -] - [[package]] name = "phf_codegen" version = "0.10.0" @@ -1580,16 +1505,6 @@ dependencies = [ "phf_shared 0.10.0", ] -[[package]] -name = "phf_generator" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" -dependencies = [ - "phf_shared 0.8.0", - "rand 0.7.3", -] - [[package]] name = "phf_generator" version = "0.10.0" @@ -1597,7 +1512,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ "phf_shared 0.10.0", - "rand 0.8.5", + "rand", ] [[package]] @@ -1607,21 +1522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ "phf_shared 0.11.2", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", + "rand", ] [[package]] @@ -1637,15 +1538,6 @@ dependencies = [ "syn 2.0.52", ] -[[package]] -name = "phf_shared" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" -dependencies = [ - "siphasher", -] - [[package]] name = "phf_shared" version = "0.10.0" @@ -1742,12 +1634,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" version = "1.0.78" @@ -1757,54 +1643,12 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "qname" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fac552bc5de28a2d8ebb5d93d157b1eb3d1ca58f88ba2d1e2b931951cb52b29" -dependencies = [ - "qname-impl", - "qname-macro", -] - -[[package]] -name = "qname-impl" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28cd0334d1ed0cb075cde40d45b9ee648fe79e69a18c3e2891f79c3ec788304" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "qname-macro" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e673fdaa2dcfd19fac443c4a361cc2635b2304592cdc5352ef76bb8dd38333c" -dependencies = [ - "proc-macro2", - "qname-impl", - "quote", - "syn 1.0.109", -] - [[package]] name = "quick-error" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -[[package]] -name = "quick-xml" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc053f057dd768a56f62cd7e434c42c831d296968997e9ac1f76ea7c2d14c41" -dependencies = [ - "memchr", -] - [[package]] name = "quick-xml" version = "0.30.0" @@ -1824,20 +1668,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", - "rand_pcg", -] - [[package]] name = "rand" version = "0.8.5" @@ -1845,18 +1675,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -1866,16 +1686,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -1884,25 +1695,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.12", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_pcg" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.1", + "getrandom", ] [[package]] @@ -2022,7 +1815,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.12", + "getrandom", "libc", "spin", "untrusted", @@ -2058,7 +1851,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27b39e889cc951e3e5f6b74012f943e642fa0fac51a8552948751f19a9b62f8" dependencies = [ - "convert_case 0.6.0", + "convert_case", "fnv", "ident_case", "indexmap 2.2.5", @@ -2088,7 +1881,7 @@ dependencies = [ "atom_syndication", "derive_builder", "never", - "quick-xml 0.30.0", + "quick-xml", "serde", ] @@ -2134,7 +1927,6 @@ dependencies = [ "tracing", "tracing-subscriber", "url", - "xmlem", ] [[package]] @@ -2188,15 +1980,6 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - [[package]] name = "rustls" version = "0.21.10" @@ -2286,12 +2069,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b80b33679ff7a0ea53d37f3b39de77ea0c75b12c5805ac43ec0c33b3051af1b" dependencies = [ "ahash", - "cssparser 0.31.2", + "cssparser", "ego-tree", "getopts", "html5ever", "once_cell", - "selectors 0.25.0", + "selectors", "tendril", ] @@ -2305,24 +2088,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "selectors" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdea87c686be721aab36607728047801ee21561bfdbd6bf0da7ace2536d5879f" -dependencies = [ - "bitflags 1.3.2", - "cssparser 0.28.1", - "derive_more", - "fxhash", - "log", - "phf 0.8.0", - "phf_codegen 0.8.0", - "precomputed-hash", - "servo_arc 0.1.1", - "smallvec", -] - [[package]] name = "selectors" version = "0.25.0" @@ -2330,24 +2095,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" dependencies = [ "bitflags 2.4.2", - "cssparser 0.31.2", + "cssparser", "derive_more", "fxhash", "log", "new_debug_unreachable", "phf 0.10.1", - "phf_codegen 0.10.0", + "phf_codegen", "precomputed-hash", - "servo_arc 0.3.0", + "servo_arc", "smallvec", ] -[[package]] -name = "semver" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" - [[package]] name = "serde" version = "1.0.197" @@ -2385,7 +2144,7 @@ version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ - "itoa 1.0.10", + "itoa", "ryu", "serde", ] @@ -2396,7 +2155,7 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" dependencies = [ - "itoa 1.0.10", + "itoa", "serde", ] @@ -2407,7 +2166,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.10", + "itoa", "ryu", "serde", ] @@ -2419,22 +2178,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" dependencies = [ "indexmap 2.2.5", - "itoa 1.0.10", + "itoa", "ryu", "serde", "unsafe-libyaml", ] -[[package]] -name = "servo_arc" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" -dependencies = [ - "nodrop", - "stable_deref_trait", -] - [[package]] name = "servo_arc" version = "0.3.0" @@ -2479,15 +2228,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "slotmap" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" -dependencies = [ - "version_check", -] - [[package]] name = "smallvec" version = "1.13.1" @@ -2850,7 +2590,7 @@ dependencies = [ "idna 0.4.0", "ipnet", "once_cell", - "rand 0.8.5", + "rand", "smallvec", "thiserror", "tinyvec", @@ -2871,7 +2611,7 @@ dependencies = [ "lru-cache", "once_cell", "parking_lot", - "rand 0.8.5", + "rand", "resolv-conf", "smallvec", "thiserror", @@ -2892,189 +2632,6 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-ucd" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625b18f7601e1127504a20ae731dc3c7826d0e86d5f7fe3434f8137669240efd" -dependencies = [ - "unic-ucd-age", - "unic-ucd-bidi", - "unic-ucd-block", - "unic-ucd-case", - "unic-ucd-category", - "unic-ucd-common", - "unic-ucd-hangul", - "unic-ucd-ident", - "unic-ucd-name", - "unic-ucd-name_aliases", - "unic-ucd-normal", - "unic-ucd-segment", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-age" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8cfdfe71af46b871dc6af2c24fcd360e2f3392ee4c5111877f2947f311671c" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-bidi" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1d568b51222484e1f8209ce48caa6b430bf352962b877d592c29ab31fb53d8c" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-block" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b2a16f2d7ecd25325a1053ca5a66e7fa1b68911a65c5e97f8d2e1b236b6f1d7" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-case" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d98d6246a79bac6cf66beee01422bda7c882e11d837fa4969bfaaba5fdea6d3" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-category" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8d4591f5fcfe1bd4453baaf803c40e1b1e69ff8455c47620440b46efef91c0" -dependencies = [ - "matches", - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b78b910beafa1aae5c59bf00877c6cece1c5db28a1241ad801e86cecdff4ad" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-hangul" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1dc690e19010e1523edb9713224cba5ef55b54894fe33424439ec9a40c0054" -dependencies = [ - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-ident" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-name" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8fc55a45b2531089dc1773bf60c1f104b38e434b774ffc37b9c29a9b0f492e" -dependencies = [ - "unic-char-property", - "unic-ucd-hangul", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-name_aliases" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7674212643087699ba247a63dd05f1204c7e4880ec9342e545a7cffcc6a46f" -dependencies = [ - "unic-char-property", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-normal" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86aed873b8202d22b13859dda5fe7c001d271412c31d411fd9b827e030569410" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-category", - "unic-ucd-hangul", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] - [[package]] name = "unicode-bidi" version = "0.3.15" @@ -3175,12 +2732,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3477,23 +3028,6 @@ dependencies = [ "markup5ever", ] -[[package]] -name = "xmlem" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff0448e51b097decfe99cae80045933fe11bdea7c2304073f665ffd604562f7" -dependencies = [ - "cssparser 0.28.1", - "indexmap 1.9.3", - "once_cell", - "qname", - "quick-xml 0.27.1", - "selectors 0.23.0", - "slotmap", - "tracing", - "unic-ucd", -] - [[package]] name = "zerocopy" version = "0.7.32" diff --git a/Cargo.toml b/Cargo.toml index 3610e00..4ef2776 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,6 @@ ego-tree = "0.6.2" readability = { version = "0.3.0", default-features = false } html5ever = "0.26.0" htmlescape = "0.3.1" -xmlem = "0.2.3" # JS runtime crates rquickjs = { version = "0.5.1", features = ["loader", "parallel", "macro", "futures", "exports", "either"] } diff --git a/src/server/endpoint.rs b/src/server/endpoint.rs index 2e52fa3..cf625ff 100644 --- a/src/server/endpoint.rs +++ b/src/server/endpoint.rs @@ -294,12 +294,3 @@ impl EndpointService { Ok(self) } } - -fn deserialize_bool_in_query<'de, D>(de: D) -> Result -where - D: serde::Deserializer<'de>, -{ - let s = String::deserialize(de)?; - let b = s == "1" || s == "true"; - Ok(b) -} From caa8beabc20ebc9e9c83f3623a35ea6748a3bc81 Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 23:09:54 +0900 Subject: [PATCH 07/16] expose param->feed transformation from endpoint service --- src/cli.rs | 5 ++--- src/server/endpoint.rs | 49 ++++++++++++------------------------------ 2 files changed, 16 insertions(+), 38 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index eb6212b..0ccc73f 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -3,7 +3,6 @@ use std::path::{Path, PathBuf}; use clap::Parser; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use tower::Service; use url::Url; use crate::{ @@ -110,13 +109,13 @@ async fn test_endpoint(feed_defn: RootConfig, test_config: &TestConfig) { ); return; }; - let mut endpoint_service = endpoint_conf + let endpoint_service = endpoint_conf .build() .await .expect("failed to build endpoint service"); let endpoint_param = test_config.to_endpoint_param(); let feed = endpoint_service - .call(endpoint_param) + .run(endpoint_param) .await .expect("failed to call endpoint service"); diff --git a/src/server/endpoint.rs b/src/server/endpoint.rs index cf625ff..53b017c 100644 --- a/src/server/endpoint.rs +++ b/src/server/endpoint.rs @@ -150,27 +150,6 @@ impl EndpointParam { } } -impl Service for EndpointService { - type Response = Feed; - type Error = Error; - type Future = - Pin> + Send>>; - - fn poll_ready( - &mut self, - _cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - std::task::Poll::Ready(Ok(())) - } - - fn call(&mut self, input: EndpointParam) -> Self::Future { - let req = input; - let this = self.clone(); - let fut = async { this.call_internal(req).await }; - Box::pin(fut) - } -} - impl Service for EndpointService { type Response = Response; type Error = Infallible; @@ -182,22 +161,12 @@ impl Service for EndpointService { &mut self, _cx: &mut std::task::Context<'_>, ) -> std::task::Poll> { - Service::::poll_ready(self, _cx).map_err(|_| unreachable!()) + std::task::Poll::Ready(Ok(())) } - fn call(&mut self, mut req: Request) -> Self::Future { + fn call(&mut self, req: Request) -> Self::Future { let this = self.clone(); - let fut = async move { - let param = req.extract_parts().await.unwrap(); - this.call_internal(param).await - }; - let fut = async { - let err = |e: Error| { - (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response() - }; - let resp = fut.await.map(|x| x.into_response()).unwrap_or_else(err); - Ok(resp) - }; + let fut = async move { Ok(this.handle(req).await.into_response()) }; Box::pin(fut) } } @@ -210,6 +179,16 @@ impl EndpointService { self } + async fn handle(self, mut req: Request) -> Result { + // infallible + let param: EndpointParam = req.extract_parts().await.unwrap(); + let feed = self.run(param).await.map_err(|e| { + (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response() + })?; + let resp = feed.into_response(); + Ok(resp) + } + pub async fn from_config( config: EndpointServiceConfig, ) -> Result { @@ -228,7 +207,7 @@ impl EndpointService { }) } - async fn call_internal(self, param: EndpointParam) -> Result { + pub async fn run(self, param: EndpointParam) -> Result { let source = self.find_source(¶m.source)?; let feed = source .fetch_feed(Some(&self.client), param.base.as_ref()) From 9b6aa4b85f58ff1a046d8ff7b7c912005277b462 Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 23:17:54 +0900 Subject: [PATCH 08/16] implement json feed preview handler --- src/feed.rs | 8 -------- src/server/feed_service.rs | 19 ++++++++++--------- src/server/inspector.rs | 23 +++++++++++++++++++++++ src/util.rs | 3 +++ 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/feed.rs b/src/feed.rs index d1e0e02..a570dea 100644 --- a/src/feed.rs +++ b/src/feed.rs @@ -93,14 +93,6 @@ impl Feed { Ok(s) } - pub fn to_json(&self, pretty: bool) -> String { - if pretty { - serde_json::to_string_pretty(self).expect("failed to serialize feed") - } else { - serde_json::to_string(self).expect("failed to serialize feed") - } - } - #[allow(clippy::field_reassign_with_default)] pub fn from_html_content(content: &str, url: &Url) -> Result { let item = Post::from_html_content(content, url)?; diff --git a/src/server/feed_service.rs b/src/server/feed_service.rs index f6ad75b..96e8b0d 100644 --- a/src/server/feed_service.rs +++ b/src/server/feed_service.rs @@ -95,20 +95,21 @@ impl FeedService { true } + pub async fn get_endpoint(&self, path: &str) -> Option { + let inner = self.inner.read().await; + inner.endpoints.get(path).cloned() + } + pub async fn handler( Path(path): Path, Extension(service): Extension, request: Request, ) -> Response { - let inner = service.inner.read().await; - match inner.endpoints.get(&path) { - Some(endpoint) => { - let mut endpoint = endpoint.clone(); - endpoint - .call(request) - .await - .expect("infallible endpoint call failed") - } + match service.get_endpoint(&path).await { + Some(mut endpoint) => endpoint + .call(request) + .await + .expect("infallible endpoint call failed"), _ => ( StatusCode::NOT_FOUND, format!("endpoint not defined: /{path}"), diff --git a/src/server/inspector.rs b/src/server/inspector.rs index d08e466..b09abc8 100644 --- a/src/server/inspector.rs +++ b/src/server/inspector.rs @@ -12,6 +12,7 @@ use crate::filter::FilterConfig; use crate::util::Error; use super::feed_service::FeedService; +use super::EndpointParam; #[derive(rust_embed::RustEmbed)] #[folder = "inspector/dist/"] @@ -23,6 +24,7 @@ pub fn router() -> Router { .route("/_inspector/dist/*file", get(static_handler)) .route("/_inspector/config", get(config_handler)) .route("/_inspector/filter_schema", get(filter_schema_handler)) + .route("/_inspector/json_preview", get(json_preview_handler)) .route( "/", get(|| async { Redirect::temporary("/_inspector/index.html") }), @@ -101,6 +103,27 @@ async fn filter_schema_handler( Ok(Json(schemas)) } +#[derive(serde::Deserialize)] +struct JsonPreviewHandlerParams { + endpoint: String, + #[serde(flatten)] + endpoint_params: EndpointParam, +} + +async fn json_preview_handler( + Extension(feed_service): Extension, + Query(params): Query, +) -> Result { + let endpoint_service = feed_service.get_endpoint(¶ms.endpoint).await; + let Some(endpoint_service) = endpoint_service else { + let e = Error::EndpointNotFound(params.endpoint); + return Err(PreviewError(e)); + }; + + let feed = endpoint_service.run(params.endpoint_params).await?; + Ok(Json(feed)) +} + #[derive(Debug, thiserror::Error)] #[error(transparent)] struct BadRequest(E); diff --git a/src/util.rs b/src/util.rs index 1096078..b7a760f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -88,6 +88,9 @@ pub enum Error { #[error("Tokio task join error {0}")] Join(#[from] tokio::task::JoinError), + #[error("Endpoint not found {0}")] + EndpointNotFound(String), + #[error("{0}")] Message(String), } From 5ee144005ce8aece44d97869c81d2cc3a281a3db Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 23:47:45 +0900 Subject: [PATCH 09/16] fix endpoint path matching --- src/server/inspector.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/inspector.rs b/src/server/inspector.rs index b09abc8..883640a 100644 --- a/src/server/inspector.rs +++ b/src/server/inspector.rs @@ -114,7 +114,8 @@ async fn json_preview_handler( Extension(feed_service): Extension, Query(params): Query, ) -> Result { - let endpoint_service = feed_service.get_endpoint(¶ms.endpoint).await; + let path = params.endpoint.trim_start_matches('/'); + let endpoint_service = feed_service.get_endpoint(path).await; let Some(endpoint_service) = endpoint_service else { let e = Error::EndpointNotFound(params.endpoint); return Err(PreviewError(e)); From 128c5e0886d2b4ba5c44cefe400e19db755b3dcb Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 23:48:11 +0900 Subject: [PATCH 10/16] show json-preview on inspector ui --- inspector/package.json | 1 + inspector/pnpm-lock.yaml | 18 +++++++++++ inspector/src/FeedInspector.js | 59 ++++++++++++++++++++++++++-------- inspector/src/index.html | 5 +++ inspector/src/util.js | 3 ++ 5 files changed, 73 insertions(+), 13 deletions(-) diff --git a/inspector/package.json b/inspector/package.json index 43f59d4..2aa60b5 100644 --- a/inspector/package.json +++ b/inspector/package.json @@ -20,6 +20,7 @@ }, "dependencies": { "@codemirror/lang-xml": "^6.0.2", + "@codemirror/lang-json": "^6.0.1", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.24.0", diff --git a/inspector/pnpm-lock.yaml b/inspector/pnpm-lock.yaml index 3f78cbf..2839e90 100644 --- a/inspector/pnpm-lock.yaml +++ b/inspector/pnpm-lock.yaml @@ -5,6 +5,9 @@ settings: excludeLinksFromLockfile: false dependencies: + '@codemirror/lang-json': + specifier: ^6.0.1 + version: 6.0.1 '@codemirror/lang-xml': specifier: ^6.0.2 version: 6.0.2(@codemirror/view@6.24.1) @@ -277,6 +280,13 @@ packages: '@lezer/common': 1.2.1 dev: false + /@codemirror/lang-json@6.0.1: + resolution: {integrity: sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==} + dependencies: + '@codemirror/language': 6.10.1 + '@lezer/json': 1.0.2 + dev: false + /@codemirror/lang-xml@6.0.2(@codemirror/view@6.24.1): resolution: {integrity: sha512-JQYZjHL2LAfpiZI2/qZ/qzDuSqmGKMwyApYmEUUCTxLM4MWS7sATUEfIguZQr9Zjx/7gcdnewb039smF6nC2zw==} dependencies: @@ -367,6 +377,14 @@ packages: '@lezer/common': 1.2.1 dev: false + /@lezer/json@1.0.2: + resolution: {integrity: sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==} + dependencies: + '@lezer/common': 1.2.1 + '@lezer/highlight': 1.2.0 + '@lezer/lr': 1.4.0 + dev: false + /@lezer/lr@1.4.0: resolution: {integrity: sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==} dependencies: diff --git a/inspector/src/FeedInspector.js b/inspector/src/FeedInspector.js index 2d63687..9d20114 100644 --- a/inspector/src/FeedInspector.js +++ b/inspector/src/FeedInspector.js @@ -3,6 +3,7 @@ import { Filter } from "./Filter.js"; import { basicSetup, EditorView } from "codemirror"; import { EditorState } from "@codemirror/state"; import { xml } from "@codemirror/lang-xml"; +import { json } from "@codemirror/lang-json"; import Split from "split.js"; import HtmlSanitizer from "jitbit-html-sanitizer"; import JSONSchemaView from "json-schema-view-js"; @@ -15,13 +16,15 @@ export class FeedInspector { this.feed_error = null; this.filter_schema = null; this.current_endpoint = null; - this.current_preview = null; this.raw_editor = null; - this.raw_feed_xml = null; + this.raw_feed_content = null; + this.json_preview_editor = null; + this.json_preview_content = null; } async init() { this.setup_raw_editor(); + this.setup_json_preview_editor(); this.setup_splitter(); this.setup_view_mode_selector(); this.setup_reload_config_handler(); @@ -87,13 +90,9 @@ export class FeedInspector { } async setup_view_mode_selector() { - $("#view-mode-selector #rendered-radio").addEventListener("change", () => { - this.render_feed(); - }); - - $("#view-mode-selector #raw-radio").addEventListener("change", () => { - this.render_feed(); - }); + for (const node of $$("#view-mode-selector .radio-button")) { + node.addEventListener("change", () => this.render_feed()); + } } async setup_param() { @@ -130,6 +129,18 @@ export class FeedInspector { }); } + async setup_json_preview_editor() { + this.json_preview_editor = new EditorView({ + extensions: [ + basicSetup, + json(), + EditorState.readOnly.of(true), + EditorView.lineWrapping, + ], + parent: $("#feed-preview #json"), + }); + } + async setup_splitter() { Split(["#sidebar-panel", "#main-panel"], { sizes: [20, 80], @@ -210,16 +221,17 @@ export class FeedInspector { const view_mode = ($("#view-mode-selector #rendered-radio-input").checked && "rendered") || ($("#view-mode-selector #raw-radio-input").checked && "raw") || + ($("#view-mode-selector #json-radio-input").checked && "json") || "rendered"; - ["rendered", "raw"].forEach((mode) => { + ["rendered", "raw", "json"].forEach((mode) => { if (mode === view_mode) { $(`#feed-preview #${mode}`).classList.remove("hidden"); } else { $(`#feed-preview #${mode}`).classList.add("hidden"); } - const raw_feed_xml_xml = this.raw_feed_xml; + const raw_feed_xml_xml = this.raw_feed_content; const function_name = `render_feed_${mode}`; if (this[function_name]) { this[function_name](raw_feed_xml_xml); @@ -269,6 +281,20 @@ export class FeedInspector { }); } + async render_feed_json(_unused) { + const json = JSON.stringify(this.json_preview_content, null, 2); + if (this.json_preview_editor.state.doc.toString() === json) { + return; + } + this.json_preview_editor.dispatch({ + changes: { + from: 0, + to: this.json_preview_editor.state.doc.length, + insert: json, + }, + }); + } + update_request_param_controls() { if (!this.current_endpoint) return; @@ -388,7 +414,11 @@ export class FeedInspector { const time_start = performance.now(); const request_path = `${path}?${params}`; $("#fetch-status").innerText = `Fetching ${request_path}...`; - const resp = await fetch(`${path}?${params}`); + + const [resp, json_preview_resp] = await Promise.all([ + fetch(`${path}?${params}`), + fetch(`/_inspector/json_preview?endpoint=${path}&${params}&pp=1`), + ]); let status_text = ""; if (resp.status != 200) { @@ -398,11 +428,14 @@ export class FeedInspector { } else { this.update_feed_error(null); const text = await resp.text(); - this.raw_feed_xml = text; + this.raw_feed_content = text; status_text = `Fetched ${request_path} `; status_text += `(content-type: ${resp.headers.get("content-type")})`; } + this.json_preview_content = + json_preview_resp.status === 200 && (await json_preview_resp.json()); + status_text += ` in ${performance.now() - time_start}ms.`; $("#fetch-status").innerText = status_text; $("#feed-preview").classList.remove("loading"); diff --git a/inspector/src/index.html b/inspector/src/index.html index b040a9c..5b0a900 100644 --- a/inspector/src/index.html +++ b/inspector/src/index.html @@ -96,9 +96,14 @@

Error detected while processing feed

+
+ + +
+
diff --git a/inspector/src/util.js b/inspector/src/util.js index 85b28de..3052645 100644 --- a/inspector/src/util.js +++ b/inspector/src/util.js @@ -35,3 +35,6 @@ export function isBlankValue(value) { export const $ = (selector, parent = document) => parent.querySelector(selector); + +export const $$ = (selector, parent = document) => + Array.from(parent.querySelectorAll(selector)); From 9a1fd3f88c064facf67e867b6e7ed8531e2cac2c Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 23:49:17 +0900 Subject: [PATCH 11/16] fix broken word-wrap for js code --- inspector/src/style.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inspector/src/style.css b/inspector/src/style.css index a50b334..92f5d02 100644 --- a/inspector/src/style.css +++ b/inspector/src/style.css @@ -209,7 +209,8 @@ ul#filter-list { } pre.js-code { /* allow wrapping in js code */ - white-space: normal; + white-space: pre-wrap; + word-wrap: break-word; } ul { From e4539cf0d48193d9f3ade09f53c36a2542dc1f9b Mon Sep 17 00:00:00 2001 From: shouya Date: Mon, 4 Mar 2024 23:49:40 +0900 Subject: [PATCH 12/16] remove debugging statement --- src/server/endpoint.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server/endpoint.rs b/src/server/endpoint.rs index 53b017c..ef01f48 100644 --- a/src/server/endpoint.rs +++ b/src/server/endpoint.rs @@ -111,7 +111,6 @@ where .unwrap_or_default(); param.base = Self::get_base(parts); - dbg!(¶m); Ok(param) } } From 2503987a09a227e22df67b4450a65036d720b513 Mon Sep 17 00:00:00 2001 From: shouya Date: Tue, 5 Mar 2024 00:05:45 +0900 Subject: [PATCH 13/16] handle base_url correctly for json preview --- inspector/src/FeedInspector.js | 6 +++--- src/server/inspector.rs | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/inspector/src/FeedInspector.js b/inspector/src/FeedInspector.js index 9d20114..ab26435 100644 --- a/inspector/src/FeedInspector.js +++ b/inspector/src/FeedInspector.js @@ -1,4 +1,4 @@ -import { elt, $ } from "./util.js"; +import { elt, $, $$ } from "./util.js"; import { Filter } from "./Filter.js"; import { basicSetup, EditorView } from "codemirror"; import { EditorState } from "@codemirror/state"; @@ -90,7 +90,7 @@ export class FeedInspector { } async setup_view_mode_selector() { - for (const node of $$("#view-mode-selector .radio-button")) { + for (const node of $$("#view-mode-selector input")) { node.addEventListener("change", () => this.render_feed()); } } @@ -434,7 +434,7 @@ export class FeedInspector { } this.json_preview_content = - json_preview_resp.status === 200 && (await json_preview_resp.json()); + json_preview_resp.status === 200 ? await json_preview_resp.json() : null; status_text += ` in ${performance.now() - time_start}ms.`; $("#fetch-status").innerText = status_text; diff --git a/src/server/inspector.rs b/src/server/inspector.rs index 883640a..a9cfc16 100644 --- a/src/server/inspector.rs +++ b/src/server/inspector.rs @@ -106,12 +106,11 @@ async fn filter_schema_handler( #[derive(serde::Deserialize)] struct JsonPreviewHandlerParams { endpoint: String, - #[serde(flatten)] - endpoint_params: EndpointParam, } async fn json_preview_handler( Extension(feed_service): Extension, + endpoint_param: EndpointParam, Query(params): Query, ) -> Result { let path = params.endpoint.trim_start_matches('/'); @@ -121,7 +120,7 @@ async fn json_preview_handler( return Err(PreviewError(e)); }; - let feed = endpoint_service.run(params.endpoint_params).await?; + let feed = endpoint_service.run(endpoint_param).await?; Ok(Json(feed)) } From ce5e062e1b1452b57ba18cc98da53edda69e82b6 Mon Sep 17 00:00:00 2001 From: shouya Date: Tue, 5 Mar 2024 00:08:07 +0900 Subject: [PATCH 14/16] add preview handler --- src/server/inspector.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/server/inspector.rs b/src/server/inspector.rs index a9cfc16..b432c52 100644 --- a/src/server/inspector.rs +++ b/src/server/inspector.rs @@ -24,7 +24,7 @@ pub fn router() -> Router { .route("/_inspector/dist/*file", get(static_handler)) .route("/_inspector/config", get(config_handler)) .route("/_inspector/filter_schema", get(filter_schema_handler)) - .route("/_inspector/json_preview", get(json_preview_handler)) + .route("/_inspector/preview", get(preview_handler)) .route( "/", get(|| async { Redirect::temporary("/_inspector/index.html") }), @@ -104,14 +104,14 @@ async fn filter_schema_handler( } #[derive(serde::Deserialize)] -struct JsonPreviewHandlerParams { +struct PreviewHandlerParams { endpoint: String, } -async fn json_preview_handler( +async fn preview_handler( Extension(feed_service): Extension, endpoint_param: EndpointParam, - Query(params): Query, + Query(params): Query, ) -> Result { let path = params.endpoint.trim_start_matches('/'); let endpoint_service = feed_service.get_endpoint(path).await; @@ -121,7 +121,12 @@ async fn json_preview_handler( }; let feed = endpoint_service.run(endpoint_param).await?; - Ok(Json(feed)) + let body = json!({ + "content_type": feed.content_type(), + "content": feed.serialize(true), + "json": feed + }); + Ok(Json(body)) } #[derive(Debug, thiserror::Error)] From 1cb8605dfad90d81a467ec726b3ed775100a78b0 Mon Sep 17 00:00:00 2001 From: shouya Date: Tue, 5 Mar 2024 00:08:16 +0900 Subject: [PATCH 15/16] remove source from query when not unnecessary --- inspector/src/FeedInspector.js | 4 ++-- src/server/inspector.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/inspector/src/FeedInspector.js b/inspector/src/FeedInspector.js index ab26435..eeecedc 100644 --- a/inspector/src/FeedInspector.js +++ b/inspector/src/FeedInspector.js @@ -462,11 +462,11 @@ export class FeedInspector { $("#limit-filters", parent).value; const params = []; - if (source) params.push(`source=${source}`); + if (!this.current_endpoint.source && source) + params.push(`source=${source}`); if (limit_posts) params.push(`limit_posts=${limit_posts}`); if (limit_filters) params.push(`limit_filters=${limit_filters}`); - params.push("pp=1"); return params.join("&"); } diff --git a/src/server/inspector.rs b/src/server/inspector.rs index b432c52..cd2b61a 100644 --- a/src/server/inspector.rs +++ b/src/server/inspector.rs @@ -123,7 +123,7 @@ async fn preview_handler( let feed = endpoint_service.run(endpoint_param).await?; let body = json!({ "content_type": feed.content_type(), - "content": feed.serialize(true), + "content": feed.serialize(true)?, "json": feed }); Ok(Json(body)) From 06b251499ad55110105acba2e82c69d874d23913 Mon Sep 17 00:00:00 2001 From: shouya Date: Tue, 5 Mar 2024 10:16:13 +0900 Subject: [PATCH 16/16] use more fitting status messages --- inspector/src/FeedInspector.js | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/inspector/src/FeedInspector.js b/inspector/src/FeedInspector.js index eeecedc..664fe62 100644 --- a/inspector/src/FeedInspector.js +++ b/inspector/src/FeedInspector.js @@ -213,7 +213,7 @@ export class FeedInspector { } async fetch_and_render_feed() { - await this.fetch_feed(); + await this.fetch_feed_preview(); this.render_feed(); } @@ -349,7 +349,7 @@ export class FeedInspector { $("#main-panel").classList.remove("hidden"); // show feed preview - await this.fetch_feed(); + await this.fetch_feed_preview(); this.render_feed(); } @@ -404,7 +404,7 @@ export class FeedInspector { } } - async fetch_feed() { + async fetch_feed_preview() { if (!this.current_endpoint) return; const { path } = this.current_endpoint; @@ -412,30 +412,23 @@ export class FeedInspector { $("#feed-preview").classList.add("loading"); const time_start = performance.now(); - const request_path = `${path}?${params}`; - $("#fetch-status").innerText = `Fetching ${request_path}...`; + $("#fetch-status").innerText = `Fetching preview for ${path}...`; - const [resp, json_preview_resp] = await Promise.all([ - fetch(`${path}?${params}`), - fetch(`/_inspector/json_preview?endpoint=${path}&${params}&pp=1`), - ]); + const resp = await fetch(`/_inspector/preview?endpoint=${path}&${params}`); let status_text = ""; if (resp.status != 200) { - status_text = `Failed fetching ${request_path}`; + status_text = `Failed fetching ${path}`; status_text += ` (status: ${resp.status} ${resp.statusText})`; this.update_feed_error(await resp.text()); } else { this.update_feed_error(null); - const text = await resp.text(); - this.raw_feed_content = text; - status_text = `Fetched ${request_path} `; - status_text += `(content-type: ${resp.headers.get("content-type")})`; + const preview = await resp.json(); + this.raw_feed_content = preview.content; + this.json_preview_content = preview.json; + status_text = `Fetched ${path} (${preview.content_type})`; } - this.json_preview_content = - json_preview_resp.status === 200 ? await json_preview_resp.json() : null; - status_text += ` in ${performance.now() - time_start}ms.`; $("#fetch-status").innerText = status_text; $("#feed-preview").classList.remove("loading");