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
|
# File 'lib/http_mimic/waf/akamai_solver.rb', line 12
def solve(target_url, initial_response, options = {})
cookies = initial_response.cookies.dup
impersonate = options[:impersonate] || HttpMimic.configuration.default_impersonate || 'chrome131'
sensor_script_url = (target_url, initial_response.body)
return nil unless sensor_script_url
script_resp = HttpMimic.get(
sensor_script_url,
impersonate: impersonate,
cookies: cookies,
headers: { 'Referer' => target_url },
auto_fallback: false,
solve_waf: false
)
return nil unless script_resp.success?
sensor_js = script_resp.body
context_js = File.read(CONTEXT_JS_PATH)
cookie_str = cookies.to_cookie_string
doc_title = initial_response.title.to_s
user_agent = options[:user_agent]
referer = (options[:headers] || {})['Referer'] || (options[:headers] || {})['referer'] || target_url
driver_script = <<~JS
globalThis.__TARGET_URL__ = #{target_url.to_json};
globalThis.__DOCUMENT_TITLE__ = #{doc_title.to_json};
globalThis.__INITIAL_COOKIES__ = #{cookie_str.to_json};
globalThis.__REFERRER__ = #{referer.to_json};
#{user_agent ? "globalThis.__USER_AGENT__ = #{user_agent.to_json};" : ""}
#{context_js}
#{sensor_js}
if (typeof globalThis.__simulateHumanInteractions === "function") {
globalThis.__simulateHumanInteractions();
}
if (typeof globalThis.__drainEventLoop === "function") {
globalThis.__drainEventLoop(100);
}
JSON.stringify({
sensor_posts: globalThis.__sensor_posts
});
JS
result = JSRuntime.eval_json(driver_script)
sensor_posts = result && result['sensor_posts']
return nil if sensor_posts.nil? || sensor_posts.empty?
updated_cookies = cookies.dup
sensor_posts.each do |post|
post_body = post['body']
next if post_body.nil? || post_body.empty?
post_resp = HttpMimic.post(
sensor_script_url,
impersonate: impersonate,
cookies: updated_cookies,
headers: {
'Content-Type' => 'text/plain;charset=UTF-8',
'Referer' => target_url,
'Origin' => URI.parse(target_url).tap { |u| u.path = ''; u.query = nil }.to_s,
'Accept' => '*/*'
},
body: post_body,
auto_fallback: false,
solve_waf: false
)
post_resp.cookies.each { |k, v| updated_cookies[k] = v }
end
= (options[:headers] || {}).merge('Referer' => target_url)
HttpMimic.get(
target_url,
options.merge(
cookies: updated_cookies,
headers: ,
auto_fallback: false,
solve_waf: false
)
)
rescue StandardError => e
if HttpMimic.configuration.debug
puts "[HttpMimic::Waf::AkamaiSolver] Error solving Akamai challenge: #{e.message}"
end
nil
end
|