Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
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.

response.py 3.3KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. from __future__ import annotations
  2. import http.client as httplib
  3. from email.errors import MultipartInvariantViolationDefect, StartBoundaryNotFoundDefect
  4. from ..exceptions import HeaderParsingError
  5. def is_fp_closed(obj: object) -> bool:
  6. """
  7. Checks whether a given file-like object is closed.
  8. :param obj:
  9. The file-like object to check.
  10. """
  11. try:
  12. # Check `isclosed()` first, in case Python3 doesn't set `closed`.
  13. # GH Issue #928
  14. return obj.isclosed() # type: ignore[no-any-return, attr-defined]
  15. except AttributeError:
  16. pass
  17. try:
  18. # Check via the official file-like-object way.
  19. return obj.closed # type: ignore[no-any-return, attr-defined]
  20. except AttributeError:
  21. pass
  22. try:
  23. # Check if the object is a container for another file-like object that
  24. # gets released on exhaustion (e.g. HTTPResponse).
  25. return obj.fp is None # type: ignore[attr-defined]
  26. except AttributeError:
  27. pass
  28. raise ValueError("Unable to determine whether fp is closed.")
  29. def assert_header_parsing(headers: httplib.HTTPMessage) -> None:
  30. """
  31. Asserts whether all headers have been successfully parsed.
  32. Extracts encountered errors from the result of parsing headers.
  33. Only works on Python 3.
  34. :param http.client.HTTPMessage headers: Headers to verify.
  35. :raises urllib3.exceptions.HeaderParsingError:
  36. If parsing errors are found.
  37. """
  38. # This will fail silently if we pass in the wrong kind of parameter.
  39. # To make debugging easier add an explicit check.
  40. if not isinstance(headers, httplib.HTTPMessage):
  41. raise TypeError(f"expected httplib.Message, got {type(headers)}.")
  42. unparsed_data = None
  43. # get_payload is actually email.message.Message.get_payload;
  44. # we're only interested in the result if it's not a multipart message
  45. if not headers.is_multipart():
  46. payload = headers.get_payload()
  47. if isinstance(payload, (bytes, str)):
  48. unparsed_data = payload
  49. # httplib is assuming a response body is available
  50. # when parsing headers even when httplib only sends
  51. # header data to parse_headers() This results in
  52. # defects on multipart responses in particular.
  53. # See: https://github.com/urllib3/urllib3/issues/800
  54. # So we ignore the following defects:
  55. # - StartBoundaryNotFoundDefect:
  56. # The claimed start boundary was never found.
  57. # - MultipartInvariantViolationDefect:
  58. # A message claimed to be a multipart but no subparts were found.
  59. defects = [
  60. defect
  61. for defect in headers.defects
  62. if not isinstance(
  63. defect, (StartBoundaryNotFoundDefect, MultipartInvariantViolationDefect)
  64. )
  65. ]
  66. if defects or unparsed_data:
  67. raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data)
  68. def is_response_to_head(response: httplib.HTTPResponse) -> bool:
  69. """
  70. Checks whether the request of a response has been a HEAD-request.
  71. :param http.client.HTTPResponse response:
  72. Response to check if the originating request
  73. used 'HEAD' as a method.
  74. """
  75. # FIXME: Can we do this somehow without accessing private httplib _method?
  76. method_str = response._method # type: str # type: ignore[attr-defined]
  77. return method_str.upper() == "HEAD"