fix(indexer): preserve request status
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
use std::{collections::BTreeSet, time::Duration};
|
||||
|
||||
use quick_xml::events::Event;
|
||||
use reqwest::Client;
|
||||
use reqwest::{Client, StatusCode};
|
||||
use serde::Deserialize;
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -95,9 +95,13 @@ impl ProwlarrClient {
|
||||
.header("X-Api-Key", &self.api_key)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|_| Error::Request)?
|
||||
.map_err(|error| Error::Request {
|
||||
status: error.status(),
|
||||
})?
|
||||
.error_for_status()
|
||||
.map_err(|_| Error::Request)?;
|
||||
.map_err(|error| Error::Request {
|
||||
status: error.status(),
|
||||
})?;
|
||||
let indexers: Vec<ProwlarrIndexer> = response.json().await.map_err(|_| Error::Response)?;
|
||||
|
||||
let mut result = Vec::with_capacity(indexers.len());
|
||||
@@ -124,13 +128,19 @@ impl ProwlarrClient {
|
||||
.query(&[("apikey", self.api_key.as_str()), ("t", "caps")])
|
||||
.send()
|
||||
.await
|
||||
.map_err(|_| CapabilityError::Request)?
|
||||
.map_err(|error| CapabilityError::Request {
|
||||
status: error.status(),
|
||||
})?
|
||||
.error_for_status()
|
||||
.map_err(|_| CapabilityError::Request)?;
|
||||
.map_err(|error| CapabilityError::Request {
|
||||
status: error.status(),
|
||||
})?;
|
||||
let body = response
|
||||
.text()
|
||||
.await
|
||||
.map_err(|_| CapabilityError::Request)?;
|
||||
.map_err(|error| CapabilityError::Request {
|
||||
status: error.status(),
|
||||
})?;
|
||||
parse_capabilities(&body)
|
||||
}
|
||||
}
|
||||
@@ -140,17 +150,20 @@ impl ProwlarrClient {
|
||||
pub enum Error {
|
||||
#[error("could not create Prowlarr HTTP client")]
|
||||
Client,
|
||||
#[error("Prowlarr indexer request failed")]
|
||||
Request,
|
||||
#[error("Prowlarr indexer request failed (status: {status:?})")]
|
||||
Request { status: Option<StatusCode> },
|
||||
#[error("could not parse Prowlarr indexer response")]
|
||||
Response,
|
||||
}
|
||||
|
||||
/// A failed capabilities request for an otherwise usable Prowlarr indexer.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, Error, PartialEq)]
|
||||
pub enum CapabilityError {
|
||||
Request,
|
||||
#[error("capabilities request failed (status: {status:?})")]
|
||||
Request { status: Option<StatusCode> },
|
||||
#[error("capabilities response was not valid Torznab XML")]
|
||||
InvalidResponse,
|
||||
#[error("tracker returned Torznab error {code:?}: {description}")]
|
||||
Torznab {
|
||||
code: Option<u16>,
|
||||
description: String,
|
||||
@@ -273,6 +286,7 @@ fn is_available(value: &str) -> bool {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Capabilities, CapabilityError, ProwlarrClient};
|
||||
use reqwest::StatusCode;
|
||||
use wiremock::{
|
||||
matchers::{header, method, path, query_param},
|
||||
Mock, MockServer, ResponseTemplate,
|
||||
@@ -306,6 +320,7 @@ mod tests {
|
||||
include_str!("../tests/fixtures/broken-caps.xml"),
|
||||
)
|
||||
.await;
|
||||
mount_failure(&server, 29).await;
|
||||
|
||||
let indexers = ProwlarrClient::new(server.uri(), API_KEY)
|
||||
.expect("HTTP client can be created")
|
||||
@@ -313,7 +328,7 @@ mod tests {
|
||||
.await
|
||||
.expect("recorded Prowlarr responses are valid");
|
||||
|
||||
assert_eq!(indexers.len(), 3);
|
||||
assert_eq!(indexers.len(), 4);
|
||||
assert_eq!(indexers[0].id, 3);
|
||||
assert_eq!(indexers[0].name, "Alpha Tracker");
|
||||
assert!(indexers[0].capabilities.movie.available);
|
||||
@@ -337,6 +352,14 @@ mod tests {
|
||||
description: "Indexer unavailable".to_owned(),
|
||||
})
|
||||
);
|
||||
|
||||
assert_eq!(indexers[3].id, 29);
|
||||
assert_eq!(
|
||||
indexers[3].capabilities_error,
|
||||
Some(CapabilityError::Request {
|
||||
status: Some(StatusCode::SERVICE_UNAVAILABLE),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
async fn mount_capabilities(server: &MockServer, id: i64, body: &str) {
|
||||
@@ -348,4 +371,14 @@ mod tests {
|
||||
.mount(server)
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn mount_failure(server: &MockServer, id: i64) {
|
||||
Mock::given(method("GET"))
|
||||
.and(path(format!("/{id}/api")))
|
||||
.and(query_param("apikey", API_KEY))
|
||||
.and(query_param("t", "caps"))
|
||||
.respond_with(ResponseTemplate::new(503))
|
||||
.mount(server)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
{ "id": 3, "name": "Alpha Tracker", "enable": true },
|
||||
{ "id": 17, "name": "Text Only", "enable": true },
|
||||
{ "id": 23, "name": "Broken Tracker", "enable": true },
|
||||
{ "id": 29, "name": "Unavailable Tracker", "enable": true },
|
||||
{ "id": 42, "name": "Disabled Tracker", "enable": false }
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user