如何让HTTP响应报头与正文在同一条消息中返回?
I have no HTTP-related experience and don't understand why this problem occurs. My service is written in Python, here's the response function of my web server:
'''the bytes of sss is 1024''' def start_burn(self): global allburnerdata burnPageNumer = round(len(allburnerdata) / 1024) self.send_response(200) sss = bytearray(); sss.append(0xF1); sss.append(burnPageNumer); self.send_header("Content-type", "application/x-www-form-urlencoded") self.send_header("Content-Length", str(len(sss))) self.end_headers() self.wfile.write(sss) returnWireshark shows the server sends two separate messages. How can I make the HTTP headers and body return in the same message?
Alright, let's break down why you're seeing two separate messages and how to fix it.
The Root Cause
It looks like you're using Python's built-in BaseHTTPRequestHandler (judging by the send_response, send_header, end_headers, and wfile methods). The key issue here is the end_headers() method: by default, it calls self.wfile.flush(), which immediately sends all the header data (status line + headers + trailing blank line) over the network before you write the body. Then when you call self.wfile.write(sss), the body gets sent as a second separate TCP segment.
Fix 1: Override end_headers to skip automatic flushing
You can modify your request handler class to override the end_headers method, removing the automatic flush. Then you can manually flush after writing the body to send everything in one go:
First, add this method to your handler class:
def end_headers(self): # Copy the default behavior but skip the flush if self.request_version != 'HTTP/0.9': self.wfile.write(b"\r\n") # Remove the original self.wfile.flush() call
Then update your start_burn function to flush after writing the body:
def start_burn(self): global allburnerdata burnPageNumer = round(len(allburnerdata) / 1024) # Ensure burnPageNumer is within 0-255 (since bytearray.append expects this range) burnPageNumer = max(0, min(255, burnPageNumer)) sss = bytearray(); sss.append(0xF1); sss.append(burnPageNumer); self.send_response(200) self.send_header("Content-type", "application/x-www-form-urlencoded") self.send_header("Content-Length", str(len(sss))) self.end_headers() self.wfile.write(sss) self.wfile.flush() # Manually flush all data at once return
Fix 2: Manually construct the full HTTP response
If you prefer to avoid overriding methods, you can build the entire HTTP response (headers + body) as a single byte string and write it all at once. This bypasses the default send_response/send_header flow entirely:
def start_burn(self): global allburnerdata burnPageNumer = round(len(allburnerdata) / 1024) burnPageNumer = max(0, min(255, burnPageNumer)) sss = bytearray(); sss.append(0xF1); sss.append(burnPageNumer) # Build the complete HTTP response response_headers = ( f"HTTP/1.1 200 OK\r\n" f"Content-Type: application/x-www-form-urlencoded\r\n" f"Content-Length: {len(sss)}\r\n" f"\r\n" # Blank line separating headers and body ).encode('utf-8') # Combine headers and body, then write and flush full_response = response_headers + sss self.wfile.write(full_response) self.wfile.flush() return
Additional Notes
- I added a check for
burnPageNumerto ensure it's between 0-255 becausebytearray.append()only accepts integers in that range—this prevents a potentialValueErrorif your page count is too large. - Both fixes ensure all response data (headers + body) is buffered first, then sent in a single TCP segment when you call
flush(), which will show up as one message in Wireshark.
内容的提问来源于stack exchange,提问作者BeNice

