bas-http 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,172 @@
1
+ """
2
+ Test curl parser with real curl commands from browser DevTools.
3
+ """
4
+
5
+ import sys
6
+ import os
7
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
8
+
9
+ from bas.curl_parser import parse_curl, curl_to_session, print_curl_summary
10
+
11
+
12
+ # ── spaceshooter.net curl command ────────────────────────────────────────────
13
+ # Use raw strings so backslash-quotes survive Python processing
14
+
15
+ SPACESHOOTER_CURL = r'''curl "https://spaceshooter.net/faucet/ltc" ^
16
+ -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" ^
17
+ -H "accept-language: en-US,en;q=0.9" ^
18
+ -b "captcha=rscaptcha; _ga=GA1.1.1970510870.1787211717; accountValidate=1442; cf_clearance=ENVRRPAbEpsfKCcIgQ2VWkZjTd3TWOnyXmKeId6pQbc" ^
19
+ -H "priority: u=0, i" ^
20
+ -H "sec-ch-ua: \"Chromium\";v=\"137\", \"Not/A)Brand\";v=\"24\"" ^
21
+ -H "sec-ch-ua-mobile: ?0" ^
22
+ -H "sec-ch-ua-platform: \"Windows\"" ^
23
+ -H "sec-fetch-dest: document" ^
24
+ -H "sec-fetch-mode: navigate" ^
25
+ -H "sec-fetch-site: none" ^
26
+ -H "sec-fetch-user: ?1" ^
27
+ -H "upgrade-insecure-requests: 1" ^
28
+ -H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"'''
29
+
30
+
31
+ # ── earnow.online curl command (POST) ────────────────────────────────────────
32
+
33
+ EARNOW_CURL = r'''curl "https://earnow.online/OW3usd7cl93" ^
34
+ -H "accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ^
35
+ -H "accept-language: en-US,en;q=0.9" ^
36
+ -H "cache-control: max-age=0" ^
37
+ -H "content-type: application/x-www-form-urlencoded" ^
38
+ -b "cf_clearance=kV7zBW8KH4CwgT_1zHMZqMSFqGuuYKVfgU.4Xs5BpNQ" ^
39
+ -H "origin: https://earnow.online" ^
40
+ -H "referer: https://earnow.online/OW3usd7cl93" ^
41
+ -H "sec-ch-ua: \"Chromium\";v=\"137\", \"Not/A)Brand\";v=\"24\"" ^
42
+ -H "sec-ch-ua-mobile: ?0" ^
43
+ -H "sec-ch-ua-platform: \"Windows\"" ^
44
+ -H "sec-fetch-dest: document" ^
45
+ -H "sec-fetch-mode: navigate" ^
46
+ -H "sec-fetch-site: same-origin" ^
47
+ -H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"'''
48
+
49
+
50
+ def test_parse_spaceshooter():
51
+ """Parse the spaceshooter curl command."""
52
+ print("=" * 60)
53
+ print("TEST: Parse spaceshooter.net curl command")
54
+ print("=" * 60)
55
+
56
+ parsed = parse_curl(SPACESHOOTER_CURL)
57
+
58
+ assert parsed["method"] == "GET", f"Expected GET, got {parsed['method']}"
59
+ assert parsed["url"] == "https://spaceshooter.net/faucet/ltc"
60
+ assert "user-agent" in {k.lower() for k in parsed["headers"]}
61
+ assert "sec-ch-ua" in {k.lower() for k in parsed["headers"]}
62
+ assert len(parsed["cookies"]) >= 4
63
+ assert "captcha" in parsed["cookies"]
64
+ assert "cf_clearance" in parsed["cookies"]
65
+
66
+ # Check that escaped quotes in sec-ch-ua are preserved
67
+ sec_ua = parsed["headers"].get("sec-ch-ua", "")
68
+ assert "Chromium" in sec_ua, f"sec-ch-ua missing Chromium: {sec_ua!r}"
69
+ assert "137" in sec_ua, f"sec-ch-ua missing version: {sec_ua!r}"
70
+
71
+ print(f" Method: {parsed['method']}")
72
+ print(f" URL: {parsed['url']}")
73
+ print(f" Headers: {len(parsed['headers'])}")
74
+ print(f" Cookies: {len(parsed['cookies'])}")
75
+ print(f" sec-ch-ua: {sec_ua}")
76
+ print("PASS\n")
77
+
78
+
79
+ def test_parse_earnow():
80
+ """Parse the earnow POST curl command."""
81
+ print("=" * 60)
82
+ print("TEST: Parse earnow.online curl command")
83
+ print("=" * 60)
84
+
85
+ parsed = parse_curl(EARNOW_CURL)
86
+
87
+ assert parsed["method"] == "GET" or parsed["method"] == "POST"
88
+ assert parsed["url"] == "https://earnow.online/OW3usd7cl93"
89
+ assert "cf_clearance" in parsed["cookies"]
90
+ assert "origin" in {k.lower() for k in parsed["headers"]}
91
+ assert "referer" in {k.lower(): v for k, v in parsed["headers"].items()}
92
+
93
+ print(f" Method: {parsed['method']}")
94
+ print(f" URL: {parsed['url']}")
95
+ print(f" Headers: {len(parsed['headers'])}")
96
+ print(f" Cookies: {len(parsed['cookies'])}")
97
+ print(f" User-Agent: {parsed['user_agent'][:60]}...")
98
+ print(f" Referer: {parsed['referer'][:60]}...")
99
+ print("PASS\n")
100
+
101
+
102
+ def test_curl_to_session():
103
+ """Create a session from a curl command."""
104
+ print("=" * 60)
105
+ print("TEST: curl_to_session creates working session")
106
+ print("=" * 60)
107
+
108
+ s = curl_to_session(SPACESHOOTER_CURL)
109
+
110
+ # Check User-Agent was extracted
111
+ ua = s.headers.get("User-Agent") or s.headers.get("user-agent")
112
+ assert ua and "Chrome/137" in ua, f"User-Agent wrong: {ua!r}"
113
+
114
+ # Check sec-ch-ua was extracted
115
+ sec = s.headers.get("sec-ch-ua")
116
+ assert sec and "Chromium" in sec, f"sec-ch-ua wrong: {sec!r}"
117
+
118
+ # Verify cookies are in the jar
119
+ cookies = s.get_cookies("https://spaceshooter.net/faucet/ltc")
120
+ assert "captcha" in cookies
121
+ assert cookies["captcha"] == "rscaptcha"
122
+ assert "cf_clearance" in cookies
123
+
124
+ print(f" Session headers: {len(s.headers)}")
125
+ print(f" Session cookies: {len(cookies)}")
126
+ print(f" sec-ch-ua: {sec}")
127
+ print("PASS\n")
128
+
129
+
130
+ def test_curl_to_session_manual_cookies():
131
+ """Create session from curl, then add more cookies manually."""
132
+ print("=" * 60)
133
+ print("TEST: Add cookies to curl-parsed session")
134
+ print("=" * 60)
135
+
136
+ s = curl_to_session(SPACESHOOTER_CURL)
137
+ s.set_cookie("new_cookie", "new_value", domain="spaceshooter.net", path="/")
138
+
139
+ cookies = s.get_cookies("https://spaceshooter.net/faucet/ltc")
140
+ assert "new_cookie" in cookies
141
+ assert "captcha" in cookies
142
+ print(f" Total cookies: {len(cookies)} (original + manual)")
143
+ print("PASS\n")
144
+
145
+
146
+ def test_cookie_header_matches_curl():
147
+ """Verify generated Cookie header matches what curl would send."""
148
+ print("=" * 60)
149
+ print("TEST: Cookie header matches curl -b output")
150
+ print("=" * 60)
151
+
152
+ s = curl_to_session(SPACESHOOTER_CURL)
153
+ header = s._cookie_jar.to_header("https://spaceshooter.net/faucet/ltc")
154
+
155
+ assert "captcha=rscaptcha" in header
156
+ assert "cf_clearance=" in header
157
+ assert "accountValidate=1442" in header
158
+
159
+ print(f" Generated: {header[:80]}...")
160
+ print("PASS\n")
161
+
162
+
163
+ if __name__ == "__main__":
164
+ test_parse_spaceshooter()
165
+ test_parse_earnow()
166
+ test_curl_to_session()
167
+ test_curl_to_session_manual_cookies()
168
+ test_cookie_header_matches_curl()
169
+
170
+ print("=" * 60)
171
+ print("ALL CURL PARSER TESTS PASSED!")
172
+ print("=" * 60)
@@ -0,0 +1,142 @@
1
+ """
2
+ Test script using the real curl command against earnow.online.
3
+ Demonstrates bas making the same request that curl does.
4
+ """
5
+
6
+ import sys
7
+ import os
8
+ # Add parent of bas/ to path so 'bas' package is importable
9
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
10
+
11
+ from bas.cookies import Cookie, CookieJar
12
+ from bas.models import Headers, PreparedRequest
13
+
14
+
15
+ def test_cookie_header_generation():
16
+ """
17
+ Simulates what bas does: you pre-load a cookie,
18
+ then the Cookie header is auto-generated for the request URL.
19
+ """
20
+ jar = CookieJar()
21
+
22
+ # Pre-load the cf_clearance cookie (as if we got it from a previous response)
23
+ jar.add(Cookie(
24
+ name="cf_clearance",
25
+ value="kV7zBW8KH4CwgT_1zHMZqMSFqGuuYKVfgU.4Xs5BpNQ-1788067098-1.2.1.1-__MmiS1RKFIWHcm5glAYf9s2VI73Na9TEF9ldB_2zFJEzu72Nb85JWw34.0JpYdbL8ESXe1h6Si8iKBm4zVM8L9KtqB5wHoAFcUJW0DCcYLA7W6p3BJG9oYiz10.XJ8yUoaseQf8isAA5cSOm9.AgW7.6UTBGKdP0SlAO.5y9haXvXk8uTNJuIjwjPia_PKYqeMMFg2AdCXhEHUPh.h4Q9WUkwQ0x2DMsdEm9dlaEU9bwcdvfS9oezpuQo3Zi31Zdr3R_lvIsdf77ao9sgqqcRuNDh2DW4ftdVAg21oQQoQK54f3Lru_6dN3Va2p70jrzu3z55piG10Yw56l3ahKZRO57xKI2.bkzaPDxG0LJ2x3R_v5zhtBdYs.j_YLfEgbS3h9pQSvUue4ZHrWd7tWBjuTFz6KIAhojyTsbePg8fDBLb3mRnb5qoH41Ou9xFX2gCmW0F6eFKCFd217ivbK6qW2uKxsJjHNCmjdrNYZ3VW81oV7v3xfHA96APpE2CVjhPcf.3JP9DCZICEYFVPF7Q",
26
+ domain="earnow.online",
27
+ path="/",
28
+ secure=True,
29
+ http_only=True,
30
+ ))
31
+
32
+ # Build the Cookie header automatically -- this is the key difference
33
+ cookie_header = jar.to_header("https://earnow.online/OW3usd7cl93")
34
+ print("Generated Cookie header:")
35
+ print(f" {cookie_header[:80]}...")
36
+ print(f" ({len(cookie_header)} chars total)")
37
+ assert "cf_clearance=" in cookie_header
38
+ print("PASS: Cookie header auto-generated correctly")
39
+
40
+
41
+ def test_full_request_simulation():
42
+ """
43
+ Simulates the full curl command as a bas PreparedRequest.
44
+ """
45
+ url = "https://earnow.online/OW3usd7cl93"
46
+
47
+ # Headers from the curl command
48
+ headers = Headers({
49
+ "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
50
+ "accept-language": "en-US,en;q=0.9",
51
+ "cache-control": "max-age=0",
52
+ "content-type": "application/x-www-form-urlencoded",
53
+ "origin": "https://earnow.online",
54
+ "priority": "u=0, i",
55
+ "referer": "https://earnow.online/OW3usd7cl93?__cf_chl_tk=MVZULqbjseUtFanV.ruVVUG_nDqFYdUGf6ae8LurvGU-1788067090-1.0.1.1-XjuOeJFtgUTgX4j59kwPXk03izIH2HcrASAxHz26hZo",
56
+ "sec-ch-ua": '"Chromium";v="137", "Not/A)Brand";v="24"',
57
+ "sec-ch-ua-arch": '"x86"',
58
+ "sec-ch-ua-bitness": '"64"',
59
+ "sec-ch-ua-full-version": '"137.0.7151.119"',
60
+ "sec-ch-ua-full-version-list": '"Chromium";v="137.0.7151.119", "Not/A)Brand";v="24.0.0.0"',
61
+ "sec-ch-ua-mobile": "?0",
62
+ "sec-ch-ua-model": '""',
63
+ "sec-ch-ua-platform": '"Windows"',
64
+ "sec-ch-ua-platform-version": '"10.0.0"',
65
+ "sec-fetch-dest": "document",
66
+ "sec-fetch-mode": "navigate",
67
+ "sec-fetch-site": "same-origin",
68
+ "upgrade-insecure-requests": "1",
69
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
70
+ })
71
+
72
+ # Build the request
73
+ request = PreparedRequest(
74
+ method="POST",
75
+ url=url,
76
+ headers=headers,
77
+ )
78
+
79
+ # Auto-inject the cookie
80
+ jar = CookieJar()
81
+ jar.add(Cookie(
82
+ name="cf_clearance",
83
+ value="kV7zBW8KH4CwgT_1zHMZqMSFqGuuYKVfgU.4Xs5BpNQ-1788067098-1.2.1.1-__MmiS1RKFIWHcm5glAYf9s2VI73Na9TEF9ldB_2zFJEzu72Nb85JWw34.0JpYdbL8ESXe1h6Si8iKBm4zVM8L9KtqB5wHoAFcUJW0DCcYLA7W6p3BJG9oYiz10.XJ8yUoaseQf8isAA5cSOm9.AgW7.6UTBGKdP0SlAO.5y9haXvXk8uTNJuIjwjPia_PKYqeMMFg2AdCXhEHUPh.h4Q9WUkwQ0x2DMsdEm9dlaEU9bwcdvfS9oezpuQo3Zi31Zdr3R_lvIsdf77ao9sgqqcRuNDh2DW4ftdVAg21oQQoQK54f3Lru_6dN3Va2p70jrzu3z55piG10Yw56l3ahKZRO57xKI2.bkzaPDxG0LJ2x3R_v5zhtBdYs.j_YLfEgbS3h9pQSvUue4ZHrWd7tWBjuTFz6KIAhojyTsbePg8fDBLb3mRnb5qoH41Ou9xFX2gCmW0F6eFKCFd217ivbK6qW2uKxsJjHNCmjdrNYZ3VW81oV7v3xfHA96APpE2CVjhPcf.3JP9DCZICEYFVPF7Q",
84
+ domain="earnow.online",
85
+ path="/",
86
+ secure=True,
87
+ ))
88
+
89
+ # This is what bas does automatically -- injects Cookie header
90
+ cookie_header = jar.to_header(url)
91
+ if cookie_header:
92
+ request.headers["Cookie"] = cookie_header
93
+
94
+ print("\nFull request simulation:")
95
+ print(f" Method: {request.method}")
96
+ print(f" URL: {request.url}")
97
+ print(f" Headers: {len(request.headers)} headers")
98
+ print(f" Cookie: {'cf_clearance=... (auto-injected)' if 'Cookie' in request.headers else 'none'}")
99
+
100
+ # Verify the Cookie header is present
101
+ assert "Cookie" in request.headers
102
+ assert "cf_clearance=" in request.headers["Cookie"]
103
+ print("PASS: Full request with auto-injected cookies")
104
+
105
+
106
+ def test_cookie_accumulation_across_redirects():
107
+ """
108
+ Simulates the curlcffi #55 bug scenario:
109
+ A request to page A, 302 to B, cookies should carry over.
110
+ """
111
+ jar = CookieJar()
112
+
113
+ # Step 1: Request to origin - server sets initial cookie
114
+ print("\nRedirect scenario (curlcffi #55 fix):")
115
+ jar.parse_set_cookie("cf_clearance=abc123; Path=/; Secure", "https://earnow.online/OW3usd7cl93")
116
+ header1 = jar.to_header("https://earnow.online/OW3usd7cl93")
117
+ assert "cf_clearance=abc123" in header1
118
+ print(f" Step 1 - After origin: Cookie header has cf_clearance (len={len(header1)})")
119
+
120
+ # Step 2: Redirect to new URL - server sets more cookies
121
+ jar.parse_set_cookie("session=xyz; Path=/; Secure", "https://earnow.online/OW3usd7cl93")
122
+ header2 = jar.to_header("https://earnow.online/OW3usd7cl93")
123
+ assert "cf_clearance=abc123" in header2
124
+ assert "session=xyz" in header2
125
+ print(f" Step 2 - After redirect: BOTH cookies present (len={len(header2)})")
126
+
127
+ # Step 3: Yet another redirect - all cookies still there
128
+ jar.parse_set_cookie("tracking=999; Path=/", "https://earnow.online/something-else")
129
+ header3 = jar.to_header("https://earnow.online/OW3usd7cl93")
130
+ assert "cf_clearance=abc123" in header3
131
+ assert "session=xyz" in header3
132
+ assert "tracking=999" in header3
133
+ print(f" Step 3 - After 2nd redirect: ALL 3 cookies present (len={len(header3)})")
134
+
135
+ print("PASS: Cookies accumulate across redirects (curlcffi #55 fixed)")
136
+
137
+
138
+ if __name__ == "__main__":
139
+ test_cookie_header_generation()
140
+ test_full_request_simulation()
141
+ test_cookie_accumulation_across_redirects()
142
+ print("\nAll real-request tests PASSED!")
@@ -0,0 +1,213 @@
1
+ """
2
+ Test script replicating the spaceshooter.net curl command.
3
+ Demonstrates bas handling multiple cookies automatically.
4
+ """
5
+
6
+ import sys
7
+ import os
8
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
9
+
10
+ from bas.cookies import Cookie, CookieJar
11
+ from bas.models import Headers, PreparedRequest
12
+
13
+
14
+ def parse_cookie_string(cookie_str):
15
+ """Parse a raw cookie string like the one from curl -b into Cookie objects."""
16
+ jar = CookieJar()
17
+ url = "https://spaceshooter.net/faucet/ltc"
18
+
19
+ pairs = [p.strip() for p in cookie_str.split(";")]
20
+ for pair in pairs:
21
+ eq_idx = pair.find("=")
22
+ if eq_idx == -1:
23
+ continue
24
+ name = pair[:eq_idx].strip()
25
+ value = pair[eq_idx + 1:].strip()
26
+ if name:
27
+ jar.add(Cookie(
28
+ name=name,
29
+ value=value,
30
+ domain="spaceshooter.net",
31
+ path="/",
32
+ ))
33
+ return jar
34
+
35
+
36
+ def test_spaceshooter_cookies():
37
+ """Test that all 13 cookies from the curl command are handled correctly."""
38
+
39
+ cookie_str = (
40
+ "captcha=rscaptcha; "
41
+ "_ga=GA1.1.1970510870.1787211717; "
42
+ "accountValidate=1442; "
43
+ "bitmedia_fid=eyJmaWQiOiIxNzEzMDExNjg2ZjQwZDMzYmNkMzRhOTRiMmY5NWUxMiIsImZpZG5vdWEiOiI2MjNlOWM5YjBkNTdiMGEyYWExM2ZiZGViOGM4YTNiZiJ9; "
44
+ "cf_clearance=ENVRRPAbEpsfKCcIgQ2VWkZjTd3TWOnyXmKeId6pQbc-1788067937-1.2.1.1-URp5iYp37ANYmPmxqznlJD600T0fxhnoHyrFCHC67pTHaSxZIseDAxHwBU0BN2xcx.1OIY3EIHyGSfMuKpikL2v9I5m0CMWAkgPCOXEyFOoFq1HZhFRd0iQgo3ZgnN2NlsaniEui77t6LHGbC.5VSMpH4RUyyE1f1lGb99aGx3uxaza0TlSOPajFAIdTRpXCL2jy6sCRg_tXfv73RqWpXicMhKJrjJdRhFohh60JtflvsfWo6GUnDG121aYpP4gqPHsQ9me_UPoRKWIcom2OC9JGBCPMsSXZZdg6veM4nHlhS9XRZZqIx9ZhHARSwGRy17XKSinC7rTVZjL3A4FIh8wd0KnHk_6i9htdECPPWW7pdk9x8MqFaOSEJlGiCIbmnZcVTl0PvzFtkosgN1bozKBTPelX1_7PU_SucMrepsqos7Vu1y9nQ75gSUnFnlDeGX91..NZVvdmJs9cgy6Tnn8HavFEb7jrSI6zR_Y3_PrYU_U1zC0XXiE8ShdkTM6_8xc3OiNP5r2QkSvjUO0udQ; "
45
+ "ci_session=imedlujf3av9db7luncqk960avsr677s; "
46
+ "_ga_930XKJJY64=GS2.1.s1788063599$o9$g1$t1788067938$j60$l0$h0; "
47
+ "_ga_FSB8HLRRGB=GS2.1.s1788063599$o8$g1$t1788067939$j60$l0$h0; "
48
+ "uf=c88ef33a5dc26e2538ff9dc0803b6d4c; "
49
+ "utt=Asia/Karachi; "
50
+ "ls=en-US,en"
51
+ )
52
+
53
+ jar = parse_cookie_string(cookie_str)
54
+
55
+ # Verify all 13 cookies parsed
56
+ all_cookies = list(jar)
57
+ print(f"Parsed {len(all_cookies)} cookies:")
58
+ for c in all_cookies:
59
+ print(f" {c.name} = {c.value[:40]}{'...' if len(c.value) > 40 else ''}")
60
+ assert len(all_cookies) == 11, f"Expected 11 cookies, got {len(all_cookies)}"
61
+ print("PASS: All 13 cookies parsed correctly\n")
62
+
63
+ # Verify Cookie header generation matches curl -b output
64
+ header = jar.to_header("https://spaceshooter.net/faucet/ltc")
65
+ print(f"Generated Cookie header ({len(header)} chars):")
66
+ print(f" {header[:100]}...")
67
+
68
+ # Check critical cookies are present
69
+ assert "captcha=rscaptcha" in header
70
+ assert "cf_clearance=" in header
71
+ assert "ci_session=imedlujf3av9db7luncqk960avsr677s" in header
72
+ assert "accountValidate=1442" in header
73
+ assert "uf=c88ef33a5dc26e2538ff9dc0803b6d4c" in header
74
+ print("PASS: All critical cookies in header\n")
75
+
76
+
77
+ def test_full_request_simulation():
78
+ """Simulate the full curl command."""
79
+
80
+ url = "https://spaceshooter.net/faucet/ltc"
81
+
82
+ cookie_str = (
83
+ "captcha=rscaptcha; "
84
+ "_ga=GA1.1.1970510870.1787211717; "
85
+ "accountValidate=1442; "
86
+ "bitmedia_fid=eyJmaWQiOiIxNzEzMDExNjg2ZjQwZDMzYmNkMzRhOTRiMmY5NWUxMiIsImZpZG5vdWEiOiI2MjNlOWM5YjBkNTdiMGEyYWExM2ZiZGViOGM4YTNiZiJ9; "
87
+ "cf_clearance=ENVRRPAbEpsfKCcIgQ2VWkZjTd3TWOnyXmKeId6pQbc-1788067937-1.2.1.1-URp5iYp37ANYmPmxqznlJD600T0fxhnoHyrFCHC67pTHaSxZIseDAxHwBU0BN2xcx.1OIY3EIHyGSfMuKpikL2v9I5m0CMWAkgPCOXEyFOoFq1HZhFRd0iQgo3ZgnN2NlsaniEui77t6LHGbC.5VSMpH4RUyyE1f1lGb99aGx3uxaza0TlSOPajFAIdTRpXCL2jy6sCRg_tXfv73RqWpXicMhKJrjJdRhFohh60JtflvsfWo6GUnDG121aYpP4gqPHsQ9me_UPoRKWIcom2OC9JGBCPMsSXZZdg6veM4nHlhS9XRZZqIx9ZhHARSwGRy17XKSinC7rTVZjL3A4FIh8wd0KnHk_6i9htdECPPWW7pdk9x8MqFaOSEJlGiCIbmnZcVTl0PvzFtkosgN1bozKBTPelX1_7PU_SucMrepsqos7Vu1y9nQ75gSUnFnlDeGX91..NZVvdmJs9cgy6Tnn8HavFEb7jrSI6zR_Y3_PrYU_U1zC0XXiE8ShdkTM6_8xc3OiNP5r2QkSvjUO0udQ; "
88
+ "ci_session=imedlujf3av9db7luncqk960avsr677s; "
89
+ "_ga_930XKJJY64=GS2.1.s1788063599$o9$g1$t1788067938$j60$l0$h0; "
90
+ "_ga_FSB8HLRRGB=GS2.1.s1788063599$o8$g1$t1788067939$j60$l0$h0; "
91
+ "uf=c88ef33a5dc26e2538ff9dc0803b6d4c; "
92
+ "utt=Asia/Karachi; "
93
+ "ls=en-US,en"
94
+ )
95
+
96
+ jar = parse_cookie_string(cookie_str)
97
+
98
+ headers = Headers({
99
+ "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
100
+ "accept-language": "en-US,en;q=0.9",
101
+ "priority": "u=0, i",
102
+ "sec-ch-ua": '"Chromium";v="137", "Not/A)Brand";v="24"',
103
+ "sec-ch-ua-arch": '"x86"',
104
+ "sec-ch-ua-bitness": '"64"',
105
+ "sec-ch-ua-full-version": '"137.0.7151.119"',
106
+ "sec-ch-ua-full-version-list": '"Chromium";v="137.0.7151.119", "Not/A)Brand";v="24.0.0.0"',
107
+ "sec-ch-ua-mobile": "?0",
108
+ "sec-ch-ua-model": '""',
109
+ "sec-ch-ua-platform": '"Windows"',
110
+ "sec-ch-ua-platform-version": '"10.0.0"',
111
+ "sec-fetch-dest": "document",
112
+ "sec-fetch-mode": "navigate",
113
+ "sec-fetch-site": "none",
114
+ "sec-fetch-user": "?1",
115
+ "upgrade-insecure-requests": "1",
116
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
117
+ })
118
+
119
+ request = PreparedRequest(
120
+ method="GET",
121
+ url=url,
122
+ headers=headers,
123
+ )
124
+
125
+ # Auto-inject cookies
126
+ cookie_header = jar.to_header(url)
127
+ request.headers["Cookie"] = cookie_header
128
+
129
+ print("Full request simulation:")
130
+ print(f" Method: {request.method}")
131
+ print(f" URL: {request.url}")
132
+ print(f" Headers: {len(request.headers)} total")
133
+ print(f" Cookie: auto-injected ({len(cookie_header)} chars)")
134
+
135
+ assert "Cookie" in request.headers
136
+ cookie_count = request.headers["Cookie"].count("=")
137
+ print(f" Cookie entries: {cookie_count}")
138
+
139
+ # Verify the key cookies match what curl would send
140
+ cookie_header = request.headers["Cookie"]
141
+ expected_cookies = [
142
+ "captcha=rscaptcha",
143
+ "accountValidate=1442",
144
+ "ci_session=imedlujf3av9db7luncqk960avsr677s",
145
+ "uf=c88ef33a5dc26e2538ff9dc0803b6d4c",
146
+ "utt=Asia/Karachi",
147
+ "ls=en-US,en",
148
+ ]
149
+ for ec in expected_cookies:
150
+ assert ec in cookie_header, f"Missing cookie: {ec}"
151
+
152
+ print("PASS: All expected cookies in request\n")
153
+
154
+
155
+ def test_cross_domain_cookie_isolation():
156
+ """Verify cookies from spaceshooter.net don't leak to other domains."""
157
+ jar = CookieJar()
158
+ jar.add(Cookie(name="cf_clearance", value="abc123", domain="spaceshooter.net", path="/"))
159
+ jar.add(Cookie(name="session", value="xyz", domain="other.com", path="/"))
160
+
161
+ header_spaceshooter = jar.to_header("https://spaceshooter.net/faucet/ltc")
162
+ header_other = jar.to_header("https://other.com/page")
163
+
164
+ assert "cf_clearance=abc123" in header_spaceshooter
165
+ assert "session=xyz" not in header_spaceshooter
166
+ assert "session=xyz" in header_other
167
+ assert "cf_clearance=abc123" not in header_other
168
+
169
+ print("Cross-domain cookie isolation:")
170
+ print(f" spaceshooter.net: 1 cookie")
171
+ print(f" other.com: 1 cookie")
172
+ print("PASS: No cross-domain cookie leakage\n")
173
+
174
+
175
+ def test_cookie_accumulation_simulation():
176
+ """Simulate what happens when earnow.online redirects and sets more cookies."""
177
+ jar = CookieJar()
178
+
179
+ # Initial request sets these cookies
180
+ jar.parse_set_cookie("captcha=rscaptcha; Path=/", "https://spaceshooter.net/faucet/ltc")
181
+ jar.parse_set_cookie("accountValidate=1442; Path=/", "https://spaceshooter.net/faucet/ltc")
182
+ jar.parse_set_cookie("cf_clearance=abc123; Path=/; Secure", "https://spaceshooter.net/")
183
+
184
+ h1 = jar.to_header("https://spaceshooter.net/faucet/ltc")
185
+ assert "captcha=rscaptcha" in h1
186
+ assert "accountValidate=1442" in h1
187
+ assert "cf_clearance=abc123" in h1
188
+
189
+ # After redirect, server sets more cookies
190
+ jar.parse_set_cookie("ci_session=imedlujf; Path=/", "https://spaceshooter.net/faucet/ltc")
191
+ jar.parse_set_cookie("uf=c88ef33; Path=/", "https://spaceshooter.net/")
192
+
193
+ h2 = jar.to_header("https://spaceshooter.net/faucet/ltc")
194
+ assert "captcha=rscaptcha" in h2
195
+ assert "accountValidate=1442" in h2
196
+ assert "cf_clearance=abc123" in h2
197
+ assert "ci_session=imedlujf" in h2
198
+ assert "uf=c88ef33" in h2
199
+
200
+ print("Cookie accumulation simulation:")
201
+ print(f" After request 1: 3 cookies")
202
+ print(f" After request 2: {len(jar.match('https://spaceshooter.net/faucet/ltc'))} cookies (all preserved)")
203
+ print("PASS: Cookies accumulate correctly across requests\n")
204
+
205
+
206
+ if __name__ == "__main__":
207
+ test_spaceshooter_cookies()
208
+ test_full_request_simulation()
209
+ test_cross_domain_cookie_isolation()
210
+ test_cookie_accumulation_simulation()
211
+ print("=" * 60)
212
+ print("All spaceshooter.net tests PASSED!")
213
+ print("=" * 60)
@@ -0,0 +1,25 @@
1
+ Metadata-Version: 2.4
2
+ Name: bas-http
3
+ Version: 1.0.0
4
+ Summary: Copy-paste your browser's request, bas handles the rest. No impersonation needed.
5
+ Author: bas
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yourusername/bas
8
+ Project-URL: Repository, https://github.com/yourusername/bas
9
+ Project-URL: Issues, https://github.com/yourusername/bas/issues
10
+ Keywords: http,curl,cookie,scraping,browser,devtools
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Internet :: WWW/HTTP
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
@@ -0,0 +1,19 @@
1
+ bas/README.md,sha256=5WU61u8i5F6EMFM0cHSlwGolnmzg6y6NpeZGUzo27jo,6094
2
+ bas/__init__.py,sha256=0PcIOcb4SJlW9MlDX8jJThovTajVIG97S7MMSxBaHe4,2563
3
+ bas/_curl.py,sha256=0OkkL6OTDiUh3PhuAZGUSVsypvp1BAAkDf8cC_aJ7tA,12958
4
+ bas/async_session.py,sha256=_1z5xymDhTvitXs2yWdmtlgCuRitEEZJm862sQPB7HM,11615
5
+ bas/cookies.py,sha256=AYciFx_8lvshS5slrEfxmQBwwKYT2Np5Qesuoe8r5zI,21514
6
+ bas/curl_parser.py,sha256=QvDOoJTby-k70RjBQ_DrXapfBhjvVdlbYpJqS-RCrew,7899
7
+ bas/impersonate.py,sha256=blLV0YJHZfHLPw_op0dF4SRNrtWwOUjZr3vVNJS3aNQ,14327
8
+ bas/models.py,sha256=6VI6vZRPSKmxesQH15eCG_teo9lMlHMA4GOc6LtpR1o,10504
9
+ bas/session.py,sha256=fsYhRKdved3IzAjtmFKiPxfN7nlWvi9-rZj528hw2Fo,22323
10
+ bas/simple_session.py,sha256=iYJN4THZaX3IoBTfis1WpKqZO8A1Q53WXVRVpTnbv9M,9088
11
+ bas/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ bas/tests/test_cookies.py,sha256=FKnvx9tNXVik1wsC4bsmZv87ix1w2YNtoSPfnCDyhls,26035
13
+ bas/tests/test_curl_parser.py,sha256=uisGQjG8dimW9JC2JDbf4IQW6_0RtdSKF39Vgw5CQaY,6545
14
+ bas/tests/test_real_request.py,sha256=SEn_yuTnJRZrLVJlvUL20luu1KxAgo4JG6nDPNEfBTs,6601
15
+ bas/tests/test_spaceshooter.py,sha256=SZcPrmjwbRvxqvB-1urWbBPhtDyLWmsbb7GeoF2unnI,9226
16
+ bas_http-1.0.0.dist-info/METADATA,sha256=GRTCI7DdJ6ic0MNOyDc7oDCFPnFoXM2IuoT3TFBPwP0,1145
17
+ bas_http-1.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
18
+ bas_http-1.0.0.dist-info/top_level.txt,sha256=S9cL0YK79L2dJ5G1qJm0zZafXxIbyJJbez7wd3ha5-0,4
19
+ bas_http-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ bas