local_target.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. """Shared local HTTP target server for attack tests."""
  2. import http.server
  3. import socketserver
  4. import threading
  5. import time
  6. import socket
  7. from contextlib import contextmanager
  8. class CountingHandler(http.server.BaseHTTPRequestHandler):
  9. counter = {"get": 0, "post": 0, "head": 0, "headers": []}
  10. def log_message(self, format, *args):
  11. pass
  12. def _record(self, method):
  13. type(self).counter[method] += 1
  14. type(self).counter["headers"].append(dict(self.headers))
  15. def do_GET(self):
  16. self._record("get")
  17. body = b"ok"
  18. self.send_response(200)
  19. self.send_header("Content-Type", "text/plain")
  20. self.send_header("Content-Length", str(len(body)))
  21. self.end_headers()
  22. self.wfile.write(body)
  23. def do_POST(self):
  24. self._record("post")
  25. self.send_response(200)
  26. self.send_header("Content-Type", "text/plain")
  27. self.end_headers()
  28. self.wfile.write(b"ok")
  29. def do_HEAD(self):
  30. self._record("head")
  31. self.send_response(200)
  32. self.send_header("Content-Type", "text/plain")
  33. self.send_header("Content-Length", "2")
  34. self.end_headers()
  35. class _ReusableServer(socketserver.ThreadingTCPServer):
  36. allow_reuse_address = True
  37. daemon_threads = True
  38. @contextmanager
  39. def http_target():
  40. CountingHandler.counter = {"get": 0, "post": 0, "head": 0, "headers": []}
  41. srv = _ReusableServer(("127.0.0.1", 0), CountingHandler)
  42. port = srv.server_address[1]
  43. t = threading.Thread(target=srv.serve_forever, daemon=True)
  44. t.start()
  45. deadline = time.time() + 5
  46. while time.time() < deadline:
  47. try:
  48. _s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  49. _s.settimeout(0.3)
  50. _s.connect(("127.0.0.1", port))
  51. _s.close()
  52. break
  53. except Exception:
  54. time.sleep(0.05)
  55. try:
  56. yield port, CountingHandler.counter
  57. finally:
  58. time.sleep(0.2)
  59. srv.shutdown()
  60. srv.server_close()