Super simple and small Web Push and Notification service
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 

147 行
5.7 KiB

  1. #!/usr/local/bin/python3
  2. import email.mime.multipart
  3. import os
  4. import sys
  5. import traceback
  6. import unittest
  7. from email.message import Message
  8. from urllib.parse import parse_qs
  9. def _deb(*args):
  10. if True:
  11. print(*args, file=sys.stderr)
  12. def getdata(ct, bstr):
  13. _deb('ct:', repr(ct))
  14. _deb('bstr:', repr(bstr))
  15. m = Message()
  16. m['content-type'] = ct
  17. boundary = '--' + m.get_param('boundary')
  18. # trim the end:
  19. _deb('bstr:', repr(bstr))
  20. # pretend we had the previous record
  21. body = b'\r\n' + bstr.split(('\r\n' + boundary + '--\r\n').encode('ASCII'), 1)[0]
  22. _deb('body:', repr(body))
  23. parts = body.split(('\r\n' + boundary + '\r\n').encode('ASCII'))[1:]
  24. msgs = [ x for x in map(email.message_from_bytes, parts) if x.get_param('name', header='content-disposition') == 'sub' ]
  25. return msgs[0].get_payload()
  26. if __name__ == '__main__':
  27. _deb('env:', repr(os.environ))
  28. contentlen = int(os.environ.get('CONTENT_LENGTH', '0'))
  29. body = sys.stdin.buffer.read(contentlen)
  30. try:
  31. sub = getdata(os.environ.get('CONTENT_TYPE'), body)
  32. os.umask(0o66)
  33. with open('/tmp/subinfo.txt', 'w') as fp:
  34. print(sub, file=fp)
  35. print('Content-Type: text/plain\r')
  36. print('\r')
  37. print('OK\r')
  38. except:
  39. _deb(traceback.format_exc())
  40. print('status: 500 Server Error\r')
  41. print('Content-Type: text/plain\r')
  42. print('\r')
  43. print('ERROR\r')
  44. class Test(unittest.TestCase):
  45. _testdata = '''
  46. 0x0040: 504f 5354 202f 7075 7368 2048 5454 ..POST./push.HTT
  47. 0x0050: 502f 312e 310d 0a48 6f73 743a 2031 3932 P/1.1..Host:.192
  48. 0x0060: 2e31 3638 2e30 2e33 0d0a 5573 6572 2d41 .168.0.3..User-A
  49. 0x0070: 6765 6e74 3a20 4d6f 7a69 6c6c 612f 352e gent:.Mozilla/5.
  50. 0x0080: 3020 284d 6163 696e 746f 7368 3b20 496e 0.(Macintosh;.In
  51. 0x0090: 7465 6c20 4d61 6320 4f53 2058 2031 302e tel.Mac.OS.X.10.
  52. 0x00a0: 3135 3b20 7276 3a31 3039 2e30 2920 4765 15;.rv:109.0).Ge
  53. 0x00b0: 636b 6f2f 3230 3130 3031 3031 2046 6972 cko/20100101.Fir
  54. 0x00c0: 6566 6f78 2f31 3135 2e30 0d0a 4163 6365 efox/115.0..Acce
  55. 0x00d0: 7074 3a20 2a2f 2a0d 0a41 6363 6570 742d pt:.*/*..Accept-
  56. 0x00e0: 4c61 6e67 7561 6765 3a20 656e 2d55 532c Language:.en-US,
  57. 0x00f0: 656e 3b71 3d30 2e35 0d0a 4163 6365 7074 en;q=0.5..Accept
  58. 0x0100: 2d45 6e63 6f64 696e 673a 2067 7a69 702c -Encoding:.gzip,
  59. 0x0110: 2064 6566 6c61 7465 2c20 6272 0d0a 5265 .deflate,.br..Re
  60. 0x0120: 6665 7265 723a 2068 7474 7073 3a2f 2f77 ferer:.https://w
  61. 0x0130: 7777 2e66 756e 6b74 6861 742e 636f 6d2f ww.funkthat.com/
  62. 0x0140: 7765 6270 7573 682f 0d0a 436f 6e74 656e webpush/..Conten
  63. 0x0150: 742d 5479 7065 3a20 6d75 6c74 6970 6172 t-Type:.multipar
  64. 0x0160: 742f 666f 726d 2d64 6174 613b 2062 6f75 t/form-data;.bou
  65. 0x0170: 6e64 6172 793d 2d2d 2d2d 2d2d 2d2d 2d2d ndary=----------
  66. 0x0180: 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d ----------------
  67. 0x0190: 2d33 3435 3837 3235 3136 3133 3033 3132 -345872516130312
  68. 0x01a0: 3635 3935 3233 3135 3033 3739 3130 310d 659523150379101.
  69. 0x01b0: 0a4f 7269 6769 6e3a 2068 7474 7073 3a2f .Origin:.https:/
  70. 0x01c0: 2f77 7777 2e66 756e 6b74 6861 742e 636f /www.funkthat.co
  71. 0x01d0: 6d0d 0a44 4e54 3a20 310d 0a53 6563 2d46 m..DNT:.1..Sec-F
  72. 0x01e0: 6574 6368 2d44 6573 743a 2065 6d70 7479 etch-Dest:.empty
  73. 0x01f0: 0d0a 5365 632d 4665 7463 682d 4d6f 6465 ..Sec-Fetch-Mode
  74. 0x0200: 3a20 636f 7273 0d0a 5365 632d 4665 7463 :.cors..Sec-Fetc
  75. 0x0210: 682d 5369 7465 3a20 7361 6d65 2d6f 7269 h-Site:.same-ori
  76. 0x0220: 6769 6e0d 0a53 6563 2d47 5043 3a20 310d gin..Sec-GPC:.1.
  77. 0x0230: 0a58 2d46 6f72 7761 7264 6564 2d46 6f72 .X-Forwarded-For
  78. 0x0240: 3a20 3139 322e 3136 382e 302e 330d 0a58 :.192.168.0.3..X
  79. 0x0250: 2d46 6f72 7761 7264 6564 2d48 6f73 743a -Forwarded-Host:
  80. 0x0260: 2077 7777 2e66 756e 6b74 6861 742e 636f .www.funkthat.co
  81. 0x0270: 6d0d 0a58 2d46 6f72 7761 7264 6564 2d53 m..X-Forwarded-S
  82. 0x0280: 6572 7665 723a 2077 7777 2e66 756e 6b74 erver:.www.funkt
  83. 0x0290: 6861 742e 636f 6d0d 0a43 6f6e 6e65 6374 hat.com..Connect
  84. 0x02a0: 696f 6e3a 204b 6565 702d 416c 6976 650d ion:.Keep-Alive.
  85. 0x02b0: 0a43 6f6e 7465 6e74 2d4c 656e 6774 683a .Content-Length:
  86. 0x02c0: 2035 3833 0d0a 0d0a 2d2d 2d2d 2d2d 2d2d .583....--------
  87. 0x02d0: 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d ----------------
  88. 0x02e0: 2d2d 2d2d 2d33 3435 3837 3235 3136 3133 -----34587251613
  89. 0x02f0: 3033 3132 3635 3935 3233 3135 3033 3739 0312659523150379
  90. 0x0300: 3130 310d 0a43 6f6e 7465 6e74 2d44 6973 101..Content-Dis
  91. 0x0310: 706f 7369 7469 6f6e 3a20 666f 726d 2d64 position:.form-d
  92. 0x0320: 6174 613b 206e 616d 653d 2273 7562 220d ata;.name="sub".
  93. 0x0330: 0a0d 0a7b 2265 6e64 706f 696e 7422 3a22 ...{"endpoint":"
  94. 0x0340: 6874 7470 733a 2f2f 7570 6461 7465 732e https://updates.
  95. 0x0350: 7075 7368 2e73 6572 7669 6365 732e 6d6f push.services.mo
  96. 0x0360: 7a69 6c6c 612e 636f 6d2f 7770 7573 682f zilla.com/wpush/
  97. 0x04c0: 5a4e 565a 6441 535f 4954 3822 7d7d 0d0a ZNVZdAS_IT8"}}..
  98. 0x04d0: 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d ----------------
  99. 0x04e0: 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d33 3435 -------------345
  100. 0x04f0: 3837 3235 3136 3133 3033 3132 3635 3935 8725161303126595
  101. 0x0500: 3233 3135 3033 3739 3130 312d 2d0d 0a 23150379101--..
  102. '''
  103. @staticmethod
  104. def _process_hexdump(data):
  105. lines = (x.split(':', 1)[1].strip().split(' ', 1)[0] for x in data.split('\n') if x.strip())
  106. return bytes.fromhex(''.join(lines))
  107. def test_basic(self):
  108. bstr = self._process_hexdump(self._testdata)
  109. # drop post line
  110. bstr = bstr.split(b'\r\n', 1)[1]
  111. _deb(repr(bstr))
  112. msg = email.message_from_bytes(bstr)
  113. _deb('msg hdrs:', repr(msg.items()))
  114. # get ct
  115. ct = msg['content-type']
  116. _deb('ct:', repr(ct))
  117. # get body:
  118. body = bstr.split(b'\r\n\r\n', 1)[1]
  119. # do the actual test:
  120. res = getdata(ct, body)
  121. self.assertEqual(res, '{"endpoint":"https://updates.push.services.mozilla.com/wpush/ZNVZdAS_IT8"}}')