diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2022-12-31 13:28:49 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rspamd.com> | 2022-12-31 13:28:49 +0000 |
commit | 8a5509271689250f6a57587d01a2b288163fd16f (patch) | |
tree | 4b5823175c3eed2b74a4a2607f24241681c81df1 /test/functional | |
parent | 3afb49bfe7cb3628ad1bf885e7b47ee9cd31087a (diff) | |
download | rspamd-8a5509271689250f6a57587d01a2b288163fd16f.tar.gz rspamd-8a5509271689250f6a57587d01a2b288163fd16f.zip |
[Test] Rewrite dummy http server
Diffstat (limited to 'test/functional')
-rwxr-xr-x | test/functional/util/dummy_http.py | 268 | ||||
-rwxr-xr-x | test/functional/util/dummy_https.py | 141 |
2 files changed, 123 insertions, 286 deletions
diff --git a/test/functional/util/dummy_http.py b/test/functional/util/dummy_http.py index 1fb721413..8e2cc2656 100755 --- a/test/functional/util/dummy_http.py +++ b/test/functional/util/dummy_http.py @@ -1,154 +1,132 @@ #!/usr/bin/env python3 -import http.server +import tornado.ioloop +import tornado.web +import tornado.httpserver +import ssl +import argparse import os -import socket -import socketserver -import sys -import time -from urllib.parse import urlparse, parse_qs -import dummy_killer - -PORT = 18080 -HOST_NAME = '0.0.0.0' - -PID = "/tmp/dummy_http.pid" - - -class MyHandler(http.server.BaseHTTPRequestHandler): - protocol_version = 'HTTP/1.1' - - def do_HEAD(self): - if self.path == "/redirect1": - self.send_response(301) - self.send_header("Location", "http://127.0.0.1:"+str(PORT)+"/hello") - elif self.path == "/redirect2": - self.send_response(301) - self.send_header("Location", "http://127.0.0.1:"+str(PORT)+"/redirect1") - elif self.path == "/redirect3": - self.send_response(301) - self.send_header("Location", "http://127.0.0.1:"+str(PORT)+"/redirect4") - elif self.path == "/redirect4": - self.send_response(301) - self.send_header("Location", "http://127.0.0.1:"+str(PORT)+"/redirect3") +class MainHandler(tornado.web.RequestHandler): + @tornado.gen.coroutine + def get(self, path): + if path == '/empty': + # Return an empty reply + self.set_header("Content-Type", "text/plain") + self.write("") + elif path == '/error_403': + # Return a 403 HTTP error + raise tornado.web.HTTPError(403) + elif path == '/timeout': + # Wait for 4 seconds before returning an empty reply + yield tornado.gen.sleep(4) + self.set_header("Content-Type", "text/plain") + self.write("") + elif path == '/map-simple': + # Return a string 'hello map' + self.set_header("Content-Type", "text/plain") + self.write("hello map") + elif path == '/map-query': + # Parse the 'key' argument from the HTTP request + key = self.get_query_argument("key", default=None) + if key == 'au': + # Return a string 'hit' if 'key' is equal to 'au' + self.set_header("Content-Type", "text/plain") + self.write("hit") + else: + # Return a 404 HTTP error if 'key' is not equal to 'au' + raise tornado.web.HTTPError(404) + elif path == '/settings': + self.set_header("Content-Type", "application/json") + self.write("{\"actions\": { \"reject\": 1.0}, \"symbols\": { \"EXTERNAL_SETTINGS\": 1.0 }}") else: - self.send_response(200) - self.send_header("Content-type", "text/html") - self.end_headers() - self.log_message("to be closed: " + repr(self.close_connection)) - - def do_GET(self): - """Respond to a GET request.""" - response = b"hello world" - url = urlparse(self.path) - self.path = url.path - - if self.path == "/empty": - self.finish() - return - - if self.path == "/timeout": - time.sleep(2) - elif self.path == "/error_403": - self.send_response(403) - elif self.path == "/map-query": - query = parse_qs(url.query) - self.log_message('query=%s', query) - if query['key'][0] == 'au': - response = b"1.0" - self.send_response(200) + raise tornado.web.HTTPError(404) + + @tornado.gen.coroutine + def post(self, path): + if path == '/empty': + # Return an empty reply + self.set_header("Content-Type", "text/plain") + self.write("") + elif path == '/error_403': + # Return a 403 HTTP error + raise tornado.web.HTTPError(403) + elif path == '/timeout': + # Wait for 4 seconds before returning an empty reply + yield tornado.gen.sleep(4) + self.set_header("Content-Type", "text/plain") + self.write("") + elif path == '/map-simple': + # Return a string 'hello map' + self.set_header("Content-Type", "text/plain") + self.write("hello map") + elif path == '/map-query': + # Parse the 'key' argument from the HTTP request + key = self.get_query_argument("key", default="") + if key == 'au': + # Return a string 'hit' if 'key' is equal to 'au' + self.set_header("Content-Type", "text/plain") + self.write("hit") else: - response = b"" - self.send_response(404) + # Return a 404 HTTP error if 'key' is not equal to 'au' + raise tornado.web.HTTPError(404) + elif path == '/settings': + self.set_header("Content-Type", "application/json") + self.write("{\"actions\": { \"reject\": 1.0}, \"symbols\": { \"EXTERNAL_SETTINGS\": 1.0 }}") else: - self.send_response(200) - - self.send_header("Content-Length", str(len(response))) - self.send_header("Content-type", "text/plain") - self.end_headers() - self.wfile.write(response) - self.log_message("to be closed: %d, headers: %s, conn:'%s'" % (self.close_connection, str(self.headers), self.headers.get('Connection', "").lower())) - - conntype = self.headers.get('Connection', "").lower() - if conntype != 'keep-alive': - self.close_connection = True - - self.log_message("ka:'%s', pv:%s[%s]" % (str(conntype == 'keep-alive'), str(self.protocol_version >= "HTTP/1.1"), self.protocol_version)) - - - def do_POST(self): - """Respond to a POST request.""" - response = b"hello post" - content_length = int(self.headers.get('Content-Length', "0")) or 0 - content_type = "text/plain" - url = urlparse(self.path) - self.path = url.path - if content_length > 0: - _ = self.rfile.read(content_length) - if self.path == "/empty": - self.finish() - return - - if self.path == "/timeout": - time.sleep(2) - - if self.path == "/error_403": - self.send_response(403) + raise tornado.web.HTTPError(404) + + def head(self, path): + self.set_header("Content-Type", "text/plain") + if path == "/redirect1": + # Send an HTTP redirect to the bind address of the server + self.redirect(f"http://{self.request.host}:{self.request.port}/hello") + elif path == "/redirect2": + # Send an HTTP redirect to the bind address of the server + self.redirect(f"http://{self.request.host}:{self.request.port}/redirect1") + elif self.path == "/redirect3": + # Send an HTTP redirect to the bind address of the server + self.redirect(f"http://{self.request.host}:{self.request.port}/redirect4") + elif self.path == "/redirect4": + # Send an HTTP redirect to the bind address of the server + self.redirect(f"http://{self.request.host}:{self.request.port}/redirect3") else: self.send_response(200) - if self.path == "/map-simple": - response = b"hello map" - if self.path == "/map-query": - query = parse_qs(url.query) - if query['key'] == 'au': - response = b"hit" - else: - self.send_response(404) - if self.path == "/settings": - response = b"{\"actions\": { \"reject\": 1.0}, \"symbols\": { \"EXTERNAL_SETTINGS\": 1.0 }}" - content_type = "application/json" - - self.send_header("Content-Length", str(len(response))) - conntype = self.headers.get('Connection', "").lower() - if conntype != 'keep-alive': - self.close_connection = True - else: - self.send_header("Connection", "keep-alive") - - self.send_header("Content-type", content_type) - self.end_headers() - self.wfile.write(response) - self.log_message("to be closed: %d, headers: %s, conn:'%s'" % (self.close_connection, str(self.headers), self.headers.get('Connection', "").lower())) - self.log_message("ka:'%s', pv:%s[%s]" % (str(conntype == 'keep-alive'), str(self.protocol_version >= "HTTP/1.1"), self.protocol_version)) - - -class ThreadingSimpleServer(socketserver.ThreadingMixIn, - http.server.HTTPServer): - def __init__(self): - self.allow_reuse_address = True - self.timeout = 1 - http.server.HTTPServer.__init__(self, (HOST_NAME, PORT), MyHandler) - - def run(self): - dummy_killer.write_pid(PID) - try: - while 1: - sys.stdout.flush() - server.handle_request() - except KeyboardInterrupt: - print("Interrupt") - except socket.error: - print("Socket closed") - - def stop(self): - self.keep_running = False - self.server_close() - - -if __name__ == '__main__': - server = ThreadingSimpleServer() - - dummy_killer.setup_killer(server, server.stop) - - server.run() + self.set_header("Content-Type", "text/plain") + +def make_app(): + return tornado.web.Application([ + (r"(/[^/]+)", MainHandler), + ]) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--bind", "-b", default="localhost", help="bind address") + parser.add_argument("--port", "-p", type=int, default=18080, help="bind port") + parser.add_argument("--keyfile", "-k", help="server private key file") + parser.add_argument("--certfile", "-c", help="server certificate file") + parser.add_argument("--pidfile", "-pf", help="path to the PID file") + args = parser.parse_args() + + # Create the Tornado application + app = make_app() + + # If keyfile and certfile are provided, create an HTTPS server. + # Otherwise, create an HTTP server. + if args.keyfile and args.certfile: + ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) + ssl_ctx.load_cert_chain(args.certfile, args.keyfile) + server = tornado.httpserver.HTTPServer(app, ssl_options=ssl_ctx) + else: + server = tornado.httpserver.HTTPServer(app) + + # Start the server + server.bind(args.port, args.bind) + server.start(1) + + # Write the PID to the specified PID file, if provided + if args.pidfile: + with open(args.pidfile, "w") as f: + f.write(str(os.getpid())) + + tornado.ioloop.IOLoop.current().start() diff --git a/test/functional/util/dummy_https.py b/test/functional/util/dummy_https.py deleted file mode 100755 index 1dc058bdb..000000000 --- a/test/functional/util/dummy_https.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python3 - -import http.server -import http.server -import os -import socket -import socketserver -import ssl -import sys -import time - -import dummy_killer -from urllib.parse import urlparse, parse_qs - -PORT = 18081 -HOST_NAME = '127.0.0.1' - -PID = "/tmp/dummy_https.pid" - - -class MyHandler(http.server.BaseHTTPRequestHandler): - - def setup(self): - http.server.BaseHTTPRequestHandler.setup(self) - self.protocol_version = "HTTP/1.1" # allow connection: keep-alive - - def do_HEAD(self): - self.send_response(200) - self.send_header("Content-type", "text/html") - self.end_headers() - self.log_message("to be closed: " + self.close_connection) - - def do_GET(self): - response = b"hello world" - - """Respond to a GET request.""" - if self.path == "/empty": - self.finish() - return - - if self.path == "/timeout": - time.sleep(2) - - if self.path == "/error_403": - self.send_response(403) - else: - self.send_response(200) - - if self.path == "/content-length": - self.send_header("Content-Length", str(len(response))) - - self.send_header("Content-type", "text/plain") - self.end_headers() - self.wfile.write(response) - self.log_message("to be closed: %d, headers: %s, conn:'%s'" % (self.close_connection, str(self.headers), self.headers.get('Connection', "").lower())) - - conntype = self.headers.get('Connection', "").lower() - if conntype != 'keep-alive': - self.close_connection = True - - self.log_message("ka:'%s', pv:%s[%s]" % (str(conntype == 'keep-alive'), str(self.protocol_version >= "HTTP/1.1"), self.protocol_version)) - - - def do_POST(self): - """Respond to a POST request.""" - response = b"hello post" - content_length = int(self.headers.get('Content-Length', "0")) or 0 - content_type = "text/plain" - url = urlparse(self.path) - self.path = url.path - if content_length > 0: - _ = self.rfile.read(content_length) - if self.path == "/empty": - self.finish() - return - - if self.path == "/timeout": - time.sleep(2) - - if self.path == "/error_403": - self.send_response(403) - else: - self.send_response(200) - if self.path == "/map-simple": - response = b"hello map" - if self.path == "/map-query": - query = parse_qs(url.query) - if query['key'] == 'au': - response = b"hit" - else: - self.send_response(404) - if self.path == "/settings": - response = b"{\"actions\": { \"reject\": 1.0}, \"symbols\": { \"EXTERNAL_SETTINGS\": 1.0 }}" - content_type = "application/json" - - self.send_header("Content-Length", str(len(response))) - conntype = self.headers.get('Connection', "").lower() - if conntype != 'keep-alive': - self.close_connection = True - else: - self.send_header("Connection", "keep-alive") - - self.send_header("Content-type", content_type) - self.end_headers() - self.wfile.write(response) - self.log_message("to be closed: %d, headers: %s, conn:'%s'" % (self.close_connection, str(self.headers), self.headers.get('Connection', "").lower())) - self.log_message("ka:'%s', pv:%s[%s]" % (str(conntype == 'keep-alive'), str(self.protocol_version >= "HTTP/1.1"), self.protocol_version)) - -class ThreadingSimpleServer(socketserver.ThreadingMixIn, - http.server.HTTPServer): - def __init__(self, certfile, - keyfile,): - self.allow_reuse_address = True - self.timeout = 10 - http.server.HTTPServer.__init__(self, (HOST_NAME, PORT), MyHandler) - self.socket = ssl.wrap_socket (self.socket, - keyfile=keyfile, - certfile=certfile, server_side=True) - - def run(self): - dummy_killer.write_pid(PID) - try: - while 1: - sys.stdout.flush() - server.handle_request() - except KeyboardInterrupt: - print("Interrupt") - except socket.error: - print("Socket closed") - - def stop(self): - self.keep_running = False - self.server_close() - - -if __name__ == '__main__': - server = ThreadingSimpleServer(sys.argv[1], sys.argv[1]) - - dummy_killer.setup_killer(server, server.stop) - - server.run() |