1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Network request types for browser-resident HTTP replay and inspection.
//!
//! - [`NetworkLogRequest`] reads entries captured by the in-page `fetch`/
//! `XMLHttpRequest` wrappers installed in `install_page_hooks`. The agent
//! uses this to discover the exact headers (notably `Authorization:
//! Bearer …`) the page sent.
//! - [`FetchRequest`] replays an HTTP request from inside the active tab
//! via `page.evaluate(fetch(…))`. Because the request runs in the page's
//! own JS context, cookies, TLS fingerprint, and Origin all match what a
//! real user click would produce.
use Serialize;
use HashMap;
/// Replay an HTTP request through the page's own axios instance.
///
/// Unlike [`FetchRequest`], this reuses every interceptor the app has
/// installed (auth header injection, CSRF tokens, baseURL rewrites,
/// request IDs), which is often the only way to reproduce a request that
/// `fetch` rejects with "Failed to fetch" due to CORS / preflight /
/// service-worker routing differences.
///
/// `axios_path` lets the caller override the discovery lookup (e.g.
/// `"window.__APP__.api"` or `"window.axios"`); when `None`, the handler
/// auto-discovers the first object on `window` that looks like an axios
/// instance (has `.defaults.baseURL` or `.defaults.headers.common`).
/// Diagnostic snapshot of the page's HTTP plumbing.
///
/// Returns a JSON blob describing service workers, discovered axios
/// instances (with their `baseURL` and a sample of common headers),
/// recently-seen request initiators, and document CSP. Useful when
/// `fetch` replay fails with a transport-layer error and the agent
/// needs to decide whether to fall back to axios, hook the app's save
/// function, or call the worker directly.
/// Replay an HTTP request through a raw `XMLHttpRequest` inside the page.
///
/// Use this when [`FetchRequest`] returns "Failed to fetch" but
/// `network_log` shows the app's own successful request had `kind: xhr`.
/// The XHR transport differs from `fetch` in several ways that matter for
/// WAF / CORS / service-worker routing:
///
/// - XHR does not send `Sec-Fetch-Mode: cors` / `Sec-Fetch-Dest: empty`
/// headers the same way, which some edge rules use to block tool replays.
/// - XHR inherits the document's full cookie jar and Origin by default;
/// there is no `credentials: 'omit'` equivalent.
/// - Service workers often pass XHR through untouched while intercepting
/// `fetch`, so a SW-rewriting auth header won't affect this path.
/// - Simple XHRs (GET/POST with allowlisted headers) skip CORS preflight
/// on the same rules as the original page script.
///
/// Request body is sent verbatim; set `Content-Type` explicitly in
/// `headers` when sending JSON.
/// Replay a request captured in `window.__codetether_net_log` with
/// optional edits.
///
/// Finds the most recent entry whose URL contains [`url_contains`]
/// (and, optionally, matches [`method_filter`]), inherits its
/// captured method, URL, and request headers (including
/// `Authorization`), and re-fires via raw XHR. The captured request
/// body is used as-is unless one of:
///
/// - [`body_override`] — replaces the body with an arbitrary string
/// - [`body_patch`] — deep-merged into the captured body when it
/// parses as JSON (other keys in the captured body are preserved)
///
/// [`url_override`] / [`method_override`] replace the captured URL /
/// method if set. Headers supplied via [`extra_headers`] are overlaid
/// on top of the captured headers.
///
/// This exists so the agent can perform the common "capture one real
/// save, then re-save with different fields" workflow without
/// reconstructing the request from scratch.
///
/// [`url_contains`]: Self::url_contains
/// [`method_filter`]: Self::method_filter
/// [`url_override`]: Self::url_override
/// [`method_override`]: Self::method_override
/// [`body_override`]: Self::body_override
/// [`body_patch`]: Self::body_patch
/// [`extra_headers`]: Self::extra_headers