|
| 1 | +#!/usr/bin/env python |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | + |
| 4 | +from __future__ import print_function |
| 5 | +import os |
| 6 | +import sys |
| 7 | +import argparse |
| 8 | +import json |
| 9 | + |
| 10 | +try: |
| 11 | + from http.server import BaseHTTPRequestHandler, HTTPServer |
| 12 | + from urllib.parse import parse_qs, urlparse |
| 13 | + from http.cookies import SimpleCookie |
| 14 | + py3 = True |
| 15 | +except ImportError: |
| 16 | + from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer |
| 17 | + from urlparse import parse_qs, urlparse |
| 18 | + from Cookie import SimpleCookie |
| 19 | + py3 = False |
| 20 | + |
| 21 | +__program_name__ = "PyHTTPBin" |
| 22 | +__version__ = "1.0.0" |
| 23 | +__project_url__ = "https://github.com/GameMaker2k/PyWWW-Get" |
| 24 | + |
| 25 | +parser = argparse.ArgumentParser(description="httpbin-like local server") |
| 26 | +parser.add_argument("-p", "--port", type=int, default=8080, help="Port to bind to") |
| 27 | +parser.add_argument("-e", "--enablessl", action="store_true", help="Enable SSL") |
| 28 | +parser.add_argument("-k", "--sslkeypem", default=None, help="Path to SSL key PEM file") |
| 29 | +parser.add_argument("-c", "--sslcertpem", default=None, help="Path to SSL cert PEM file") |
| 30 | +parser.add_argument("-V", "--version", action="version", version=__program_name__ + " " + __version__) |
| 31 | +args = parser.parse_args() |
| 32 | + |
| 33 | +if args.port < 1 or args.port > 65535: |
| 34 | + print("Invalid port. Falling back to 8080.") |
| 35 | + args.port = 8080 |
| 36 | + |
| 37 | +if args.enablessl: |
| 38 | + if not (args.sslkeypem and os.path.isfile(args.sslkeypem)) or \ |
| 39 | + not (args.sslcertpem and os.path.isfile(args.sslcertpem)): |
| 40 | + print("Invalid SSL files provided. Disabling SSL.") |
| 41 | + args.enablessl = False |
| 42 | + |
| 43 | +class RequestHandler(BaseHTTPRequestHandler): |
| 44 | + def _json_response(self, data, status=200): |
| 45 | + payload = json.dumps(data, indent=2) |
| 46 | + self.send_response(status) |
| 47 | + self.send_header("Content-Type", "application/json") |
| 48 | + self.send_header("Content-Length", str(len(payload.encode('utf-8')))) |
| 49 | + self.end_headers() |
| 50 | + self.wfile.write(payload.encode('utf-8') if py3 else payload) |
| 51 | + |
| 52 | + def _parse_request(self): |
| 53 | + parsed_url = urlparse(self.path) |
| 54 | + return { |
| 55 | + "method": self.command, |
| 56 | + "path": parsed_url.path, |
| 57 | + "query": parse_qs(parsed_url.query), |
| 58 | + "headers": dict(self.headers), |
| 59 | + "cookies": {k: v.value for k, v in SimpleCookie(self.headers.get('Cookie', '')).items()}, |
| 60 | + "origin": self.client_address[0] |
| 61 | + } |
| 62 | + |
| 63 | + def do_GET(self): |
| 64 | + info = self._parse_request() |
| 65 | + if info['path'] == "/get": |
| 66 | + self._json_response(info) |
| 67 | + elif info['path'] == "/headers": |
| 68 | + self._json_response({"headers": info['headers']}) |
| 69 | + elif info['path'] == "/ip": |
| 70 | + self._json_response({"origin": info['origin']}) |
| 71 | + elif info['path'] == "/user-agent": |
| 72 | + self._json_response({"user-agent": info['headers'].get("User-Agent", "")}) |
| 73 | + elif info['path'] == "/cookies": |
| 74 | + self._json_response({"cookies": info['cookies']}) |
| 75 | + elif info['path'] == "/anything": |
| 76 | + self._json_response(info) |
| 77 | + else: |
| 78 | + self._json_response({"message": "Not Found"}, 404) |
| 79 | + |
| 80 | + def do_POST(self): |
| 81 | + info = self._parse_request() |
| 82 | + content_length = int(self.headers.get("Content-Length", 0)) |
| 83 | + body = self.rfile.read(content_length) |
| 84 | + if py3: |
| 85 | + body = body.decode('utf-8') |
| 86 | + form = parse_qs(body) |
| 87 | + info["form"] = form |
| 88 | + info["data"] = body |
| 89 | + self._json_response(info) |
| 90 | + |
| 91 | + def log_message(self, format, *args): |
| 92 | + sys.stdout.write("%s - - [%s] %s\n" % |
| 93 | + (self.client_address[0], |
| 94 | + self.log_date_time_string(), |
| 95 | + format % args)) |
| 96 | + |
| 97 | +if __name__ == "__main__": |
| 98 | + server = HTTPServer(('', args.port), RequestHandler) |
| 99 | + if args.enablessl: |
| 100 | + import ssl |
| 101 | + server.socket = ssl.wrap_socket(server.socket, |
| 102 | + keyfile=args.sslkeypem, |
| 103 | + certfile=args.sslcertpem, |
| 104 | + server_side=True) |
| 105 | + print("Serving HTTPS on port %d" % args.port) |
| 106 | + else: |
| 107 | + print("Serving HTTP on port %d" % args.port) |
| 108 | + try: |
| 109 | + server.serve_forever() |
| 110 | + except KeyboardInterrupt: |
| 111 | + print("\nShutting down.") |
| 112 | + server.server_close() |
0 commit comments