diff --git a/Cargo.toml b/Cargo.toml index ee5bc91..6b94f08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,13 +21,15 @@ serde_qs = "0.10.1" serde_urlencoded = "0.7.1" tap-reader = "1" url = "1" -# Provides parsing for the link header in get_links() in page.rs -hyper-old-types = "0.11.0" futures-util = "0.3.25" static_assertions = "1.1.0" percent-encoding = "2.2.0" thiserror = "1.0.38" +[dependencies.parse_link_header] +version = "0.3.3" +features = ["url"] + [dependencies.uuid] version = "1.2.2" features = ["v4"] diff --git a/src/errors.rs b/src/errors.rs index 635d9ee..673d956 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -2,7 +2,6 @@ use std::{error, fmt, io::Error as IoError, num::TryFromIntError}; #[cfg(feature = "env")] use envy::Error as EnvyError; -use hyper_old_types::Error as HeaderParseError; use reqwest::{header::ToStrError as HeaderStrError, Error as HttpError, StatusCode}; use serde::Deserialize; use serde_json::Error as SerdeError; @@ -69,8 +68,16 @@ pub enum Error { #[error("Error converting an http header to a string")] HeaderStrError(#[from] HeaderStrError), /// Error parsing the http Link header - #[error("Error parsing the http Link header")] - HeaderParseError(#[from] HeaderParseError), + #[error("error parsing http link header")] + LinkHeaderParse(#[from] parse_link_header::Error), + /// Error returned when an unexpected rel was parsed. + #[error("unrecognized rel {rel:?} in link header {link:?}")] + UnrecognizedRel { + /// The relation which was not recognized + rel: String, + /// The raw link header + link: String, + }, #[cfg(feature = "env")] /// Error deserializing config from the environment #[error("Error deserializing config from the environment")] diff --git a/src/page.rs b/src/page.rs index 82348c4..98e1f2f 100644 --- a/src/page.rs +++ b/src/page.rs @@ -1,9 +1,6 @@ use super::{Mastodon, Result}; -use crate::{ - entities::itemsiter::ItemsIter, format_err, helpers::read_response::read_response, Error, -}; +use crate::{entities::itemsiter::ItemsIter, helpers::read_response::read_response, Error}; use futures::Stream; -use hyper_old_types::header::{parsing, Link, RelationType}; use log::{as_debug, as_serde, debug, error, trace}; use reqwest::{header::LINK, Response, Url}; use serde::{Deserialize, Serialize}; @@ -171,30 +168,19 @@ fn get_links(response: &Response, call_id: Uuid) -> Result<(Option, Option< if let Some(link_header) = response.headers().get(LINK) { let link_header = link_header.to_str()?; + let raw_link_header = link_header.to_string(); trace!(link_header = link_header, call_id = as_debug!(call_id); "parsing link header"); - let link_header = link_header.as_bytes(); - let link_header: Link = parsing::from_raw_str(link_header)?; - for value in link_header.values() { - if let Some(relations) = value.rel() { - if relations.contains(&RelationType::Next) { - // next = Some(Url::parse(value.link())?); - next = if let Ok(url) = Url::parse(value.link()) { - trace!(next = url.as_str(), call_id = as_debug!(call_id); "parsed link header"); - Some(url) - } else { - // HACK: url::ParseError::into isn't working for some reason. - return Err(format_err!("error parsing url {:?}", value.link())); - }; - } - - if relations.contains(&RelationType::Prev) { - prev = if let Ok(url) = Url::parse(value.link()) { - trace!(prev = url.as_str(), call_id = as_debug!(call_id); "parsed link header"); - Some(url) - } else { - // HACK: url::ParseError::into isn't working for some reason. - return Err(format_err!("error parsing url {:?}", value.link())); - }; + let link_header = parse_link_header::parse(link_header)?; + for (rel, link) in link_header.iter() { + match rel.as_ref().map(|it| it.as_str()) { + Some("next") => next = Some(link.uri.clone()), + Some("prev") => prev = Some(link.uri.clone()), + None => debug!(link = as_debug!(link); "link header with no rel specified"), + Some(other) => { + return Err(Error::UnrecognizedRel { + rel: other.to_string(), + link: raw_link_header, + }) } } }