tail_fin_common/
interceptor.rs1use night_fury_core::BrowserSession;
2use serde_json::Value;
3
4use crate::error::TailFinError;
5
6pub async fn install_interceptor(
12 session: &BrowserSession,
13 pattern: &str,
14) -> Result<(), TailFinError> {
15 let pattern_escaped = serde_json::to_string(pattern).unwrap_or_default();
16 let js = format!(
17 r#"
18 (() => {{
19 if (window.__tailfin_interceptor_active) return 'already_installed';
20
21 window.__tailfin_captured = [];
22 window.__tailfin_interceptor_active = true;
23
24 window.__tailfin_original_fetch = window.fetch;
25 const _originalFetch = window.fetch;
26 window.fetch = async function(...args) {{
27 const resp = await _originalFetch.apply(this, args);
28 try {{
29 const url = typeof args[0] === 'string' ? args[0] : (args[0]?.url || '');
30 if (url.includes({pattern_escaped})) {{
31 const clone = resp.clone();
32 const json = await clone.json();
33 window.__tailfin_captured.push({{ url: url, data: json }});
34 }}
35 }} catch (e) {{
36 // Silently ignore parse errors for non-JSON responses
37 }}
38 return resp;
39 }};
40 return 'installed';
41 }})()
42 "#
43 );
44
45 session.eval(&js).await?;
46 Ok(())
47}
48
49pub async fn read_captured(session: &BrowserSession) -> Result<Vec<Value>, TailFinError> {
51 let result = session
52 .eval("JSON.parse(JSON.stringify(window.__tailfin_captured || []))")
53 .await?;
54
55 match result {
56 Value::Array(arr) => Ok(arr),
57 Value::Null => Ok(vec![]),
58 _ => Err(TailFinError::Parse(
59 "unexpected interceptor result type".into(),
60 )),
61 }
62}
63
64pub async fn clear_captured(session: &BrowserSession) -> Result<(), TailFinError> {
66 session.eval("window.__tailfin_captured = []").await?;
67 Ok(())
68}
69
70pub async fn remove_interceptor(session: &BrowserSession) -> Result<(), TailFinError> {
72 let js = r#"
73 (() => {
74 if (window.__tailfin_interceptor_active) {
75 window.fetch = window.__tailfin_original_fetch || window.fetch;
76 window.__tailfin_interceptor_active = false;
77 window.__tailfin_captured = [];
78 delete window.__tailfin_original_fetch;
79 }
80 return 'removed';
81 })()
82 "#;
83
84 session.eval(js).await?;
85 Ok(())
86}