Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

81 lines
3.3KB

  1. import six
  2. from . import packet
  3. from six.moves import urllib
  4. class Payload(object):
  5. """Engine.IO payload."""
  6. def __init__(self, packets=None, encoded_payload=None):
  7. self.packets = packets or []
  8. if encoded_payload is not None:
  9. self.decode(encoded_payload)
  10. def encode(self, b64=False, jsonp_index=None):
  11. """Encode the payload for transmission."""
  12. encoded_payload = b''
  13. for pkt in self.packets:
  14. encoded_packet = pkt.encode(b64=b64)
  15. packet_len = len(encoded_packet)
  16. if b64:
  17. encoded_payload += str(packet_len).encode('utf-8') + b':' + \
  18. encoded_packet
  19. else:
  20. binary_len = b''
  21. while packet_len != 0:
  22. binary_len = six.int2byte(packet_len % 10) + binary_len
  23. packet_len = int(packet_len / 10)
  24. if not pkt.binary:
  25. encoded_payload += b'\0'
  26. else:
  27. encoded_payload += b'\1'
  28. encoded_payload += binary_len + b'\xff' + encoded_packet
  29. if jsonp_index is not None:
  30. encoded_payload = b'___eio[' + \
  31. str(jsonp_index).encode() + \
  32. b']("' + \
  33. encoded_payload.replace(b'"', b'\\"') + \
  34. b'");'
  35. return encoded_payload
  36. def decode(self, encoded_payload):
  37. """Decode a transmitted payload."""
  38. self.packets = []
  39. while encoded_payload:
  40. # JSONP POST payload starts with 'd='
  41. if encoded_payload.startswith(b'd='):
  42. encoded_payload = urllib.parse.parse_qs(
  43. encoded_payload)[b'd'][0]
  44. if six.byte2int(encoded_payload[0:1]) <= 1:
  45. packet_len = 0
  46. i = 1
  47. while six.byte2int(encoded_payload[i:i + 1]) != 255:
  48. packet_len = packet_len * 10 + six.byte2int(
  49. encoded_payload[i:i + 1])
  50. i += 1
  51. self.packets.append(packet.Packet(
  52. encoded_packet=encoded_payload[i + 1:i + 1 + packet_len]))
  53. else:
  54. i = encoded_payload.find(b':')
  55. if i == -1:
  56. raise ValueError('invalid payload')
  57. # extracting the packet out of the payload is extremely
  58. # inefficient, because the payload needs to be treated as
  59. # binary, but the non-binary packets have to be parsed as
  60. # unicode. Luckily this complication only applies to long
  61. # polling, as the websocket transport sends packets
  62. # individually wrapped.
  63. packet_len = int(encoded_payload[0:i])
  64. pkt = encoded_payload.decode('utf-8', errors='ignore')[
  65. i + 1: i + 1 + packet_len].encode('utf-8')
  66. self.packets.append(packet.Packet(encoded_packet=pkt))
  67. # the engine.io protocol sends the packet length in
  68. # utf-8 characters, but we need it in bytes to be able to
  69. # jump to the next packet in the payload
  70. packet_len = len(pkt)
  71. encoded_payload = encoded_payload[i + 1 + packet_len:]