Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

body.py 7.2KB

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