flaresolverr life cycle
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
use std::{collections::HashMap, env};
|
||||
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
use wreq::{Client, Proxy};
|
||||
use wreq_util::Emulation;
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||
pub struct FlareSolverrRequest {
|
||||
pub cmd: String,
|
||||
pub url: String,
|
||||
@@ -64,20 +65,16 @@ impl Flaresolverr {
|
||||
self.proxy = proxy;
|
||||
}
|
||||
|
||||
pub async fn solve(
|
||||
async fn post_payload(
|
||||
&self,
|
||||
request: FlareSolverrRequest,
|
||||
) -> Result<FlareSolverrResponse, Box<dyn std::error::Error>> {
|
||||
payload: Value,
|
||||
) -> Result<Value, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let client = Client::builder().emulation(Emulation::Firefox136).build()?;
|
||||
|
||||
let mut req = client
|
||||
.post(&self.url)
|
||||
.header("Content-Type", "application/json")
|
||||
.json(&json!({
|
||||
"cmd": request.cmd,
|
||||
"url": request.url,
|
||||
"maxTimeout": request.maxTimeout,
|
||||
}));
|
||||
.json(&payload);
|
||||
|
||||
if self.proxy {
|
||||
if let Ok(proxy_url) = env::var("BURP_URL") {
|
||||
@@ -93,8 +90,72 @@ impl Flaresolverr {
|
||||
}
|
||||
|
||||
let response = req.send().await?;
|
||||
|
||||
let body = response.json::<FlareSolverrResponse>().await?;
|
||||
let body = response.json::<Value>().await?;
|
||||
if body
|
||||
.get("status")
|
||||
.and_then(Value::as_str)
|
||||
.is_some_and(|status| status.eq_ignore_ascii_case("error"))
|
||||
{
|
||||
let message = body
|
||||
.get("message")
|
||||
.and_then(Value::as_str)
|
||||
.unwrap_or("FlareSolverr returned status=error");
|
||||
return Err(message.to_string().into());
|
||||
}
|
||||
Ok(body)
|
||||
}
|
||||
|
||||
async fn create_session(&self) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let body = self.post_payload(json!({ "cmd": "sessions.create" })).await?;
|
||||
let session = body
|
||||
.get("session")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or("sessions.create response missing `session`")?;
|
||||
Ok(session.to_string())
|
||||
}
|
||||
|
||||
async fn destroy_session(
|
||||
&self,
|
||||
session: &str,
|
||||
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let _ = self
|
||||
.post_payload(json!({
|
||||
"cmd": "sessions.destroy",
|
||||
"session": session,
|
||||
}))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn solve_with_session(
|
||||
&self,
|
||||
request: FlareSolverrRequest,
|
||||
session: &str,
|
||||
) -> Result<FlareSolverrResponse, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let body = self
|
||||
.post_payload(json!({
|
||||
"cmd": request.cmd,
|
||||
"url": request.url,
|
||||
"maxTimeout": request.maxTimeout,
|
||||
"session": session,
|
||||
}))
|
||||
.await?;
|
||||
let typed = serde_json::from_value::<FlareSolverrResponse>(body)?;
|
||||
Ok(typed)
|
||||
}
|
||||
|
||||
pub async fn solve(
|
||||
&self,
|
||||
request: FlareSolverrRequest,
|
||||
) -> Result<FlareSolverrResponse, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let session = self.create_session().await?;
|
||||
let result = self.solve_with_session(request, &session).await;
|
||||
if let Err(error) = self.destroy_session(&session).await {
|
||||
eprintln!(
|
||||
"FlareSolverr session cleanup failed for session '{}': {}",
|
||||
session, error
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user