Read a single JSON value from reader. Returns JSON value as parsed by decoder.decode(), or raises NoMoreMessages if there are no more values to be read.
(self, decoder=None)
| 175 | return line |
| 176 | |
| 177 | def read_json(self, decoder=None): |
| 178 | """Read a single JSON value from reader. |
| 179 | |
| 180 | Returns JSON value as parsed by decoder.decode(), or raises NoMoreMessages |
| 181 | if there are no more values to be read. |
| 182 | """ |
| 183 | |
| 184 | decoder = decoder if decoder is not None else self.json_decoder_factory() |
| 185 | reader = self._reader |
| 186 | read_line = functools.partial(self._read_line, reader) |
| 187 | |
| 188 | # If any error occurs while reading and parsing the message, log the original |
| 189 | # raw message data as is, so that it's possible to diagnose missing or invalid |
| 190 | # headers, encoding issues, JSON syntax errors etc. |
| 191 | def log_message_and_reraise_exception(format_string="", *args, **kwargs): |
| 192 | if format_string: |
| 193 | format_string += "\n\n" |
| 194 | format_string += "{name} -->\n{raw_lines}" |
| 195 | |
| 196 | raw_lines = b"".join(raw_chunks).split(b"\n") |
| 197 | raw_lines = "\n".join(repr(line) for line in raw_lines) |
| 198 | |
| 199 | log.reraise_exception( |
| 200 | format_string, *args, name=self.name, raw_lines=raw_lines, **kwargs |
| 201 | ) |
| 202 | |
| 203 | raw_chunks = [] |
| 204 | headers = {} |
| 205 | |
| 206 | while True: |
| 207 | try: |
| 208 | line = read_line() |
| 209 | except Exception: # pragma: no cover |
| 210 | # Only log it if we have already read some headers, and are looking |
| 211 | # for a blank line terminating them. If this is the very first read, |
| 212 | # there's no message data to log in any case, and the caller might |
| 213 | # be anticipating the error - e.g. NoMoreMessages on disconnect. |
| 214 | if headers: |
| 215 | log_message_and_reraise_exception( |
| 216 | "Error while reading message headers:" |
| 217 | ) |
| 218 | else: |
| 219 | raise |
| 220 | |
| 221 | raw_chunks += [line, b"\n"] |
| 222 | if line == b"": |
| 223 | break |
| 224 | |
| 225 | key, _, value = line.partition(b":") |
| 226 | headers[key] = value |
| 227 | |
| 228 | try: |
| 229 | length = int(headers[b"Content-Length"]) |
| 230 | if not (0 <= length <= self.MAX_BODY_SIZE): |
| 231 | raise ValueError |
| 232 | except (KeyError, ValueError): # pragma: no cover |
| 233 | try: |
| 234 | raise IOError("Content-Length is missing or invalid:") |