|
| 1 | + |
| 2 | +import http.server |
| 3 | +import socketserver |
| 4 | +import threading |
| 5 | +import time |
| 6 | +import os |
| 7 | + |
| 8 | +PORT = 8080 |
| 9 | +f=open("host.txt","r") #example for host.txt: myhost.hopto.org |
| 10 | +PUBLIC_IP = f.read() |
| 11 | +f.close() |
| 12 | +f2=open("path.txt","r") #example for path.txt: C:/public/myfiles/ |
| 13 | +LOCAL_FILES_PATH = f2.read() |
| 14 | +f2.close() |
| 15 | +REQUESTS_PER_SECOND = 1 |
| 16 | +TIMEOUT_SECONDS = 5 |
| 17 | + |
| 18 | +class ThrottledRequestHandler(http.server.SimpleHTTPRequestHandler): |
| 19 | + request_count = 0 |
| 20 | + last_request_time = None |
| 21 | + clients = set() |
| 22 | + file_stats = {} |
| 23 | + |
| 24 | + def do_GET(self): |
| 25 | + # Check if request limit exceeded |
| 26 | + self.request_count += 1 |
| 27 | + current_time = time.time() |
| 28 | + if self.last_request_time is not None and current_time - self.last_request_time < 1 / REQUESTS_PER_SECOND: |
| 29 | + self.send_error(429, "Too many requests") |
| 30 | + print("✘ Timeout by", self.client_address[0]) |
| 31 | + return |
| 32 | + self.last_request_time = current_time |
| 33 | + |
| 34 | + # Remove port from URL |
| 35 | + url_parts = self.path.split(':') |
| 36 | + if len(url_parts) > 2: |
| 37 | + self.send_error(400, "Invalid URL") |
| 38 | + return |
| 39 | + if len(url_parts) == 2: |
| 40 | + if url_parts[1].startswith('/'): |
| 41 | + self.path = url_parts[1] |
| 42 | + else: |
| 43 | + self.send_error(400, "Invalid URL") |
| 44 | + return |
| 45 | + |
| 46 | + # Serve file |
| 47 | + file_path = LOCAL_FILES_PATH + self.path[1:] |
| 48 | + if not os.path.exists(file_path): |
| 49 | + self.send_error(404, "File not found") |
| 50 | + print("✘ Not existing file by", self.client_address[0]) |
| 51 | + return |
| 52 | + self.send_response(200) |
| 53 | + self.send_header("Content-type", "application/octet-stream") |
| 54 | + self.end_headers() |
| 55 | + with open(file_path, "rb") as f: |
| 56 | + self.wfile.write(f.read()) |
| 57 | + print("✓", self.client_address[0]) |
| 58 | + |
| 59 | + # Log unique client IPs and file stats |
| 60 | + self.clients.add(self.client_address[0]) |
| 61 | + if self.path[1:] in self.file_stats: |
| 62 | + self.file_stats[self.path[1:]] += 1 |
| 63 | + else: |
| 64 | + self.file_stats[self.path[1:]] = 1 |
| 65 | + |
| 66 | + # Write client IPs and file stats to files |
| 67 | + with open("clients.txt", "w") as f: |
| 68 | + f.write("\n".join(self.clients)) |
| 69 | + with open("stats.txt", "w") as f: |
| 70 | + for file, count in self.file_stats.items(): |
| 71 | + f.write(f"{file}:{count}\n") |
| 72 | + |
| 73 | +with socketserver.ThreadingTCPServer(("", PORT), ThrottledRequestHandler) as httpd: |
| 74 | + print(f"Serving files from {LOCAL_FILES_PATH} at {PUBLIC_IP}:{PORT}") |
| 75 | + try: |
| 76 | + httpd.serve_forever() |
| 77 | + except KeyboardInterrupt: |
| 78 | + pass |
| 79 | + httpd.server_close() |
0 commit comments