Python requests'e Chunked Transfer Encoding Yerine Content-Length Göndertme

Sorun

requests ile bir sunucuya dosya POST ediyorsun ve sunucu 400 Bad request syntax ile reddediyor — veya hiç gelmeyen bir Content-Length bekleyerek takılıyor. İsteği inceleyince şunu görüyorsun:

request-headers.txt
POST /upload HTTP/1.1
Transfer-Encoding: chunked

Bu, yalnızca sabit uzunluklu body’leri anlayan minimal/gömülü HTTP sunucularını (ESP-IDF httpd, bazı IoT cihazları, basit parser’lar) tipik olarak bozar.

Neden

requests, body’nin bilinen bir uzunluğu olmadığında chunked transfer encoding kullanır. Bir generator, iterator veya len()‘i olmayan herhangi bir data= nesnesi geçirmek bunu tetikler:

chunked.py
def gen():
    with open("firmware.bin", "rb") as f:
        while chunk := f.read(4096):
            yield chunk

requests.post(url, data=gen())  # → Transfer-Encoding: chunked

Content-Length‘i manuel ayarlamak bile tüm requests sürümlerinde yardımcı olmaz — bir generator body’sinin varlığı yine de chunked modu zorlayabilir veya uyumsuzluk üretebilir.

Çözüm

Bilinen uzunluklu bir nesne geçir — en basiti dosya nesnesinin kendisidir:

fixed.py
import os
import requests

size = os.path.getsize("firmware.bin")
with open("firmware.bin", "rb") as f:
    r = requests.post(
        url,
        data=f,                       # dosya nesnesi → bilinen uzunluk
        headers={
            "Content-Type": "application/octet-stream",
            "Content-Length": str(size),
        },
        timeout=120,
    )
print(r.status_code, r.text)

requests, f‘in dosya-benzeri nesne olduğunu algılar, doğrudan okur ve düzgün bir Content-Length header’ı gönderir. Küçük payload’lar için data=open(...).read() (bytes) de çalışır.

Body’yi sarmak zorundaysan alternatifler:

  • data=payload_bytes — bytes/str olan her şey hesaplanmış bir Content-Length alır.
  • requests_toolbelt.StreamingIterator / len‘li MultipartEncoder — multipart yüklemeler için.
  • Tam kontrol için ham http.client / http.client.HTTPSConnection.putrequest(..., encode_chunked=False).

Doğrula

check.sh
# tcpdump veya bir netcat dinleyicisi gerçek wire formatını gösterir:
nc -l 8080 > request.raw &
python3 your_upload.py
head -10 request.raw

Content-Length: 1462400 görmeli ve Transfer-Encoding header’ı olmamalı.

İlgili


Check out similar posts by category: Python Ağ