Ciała POST w proxy HTTP w Pythonie można buforować w rfile
Czytaj żądanie proxy HTTP w Pythonie przez buforowane wejście handlera, zamiast czekać na bajty, które już opuściły bufor gniazda.
Proxy przekazujące czyta wiersz żądania i nagłówki, przekazuje je, a następnie czeka w select na ciało POST. Klient już je wysłał. Obie strony wyglądają, jakby czekały na siebie.
W BaseHTTPRequestHandler Pythona odczyt nagłówków przechodzi przez rfile, buforowany strumień wejściowy. Ten strumień może czytać w przód i przechowywać bajty należące do ciała. Czekanie na bazowe gniazdo pyta tylko, czy jego deskryptor pliku jest gotowy; nie pyta, czy strumień Pythona zawiera już użyteczne dane.
Podążaj za buforem, który odczytał nagłówki
Czytaj ciało także przez self.rfile. Nie przełączaj się na self.connection.recv po przeanalizowaniu nagłówków buforowanym strumieniem. W przeciwnym razie kod może pominąć bajty już trzymane przez ten strumień i czekać na dane, które nigdy nie zostaną ponownie wysłane.
Przekazanie samego rfile do select nie sprawia, że select bada jego bufor Pythona. API gotowości działa przez deskryptor pliku obiektu.
Dla żądania z jednym prawidłowym Content-Length i bez Transfer-Encoding zużyj dokładnie zadeklarowaną liczbę bajtów, obsługując przedwczesny koniec wejścia oraz własne limity rozmiaru i czasu. Nie czytaj do EOF: klient korzystający z trwałego połączenia może pozostawić połączenie otwarte po zakończeniu żądania.
Uczyń ramkowanie jawną częścią proxy
Ciała żądań w formacie chunked wymagają obsługi ramkowania chunked. Nie można ich czytać, szukając nieobecnego Content-Length. Niejednoznaczne metadane długości wymagają zdefiniowanej ścieżki odrzucenia, a nie wyboru nagłówka, który wydaje się wygodny.
Blokujący handler może nadal używać interfejsu strumienia z ograniczonymi odczytami. Proxy sterowane zdarzeniami potrzebuje modelu bufora, który integruje czytanie w przód parsera z obsługą gotowości. Zmiana limitu czasu nie pogodzi dwóch niezależnych konsumentów tego samego gniazda.
Ta diagnoza dotyczy konkretnie tego, gdzie trzymane są przychodzące bajty. Gdy proxy zużyje właściwe ciało, nadal musi je przekazać ze spójnym ramkowaniem HTTP. Standardowy handler http.server to użyteczne miejsce do zrozumienia mechanizmu, ale nie jest produkcyjną implementacją proxy przekazującego.