fix jable: FlaresolverrCookie missing fields + requester transport-error fallback
Three bugs prevented jable.tv from returning items: 1. FlaresolverrCookie deserialization (root cause): fields like `expires`, `size`, `priority`, `sameParty`, `sourceScheme`, `sourcePort` are omitted by FlareSolverr for session cookies, causing serde to fail with "missing field" and the entire solve to return Err. Added #[serde(default)] to all non-essential cookie fields. 2. Transport-error branch in get_with_headers: when direct fetch fails with a transport error and Jina returns a CF challenge body, the old code returned Ok(challenge_html) instead of falling through to FlareSolverr. Now checks looks_like_cloudflare_challenge and breaks to FS. 3. Post-FlareSolverr retry: wreq's Firefox136 TLS fingerprint causes CF to drop the connection even with FS cookies applied, so request.send() returns Err. Was propagated with `?`; now catches and returns res.solution.response (the headless-browser body) directly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,15 +19,24 @@ pub struct FlaresolverrCookie {
|
|||||||
pub value: String,
|
pub value: String,
|
||||||
pub domain: String,
|
pub domain: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
#[serde(default)]
|
||||||
pub expires: f64,
|
pub expires: f64,
|
||||||
|
#[serde(default)]
|
||||||
pub size: u64,
|
pub size: u64,
|
||||||
|
#[serde(default)]
|
||||||
pub httpOnly: bool,
|
pub httpOnly: bool,
|
||||||
|
#[serde(default)]
|
||||||
pub secure: bool,
|
pub secure: bool,
|
||||||
|
#[serde(default)]
|
||||||
pub session: bool,
|
pub session: bool,
|
||||||
pub sameSite: Option<String>,
|
pub sameSite: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub priority: String,
|
pub priority: String,
|
||||||
|
#[serde(default)]
|
||||||
pub sameParty: bool,
|
pub sameParty: bool,
|
||||||
|
#[serde(default)]
|
||||||
pub sourceScheme: String,
|
pub sourceScheme: String,
|
||||||
|
#[serde(default)]
|
||||||
pub sourcePort: u32,
|
pub sourcePort: u32,
|
||||||
pub partitionKey: Option<String>,
|
pub partitionKey: Option<String>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -535,15 +535,25 @@ impl Requester {
|
|||||||
}
|
}
|
||||||
let response = match request.send().await {
|
let response = match request.send().await {
|
||||||
Ok(response) => response,
|
Ok(response) => response,
|
||||||
Err(error) => {
|
Err(_error) => {
|
||||||
crate::flow_debug!(
|
crate::flow_debug!(
|
||||||
"trace={} requester direct transport failed url={} error={} using_jina_fallback=true",
|
"trace={} requester direct transport failed url={} error={} using_jina_fallback=true",
|
||||||
_trace_id,
|
_trace_id,
|
||||||
crate::util::flow_debug::preview(url, 120),
|
crate::util::flow_debug::preview(url, 120),
|
||||||
crate::util::flow_debug::preview(&error.to_string(), 160)
|
crate::util::flow_debug::preview(&_error.to_string(), 160)
|
||||||
);
|
);
|
||||||
match jina_handle.await {
|
match jina_handle.await {
|
||||||
Ok(Ok(body)) => return Ok(body),
|
Ok(Ok(body)) => {
|
||||||
|
if Self::looks_like_cloudflare_challenge(&body) {
|
||||||
|
crate::flow_debug!(
|
||||||
|
"trace={} requester jina fallback returned cloudflare challenge after transport error url={} using_flaresolverr=true",
|
||||||
|
_trace_id,
|
||||||
|
crate::util::flow_debug::preview(url, 120)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Ok(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(Err(_jina_error)) => {
|
Ok(Err(_jina_error)) => {
|
||||||
crate::flow_debug!(
|
crate::flow_debug!(
|
||||||
"trace={} requester jina fallback failed after transport error url={} error={}",
|
"trace={} requester jina fallback failed after transport error url={} error={}",
|
||||||
@@ -551,7 +561,6 @@ impl Requester {
|
|||||||
crate::util::flow_debug::preview(url, 120),
|
crate::util::flow_debug::preview(url, 120),
|
||||||
crate::util::flow_debug::preview(&_jina_error.to_string(), 160)
|
crate::util::flow_debug::preview(&_jina_error.to_string(), 160)
|
||||||
);
|
);
|
||||||
return Err(error.into());
|
|
||||||
}
|
}
|
||||||
Err(_join_error) => {
|
Err(_join_error) => {
|
||||||
crate::flow_debug!(
|
crate::flow_debug!(
|
||||||
@@ -560,9 +569,9 @@ impl Requester {
|
|||||||
crate::util::flow_debug::preview(url, 120),
|
crate::util::flow_debug::preview(url, 120),
|
||||||
crate::util::flow_debug::preview(&_join_error.to_string(), 160)
|
crate::util::flow_debug::preview(&_join_error.to_string(), 160)
|
||||||
);
|
);
|
||||||
return Err(error.into());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.store_response_cookies(url, &response);
|
self.store_response_cookies(url, &response);
|
||||||
@@ -714,7 +723,17 @@ impl Requester {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = request.send().await?;
|
let response = match request.send().await {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(_retry_err) => {
|
||||||
|
crate::flow_debug!(
|
||||||
|
"trace={} requester post-flaresolverr retry transport failed url={} using_flaresolverr_body=true",
|
||||||
|
self.debug_trace_id().unwrap_or("none"),
|
||||||
|
crate::util::flow_debug::preview(url, 120)
|
||||||
|
);
|
||||||
|
return Ok(res.solution.response);
|
||||||
|
}
|
||||||
|
};
|
||||||
self.store_response_cookies(url, &response);
|
self.store_response_cookies(url, &response);
|
||||||
crate::flow_debug!(
|
crate::flow_debug!(
|
||||||
"trace={} requester retry response url={} status={}",
|
"trace={} requester retry response url={} status={}",
|
||||||
|
|||||||
Reference in New Issue
Block a user