fix: 414 URI Too Long — omit False-valued features from GET URL, add regression tests

This commit is contained in:
jackwener
2026-03-09 20:50:45 +08:00
parent 12f425abea
commit d20c5699fd
4 changed files with 27 additions and 4 deletions

View File

@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "twitter-cli"
version = "0.4.1"
version = "0.4.2"
description = "A CLI for Twitter/X — feed, bookmarks, and user timeline in terminal"
readme = "README.md"
license = "Apache-2.0"

View File

@@ -176,6 +176,23 @@ class TestBuildGraphqlUrl:
url = _build_graphql_url("x", "Op", {}, {}, {"toggle": True})
assert "fieldToggles=" in url
def test_false_features_omitted_from_url(self):
"""False-valued features should be omitted to keep URL short (avoid 414)."""
features = {"enabled_flag": True, "disabled_flag": False, "another_enabled": True}
url = _build_graphql_url("q", "Op", {}, features)
assert "enabled_flag" in url
assert "another_enabled" in url
assert "disabled_flag" not in url
def test_url_length_with_full_features(self):
"""URL with full FEATURES dict should stay under 8000 chars (server limit)."""
url = _build_graphql_url(
"abc123", "SearchTimeline",
{"rawQuery": "AI agent", "querySource": "typed_query", "product": "Latest", "count": 50},
FEATURES,
)
assert len(url) < 8000, f"URL too long: {len(url)} chars"
# ── _best_chrome_target ──────────────────────────────────────────────────

View File

@@ -164,12 +164,18 @@ def _url_fetch(url, headers=None):
def _build_graphql_url(query_id, operation_name, variables, features, field_toggles=None):
# type: (str, str, Dict[str, Any], Dict[str, Any], Optional[Dict[str, Any]]) -> str
"""Build GraphQL GET URL with encoded variables/features/fieldToggles."""
"""Build GraphQL GET URL with encoded variables/features/fieldToggles.
Only includes True-valued feature flags in the URL to avoid 414 URI Too Long.
Twitter's API defaults missing features to False.
"""
# Compact features: omit False values to keep URL under server limits
compact_features = {k: v for k, v in features.items() if v is not False}
url = "https://x.com/i/api/graphql/%s/%s?variables=%s&features=%s" % (
query_id,
operation_name,
urllib.parse.quote(json.dumps(variables, separators=(",", ":"))),
urllib.parse.quote(json.dumps(features, separators=(",", ":"))),
urllib.parse.quote(json.dumps(compact_features, separators=(",", ":"))),
)
if field_toggles:
url += "&fieldToggles=%s" % urllib.parse.quote(

2
uv.lock generated
View File

@@ -950,7 +950,7 @@ wheels = [
[[package]]
name = "twitter-cli"
version = "0.4.0"
version = "0.4.1"
source = { editable = "." }
dependencies = [
{ name = "beautifulsoup4" },