Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Retry-After is never read on 429 retries: dict(httpx.Headers) lowercases the key

Đang mở Phù hợp với người mới
#17 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
78/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
python
Lĩnh vực
api, backend

Hướng nghiên cứu

Bắt đầu với shopify_app/graphql/admin_graphql.py tại các dòng 111 và 708, sau đó kiểm tra các handler 429 sync và async tại các dòng 389 và 445. Tái hiện hành vi của khóa header bằng snippet httpx được cung cấp và xác nhận rằng cả hai đường dẫn retry đều sử dụng giá trị Retry-After do máy chủ cung cấp thay vì giá trị mặc định.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

devtools-gardener

Summary

In admin_graphql_request, the Retry-After header is never read on a 429 response. The lookup always falls through to its "1" default, so every rate-limit retry sleeps exactly one second regardless of what the server asked for.

Affects both the sync and async paths.

Version: shopifyapp 1.0.1 (sdist from PyPI), httpx 0.28.1.

Cause

shopify_app/graphql/admin_graphql.py:111 (and :708 on the async path) normalizes the response headers with:

response_headers = dict(response.headers)

dict() on an httpx.Headers instance produces lowercased keys. The 429 handlers then look the header up with its canonical casing, at shopify_app/graphql/admin_graphql.py:389 (sync) and :445 (async):

retry_after = response_headers.get("Retry-After", "1")

That key is never present, so retry_after is always the literal string "1".

Reproduction

import httpx

h = httpx.Headers({"Retry-After": "2.0", "Content-Type": "application/json"})
d = dict(h)

print(list(d))                     # ['retry-after', 'content-type']
print(d.get("Retry-After", "1"))   # '1'   <- expected '2.0'

Impact

The client ignores server-provided backoff on rate limiting and retries on a fixed one-second interval instead. With the default max_retries=2 that is about two seconds of total backoff, typically well short of what a rate-limited endpoint asks for.

Suggested fix

httpx.Headers is already case-insensitive, so reading from the response object directly avoids the problem:

retry_after = response.headers.get("Retry-After", "1")

Keeping the dict and looking up the lowercase key works too.

One caveat: fixing this lookup on its own exposes a second defect on the same value, where int(retry_after) raises ValueError on anything that is not a bare integer. Filed separately as #18, which also notes that the two are best addressed together.

Ngôn ngữ chính
Python
Star
17
Fork
1
Merge trung bình
4 phút
Pull request đã merge (30 ngày)
1

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của Shopify/shopify-app-python

Tất cả issue của Shopify/shopify-app-python

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.