httpr 0.3.2__tar.gz → 0.3.3__tar.gz
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.
- {httpr-0.3.2 → httpr-0.3.3}/.github/workflows/mkdocs.yml +6 -3
- {httpr-0.3.2 → httpr-0.3.3}/Cargo.lock +1 -1
- {httpr-0.3.2 → httpr-0.3.3}/Cargo.toml +1 -1
- {httpr-0.3.2 → httpr-0.3.3}/PKG-INFO +1 -1
- {httpr-0.3.2 → httpr-0.3.3}/pyproject.toml +1 -1
- {httpr-0.3.2 → httpr-0.3.3}/src/lib.rs +6 -3
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/test_client.py +42 -0
- {httpr-0.3.2 → httpr-0.3.3}/.github/actions/set-version/action.yml +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/.github/copilot-instructions.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/.github/workflows/CI.yml +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/.github/workflows/CI.yml.backup +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/.github/workflows/benchmark.yml +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/.github/workflows/claude-code-review.yml +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/.github/workflows/claude.yml +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/.github/workflows/copilot-setup-steps.yml +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/.github/workflows/set_version.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/.gitignore +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/.pre-commit-config.yaml +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/CLAUDE.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/LICENSE +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/README.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/Taskfile.yaml +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/benchmark/README.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/benchmark/__init__.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/benchmark/benchmark.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/benchmark/benchmark_cbor.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/benchmark/generate_image.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/benchmark/server.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/benchmark.jpg +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/advanced/cookies.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/advanced/index.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/advanced/proxy.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/advanced/ssl-tls.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/api/async-client.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/api/client.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/api/functions.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/api/index.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/api/response.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/index.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/quickstart.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/tutorial/async.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/tutorial/authentication.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/tutorial/index.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/tutorial/making-requests.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/tutorial/response-handling.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/writings/index.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/docs/writings/posts/2025-02-24-python-http-clients-suck.md +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/httpr/__init__.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/httpr/httpr.pyi +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/httpr/py.typed +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/httpr.code-workspace +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/mkdocs.yml +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/scripts/generate_certs.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/src/exceptions.rs +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/src/response.rs +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/src/traits.rs +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/src/utils.rs +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/benchmark/__init__.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/benchmark/test_performance.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/conftest.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/e2e/__init__.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/e2e/test_async.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/e2e/test_auth.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/e2e/test_redirects.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/e2e/test_ssl.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/e2e/test_streaming.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/e2e/test_uploads.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/__init__.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/cbor_test_server.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/httpx_conns.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/test_asyncclient.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/test_cbor.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/test_defs.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/test_docs.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/test_exceptions.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/test_ssl.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/tests/unit/test_streaming.py +0 -0
- {httpr-0.3.2 → httpr-0.3.3}/uv.lock +0 -0
|
@@ -36,6 +36,9 @@ jobs:
|
|
|
36
36
|
# Capture source commit BEFORE switching branches
|
|
37
37
|
SOURCE_COMMIT=$(git rev-parse --short HEAD)
|
|
38
38
|
|
|
39
|
+
# Save the built site before switching branches
|
|
40
|
+
cp -r site /tmp/site-backup
|
|
41
|
+
|
|
39
42
|
# Fetch gh-pages branch
|
|
40
43
|
git fetch origin gh-pages:gh-pages || true
|
|
41
44
|
|
|
@@ -58,12 +61,12 @@ jobs:
|
|
|
58
61
|
# Remove all tracked files
|
|
59
62
|
git rm -rf . || true
|
|
60
63
|
|
|
61
|
-
# Copy new docs from
|
|
62
|
-
if [ ! -d "site" ] || [ -z "$(ls -A site 2>/dev/null)" ]; then
|
|
64
|
+
# Copy new docs from backup
|
|
65
|
+
if [ ! -d "/tmp/site-backup" ] || [ -z "$(ls -A /tmp/site-backup 2>/dev/null)" ]; then
|
|
63
66
|
echo "Error: site/ directory is empty or missing"
|
|
64
67
|
exit 1
|
|
65
68
|
fi
|
|
66
|
-
cp -r site/* .
|
|
69
|
+
cp -r /tmp/site-backup/* .
|
|
67
70
|
|
|
68
71
|
# Restore benchmark data if it existed
|
|
69
72
|
if [ -f /tmp/bench-backup/data.js ] || [ -f /tmp/bench-backup/index.html ]; then
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name = "httpr"
|
|
3
3
|
# Version is set dynamically by CI from git tags (e.g., v1.2.3 -> 1.2.3).
|
|
4
4
|
# Do not edit manually. See .github/actions/set-version/ for details.
|
|
5
|
-
version = "0.3.
|
|
5
|
+
version = "0.3.3"
|
|
6
6
|
edition = "2021"
|
|
7
7
|
description = "Fast HTTP client for python"
|
|
8
8
|
authors = ["thomasht86"]
|
|
@@ -11,7 +11,7 @@ keywords = [ "python", "request",]
|
|
|
11
11
|
classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Internet :: WWW/HTTP", "Topic :: Software Development :: Libraries :: Python Modules",]
|
|
12
12
|
# Version is set dynamically by CI from git tags (e.g., v1.2.3 -> 1.2.3).
|
|
13
13
|
# Do not edit manually. See .github/actions/set-version/ for details.
|
|
14
|
-
version = "0.3.
|
|
14
|
+
version = "0.3.3"
|
|
15
15
|
dependencies = []
|
|
16
16
|
[[project.authors]]
|
|
17
17
|
name = "thomasht86"
|
|
@@ -145,7 +145,7 @@ impl RClient {
|
|
|
145
145
|
let mut client_builder = reqwest::Client::builder();
|
|
146
146
|
|
|
147
147
|
// Headers || Cookies
|
|
148
|
-
if headers.is_some() || cookies.is_some() {
|
|
148
|
+
let headers_headermap = if headers.is_some() || cookies.is_some() {
|
|
149
149
|
let headers = headers.unwrap_or_else(|| IndexMap::with_hasher(RandomState::default()));
|
|
150
150
|
let mut headers_headermap = headers.to_headermap();
|
|
151
151
|
if let Some(cookies) = cookies {
|
|
@@ -156,7 +156,10 @@ impl RClient {
|
|
|
156
156
|
.map_err(|e| map_anyhow_error(anyhow::Error::new(e)))?,
|
|
157
157
|
);
|
|
158
158
|
}
|
|
159
|
-
client_builder = client_builder.default_headers(headers_headermap);
|
|
159
|
+
client_builder = client_builder.default_headers(headers_headermap.clone());
|
|
160
|
+
headers_headermap
|
|
161
|
+
} else {
|
|
162
|
+
reqwest::header::HeaderMap::new()
|
|
160
163
|
};
|
|
161
164
|
|
|
162
165
|
// Cookie_store
|
|
@@ -231,7 +234,7 @@ impl RClient {
|
|
|
231
234
|
let client = Arc::new(Mutex::new(
|
|
232
235
|
client_builder.build().map_err(map_reqwest_error)?,
|
|
233
236
|
));
|
|
234
|
-
let headers = Arc::new(Mutex::new(
|
|
237
|
+
let headers = Arc::new(Mutex::new(headers_headermap));
|
|
235
238
|
|
|
236
239
|
Ok(RClient {
|
|
237
240
|
client,
|
|
@@ -278,6 +278,48 @@ def test_client_post_files(test_files):
|
|
|
278
278
|
assert json_data["files"] == {"file1": "aaa111", "file2": "bbb222"}
|
|
279
279
|
|
|
280
280
|
|
|
281
|
+
def test_constructor_headers_accessible():
|
|
282
|
+
"""Test that headers passed to constructor are accessible via the headers property."""
|
|
283
|
+
client = httpr.Client(headers={"X-Custom": "value", "User-Agent": "test-agent"})
|
|
284
|
+
assert client.headers == {"x-custom": "value", "user-agent": "test-agent"}
|
|
285
|
+
client.close()
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def test_constructor_headers_with_cookies():
|
|
289
|
+
"""Test that cookies are excluded from headers getter when passed to constructor."""
|
|
290
|
+
client = httpr.Client(
|
|
291
|
+
headers={"X-Custom": "value"},
|
|
292
|
+
cookies={"session": "abc123"},
|
|
293
|
+
)
|
|
294
|
+
# Cookies should not appear in headers getter
|
|
295
|
+
assert client.headers == {"x-custom": "value"}
|
|
296
|
+
# But cookies should be accessible via cookies getter
|
|
297
|
+
assert client.cookies == {"session": "abc123"}
|
|
298
|
+
client.close()
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def test_constructor_cookies_only():
|
|
302
|
+
"""Test that cookies-only constructor doesn't expose Cookie header."""
|
|
303
|
+
client = httpr.Client(cookies={"session": "abc123"})
|
|
304
|
+
# Headers should be empty (no Cookie header exposed)
|
|
305
|
+
assert client.headers == {}
|
|
306
|
+
# Cookies should be accessible
|
|
307
|
+
assert client.cookies == {"session": "abc123"}
|
|
308
|
+
client.close()
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def test_setter_overwrites_constructor_headers():
|
|
312
|
+
"""Test that setting headers overwrites constructor headers."""
|
|
313
|
+
client = httpr.Client(headers={"X-Original": "original"})
|
|
314
|
+
assert client.headers == {"x-original": "original"}
|
|
315
|
+
# Overwrite with new headers
|
|
316
|
+
client.headers = {"X-New": "new"}
|
|
317
|
+
assert client.headers == {"x-new": "new"}
|
|
318
|
+
# Original header should be gone
|
|
319
|
+
assert "x-original" not in client.headers
|
|
320
|
+
client.close()
|
|
321
|
+
|
|
322
|
+
|
|
281
323
|
def test_graceful_invalid_header_handling(base_url_ssl, ca_bundle):
|
|
282
324
|
"""Test that invalid header values are handled gracefully without crashing."""
|
|
283
325
|
client = httpr.Client(ca_cert_file=ca_bundle)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|