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:
POST /upload HTTP/1.1
Transfer-Encoding: chunkedBu, 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:
def gen():
with open("firmware.bin", "rb") as f:
while chunk := f.read(4096):
yield chunk
requests.post(url, data=gen()) # → Transfer-Encoding: chunkedContent-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:
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/strolan her şey hesaplanmış birContent-Lengthalır.requests_toolbelt.StreamingIterator/len‘liMultipartEncoder— multipart yüklemeler için.- Tam kontrol için ham
http.client/http.client.HTTPSConnection.putrequest(..., encode_chunked=False).
Doğrula
# tcpdump veya bir netcat dinleyicisi gerçek wire formatını gösterir:
nc -l 8080 > request.raw &
python3 your_upload.py
head -10 request.rawContent-Length: 1462400 görmeli ve Transfer-Encoding header’ı olmamalı.
İlgili
- How to Perform ESP32 Firmware OTA Updates via HTTP POST — tam olarak bunu gerektiren somut bir gömülü endpoint.