body.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. # -*- coding: utf-8 -
  2. #
  3. # This file is part of gunicorn released under the MIT license.
  4. # See the NOTICE for more information.
  5. import io
  6. import sys
  7. from gunicorn.http.errors import (NoMoreData, ChunkMissingTerminator,
  8. InvalidChunkSize)
  9. class ChunkedReader(object):
  10. def __init__(self, req, unreader):
  11. self.req = req
  12. self.parser = self.parse_chunked(unreader)
  13. self.buf = io.BytesIO()
  14. def read(self, size):
  15. if not isinstance(size, int):
  16. raise TypeError("size must be an integral type")
  17. if size < 0:
  18. raise ValueError("Size must be positive.")
  19. if size == 0:
  20. return b""
  21. if self.parser:
  22. while self.buf.tell() < size:
  23. try:
  24. self.buf.write(next(self.parser))
  25. except StopIteration:
  26. self.parser = None
  27. break
  28. data = self.buf.getvalue()
  29. ret, rest = data[:size], data[size:]
  30. self.buf = io.BytesIO()
  31. self.buf.write(rest)
  32. return ret
  33. def parse_trailers(self, unreader, data):
  34. buf = io.BytesIO()
  35. buf.write(data)
  36. idx = buf.getvalue().find(b"\r\n\r\n")
  37. done = buf.getvalue()[:2] == b"\r\n"
  38. while idx < 0 and not done:
  39. self.get_data(unreader, buf)
  40. idx = buf.getvalue().find(b"\r\n\r\n")
  41. done = buf.getvalue()[:2] == b"\r\n"
  42. if done:
  43. unreader.unread(buf.getvalue()[2:])
  44. return b""
  45. self.req.trailers = self.req.parse_headers(buf.getvalue()[:idx])
  46. unreader.unread(buf.getvalue()[idx + 4:])
  47. def parse_chunked(self, unreader):
  48. (size, rest) = self.parse_chunk_size(unreader)
  49. while size > 0:
  50. while size > len(rest):
  51. size -= len(rest)
  52. yield rest
  53. rest = unreader.read()
  54. if not rest:
  55. raise NoMoreData()
  56. yield rest[:size]
  57. # Remove \r\n after chunk
  58. rest = rest[size:]
  59. while len(rest) < 2:
  60. rest += unreader.read()
  61. if rest[:2] != b'\r\n':
  62. raise ChunkMissingTerminator(rest[:2])
  63. (size, rest) = self.parse_chunk_size(unreader, data=rest[2:])
  64. def parse_chunk_size(self, unreader, data=None):
  65. buf = io.BytesIO()
  66. if data is not None:
  67. buf.write(data)
  68. idx = buf.getvalue().find(b"\r\n")
  69. while idx < 0:
  70. self.get_data(unreader, buf)
  71. idx = buf.getvalue().find(b"\r\n")
  72. data = buf.getvalue()
  73. line, rest_chunk = data[:idx], data[idx + 2:]
  74. chunk_size = line.split(b";", 1)[0].strip()
  75. try:
  76. chunk_size = int(chunk_size, 16)
  77. except ValueError:
  78. raise InvalidChunkSize(chunk_size)
  79. if chunk_size == 0:
  80. try:
  81. self.parse_trailers(unreader, rest_chunk)
  82. except NoMoreData:
  83. pass
  84. return (0, None)
  85. return (chunk_size, rest_chunk)
  86. def get_data(self, unreader, buf):
  87. data = unreader.read()
  88. if not data:
  89. raise NoMoreData()
  90. buf.write(data)
  91. class LengthReader(object):
  92. def __init__(self, unreader, length):
  93. self.unreader = unreader
  94. self.length = length
  95. def read(self, size):
  96. if not isinstance(size, int):
  97. raise TypeError("size must be an integral type")
  98. size = min(self.length, size)
  99. if size < 0:
  100. raise ValueError("Size must be positive.")
  101. if size == 0:
  102. return b""
  103. buf = io.BytesIO()
  104. data = self.unreader.read()
  105. while data:
  106. buf.write(data)
  107. if buf.tell() >= size:
  108. break
  109. data = self.unreader.read()
  110. buf = buf.getvalue()
  111. ret, rest = buf[:size], buf[size:]
  112. self.unreader.unread(rest)
  113. self.length -= size
  114. return ret
  115. class EOFReader(object):
  116. def __init__(self, unreader):
  117. self.unreader = unreader
  118. self.buf = io.BytesIO()
  119. self.finished = False
  120. def read(self, size):
  121. if not isinstance(size, int):
  122. raise TypeError("size must be an integral type")
  123. if size < 0:
  124. raise ValueError("Size must be positive.")
  125. if size == 0:
  126. return b""
  127. if self.finished:
  128. data = self.buf.getvalue()
  129. ret, rest = data[:size], data[size:]
  130. self.buf = io.BytesIO()
  131. self.buf.write(rest)
  132. return ret
  133. data = self.unreader.read()
  134. while data:
  135. self.buf.write(data)
  136. if self.buf.tell() > size:
  137. break
  138. data = self.unreader.read()
  139. if not data:
  140. self.finished = True
  141. data = self.buf.getvalue()
  142. ret, rest = data[:size], data[size:]
  143. self.buf = io.BytesIO()
  144. self.buf.write(rest)
  145. return ret
  146. class Body(object):
  147. def __init__(self, reader):
  148. self.reader = reader
  149. self.buf = io.BytesIO()
  150. def __iter__(self):
  151. return self
  152. def __next__(self):
  153. ret = self.readline()
  154. if not ret:
  155. raise StopIteration()
  156. return ret
  157. next = __next__
  158. def getsize(self, size):
  159. if size is None:
  160. return sys.maxsize
  161. elif not isinstance(size, int):
  162. raise TypeError("size must be an integral type")
  163. elif size < 0:
  164. return sys.maxsize
  165. return size
  166. def read(self, size=None):
  167. size = self.getsize(size)
  168. if size == 0:
  169. return b""
  170. if size < self.buf.tell():
  171. data = self.buf.getvalue()
  172. ret, rest = data[:size], data[size:]
  173. self.buf = io.BytesIO()
  174. self.buf.write(rest)
  175. return ret
  176. while size > self.buf.tell():
  177. data = self.reader.read(1024)
  178. if not data:
  179. break
  180. self.buf.write(data)
  181. data = self.buf.getvalue()
  182. ret, rest = data[:size], data[size:]
  183. self.buf = io.BytesIO()
  184. self.buf.write(rest)
  185. return ret
  186. def readline(self, size=None):
  187. size = self.getsize(size)
  188. if size == 0:
  189. return b""
  190. data = self.buf.getvalue()
  191. self.buf = io.BytesIO()
  192. ret = []
  193. while 1:
  194. idx = data.find(b"\n", 0, size)
  195. idx = idx + 1 if idx >= 0 else size if len(data) >= size else 0
  196. if idx:
  197. ret.append(data[:idx])
  198. self.buf.write(data[idx:])
  199. break
  200. ret.append(data)
  201. size -= len(data)
  202. data = self.reader.read(min(1024, size))
  203. if not data:
  204. break
  205. return b"".join(ret)
  206. def readlines(self, size=None):
  207. ret = []
  208. data = self.read()
  209. while data:
  210. pos = data.find(b"\n")
  211. if pos < 0:
  212. ret.append(data)
  213. data = b""
  214. else:
  215. line, data = data[:pos + 1], data[pos + 1:]
  216. ret.append(line)
  217. return ret