paulb@46 | 1 | #!/usr/bin/env python |
paulb@46 | 2 | |
paulb@46 | 3 | """ |
paulb@46 | 4 | Request helper classes. |
paulb@46 | 5 | """ |
paulb@46 | 6 | |
paulb@46 | 7 | class MessageBodyStream: |
paulb@46 | 8 | |
paulb@46 | 9 | """ |
paulb@46 | 10 | A naive stream class, providing a non-blocking stream for transactions when |
paulb@46 | 11 | reading the message body. According to the HTTP standard, the following |
paulb@46 | 12 | things decide how long the message is: |
paulb@46 | 13 | |
paulb@46 | 14 | * Use of the Content-Length header field (see 4.4 Message Length). |
paulb@46 | 15 | * Use of the Transfer-Coding header field (see 3.6 Transfer Codings), |
paulb@46 | 16 | particularly when the "chunked" coding is used. |
paulb@46 | 17 | |
paulb@46 | 18 | NOTE: For now, we don't support the Transfer-Coding business. |
paulb@46 | 19 | """ |
paulb@46 | 20 | |
paulb@46 | 21 | def __init__(self, stream, headers): |
paulb@46 | 22 | |
paulb@46 | 23 | """ |
paulb@46 | 24 | Initialise the object with the given underlying 'stream'. The supplied |
paulb@46 | 25 | 'headers' in a dictionary-style object are used to examine the nature of |
paulb@46 | 26 | the request. |
paulb@46 | 27 | """ |
paulb@46 | 28 | |
paulb@46 | 29 | self.stream = stream |
paulb@46 | 30 | self.headers = headers |
paulb@46 | 31 | self.length = int(headers.get("Content-Length") or 0) |
paulb@46 | 32 | |
paulb@46 | 33 | def read(self, limit=None): |
paulb@46 | 34 | |
paulb@46 | 35 | "Reads all remaining data from the message body." |
paulb@46 | 36 | |
paulb@46 | 37 | if limit is not None: |
paulb@46 | 38 | limit = min(limit, self.length) |
paulb@46 | 39 | else: |
paulb@46 | 40 | limit = self.length |
paulb@46 | 41 | data = self.stream.read(limit) |
paulb@46 | 42 | self.length = self.length - len(data) |
paulb@46 | 43 | return data |
paulb@46 | 44 | |
paulb@46 | 45 | def readline(self): |
paulb@46 | 46 | |
paulb@46 | 47 | "Reads a single line of data from the message body." |
paulb@46 | 48 | |
paulb@46 | 49 | data = [] |
paulb@46 | 50 | while self.length > 0: |
paulb@46 | 51 | data.append(self.read(1)) |
paulb@46 | 52 | if data[-1] == "\n": |
paulb@46 | 53 | break |
paulb@46 | 54 | return "".join(data) |
paulb@46 | 55 | |
paulb@46 | 56 | def readlines(self): |
paulb@46 | 57 | |
paulb@46 | 58 | """ |
paulb@46 | 59 | Reads all remaining data from the message body, splitting it into lines |
paulb@46 | 60 | and returning the data as a list of lines. |
paulb@46 | 61 | """ |
paulb@46 | 62 | |
paulb@46 | 63 | lines = self.read().split("\n") |
paulb@46 | 64 | for i in range(0, len(lines) - 1): |
paulb@46 | 65 | lines[i] = lines[i] + "\n" |
paulb@46 | 66 | return lines |
paulb@46 | 67 | |
paulb@46 | 68 | def close(self): |
paulb@46 | 69 | |
paulb@46 | 70 | "Closes the stream." |
paulb@46 | 71 | |
paulb@46 | 72 | self.stream.close() |
paulb@46 | 73 | |
paulb@46 | 74 | # vim: tabstop=4 expandtab shiftwidth=4 |