diff --git a/Cargo.toml b/Cargo.toml index 7960f8d..f3d9d23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,14 @@ [package] name = "raspa" version = "0.1.0" -authors = ["kirbylife "] +authors = ["kirbylife "] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +reqwest = { version = "0.10", features = ["blocking", "json"] } +tokio = { version = "0.2", features = ["full"] } +url = "2.1" +http = "0.2" +nipper = "0.1.8" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 31e1bb2..2cdd4d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,34 @@ +pub mod request; +pub mod response; +pub mod selector; + #[cfg(test)] mod tests { + use crate::request::{Request, RequestBase}; + use crate::selector::{Selector, SelectorBase}; + use http::StatusCode; + #[test] - fn it_works() { - assert_eq!(2 + 2, 4); + fn plain_text_selector() { + let html = " + + +

hello world

+

good bye

+ + +"; + let sel = Selector::from_html(html); + println!("{:?}", sel.css("h1")); + assert_eq!(sel.css("h1")[0].html(), "

hello world

"); + assert_eq!(sel.css("#text")[0].content(), "good bye"); + } + + #[test] + fn simple_request() { + let req: Request = RequestBase::new("https://httpbin.org/"); + let resp = req.launch(); + assert_eq!(resp.status_code, StatusCode::OK); + assert!(resp.css("h2")[0].html().contains("httpbin.org")); } } diff --git a/src/request.rs b/src/request.rs new file mode 100644 index 0000000..324603b --- /dev/null +++ b/src/request.rs @@ -0,0 +1,36 @@ +use crate::response; +use http::status::StatusCode; +use url::Url; + +pub trait RequestBase { + fn new(url: &'static str) -> Self; + fn launch(&self) -> response::Response; +} + +#[derive(Debug)] +pub struct Request { + pub url: url::Url, +} + +impl RequestBase for Request { + fn new(url: &'static str) -> Request { + Request { + url: Url::parse(url).unwrap(), + } + } + + fn launch(&self) -> response::Response { + let resp = reqwest::blocking::get(self.url.as_str()).unwrap(); + + let text: String = resp.text().unwrap(); + let status = StatusCode::OK; + + let url = self.url.clone(); + + response::Response { + text: text, + status_code: status, + url: url, + } + } +} diff --git a/src/response.rs b/src/response.rs new file mode 100644 index 0000000..0bfc9d2 --- /dev/null +++ b/src/response.rs @@ -0,0 +1,16 @@ +use crate::selector::SelectorBase; +use http::StatusCode; +use url::Url; + +#[derive(Debug)] +pub struct Response { + pub text: String, + pub status_code: StatusCode, + pub url: Url, +} + +impl SelectorBase for Response { + fn html(&self) -> &str { + self.text.as_str() + } +} diff --git a/src/selector.rs b/src/selector.rs new file mode 100644 index 0000000..94ec37c --- /dev/null +++ b/src/selector.rs @@ -0,0 +1,42 @@ +pub trait SelectorBase { + fn html(&self) -> &str; + + fn css(&self, css_selector: &'static str) -> Vec { + let html = nipper::Document::from(self.html()); + html.select(css_selector) + .iter() + .map(|element| Selector { + text: element.html().to_string(), + }) + .into_iter() + .collect::>() + } + + fn content(&self) -> String { + let html = nipper::Document::from(self.html()); + html.select("*") + .iter() + .map(|element| element.text().to_string()) + .last() + .unwrap() + } +} + +#[derive(Debug)] +pub struct Selector { + text: String, +} + +impl SelectorBase for Selector { + fn html(&self) -> &str { + self.text.as_str() + } +} + +impl Selector { + pub fn from_html(html: &'static str) -> Self { + Selector { + text: html.to_string(), + } + } +}