import http.client from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer import threading import unittest import subpath_gateway as gateway class Backend(BaseHTTPRequestHandler): def do_GET(self): if self.path=='/api/status': data=b'{"ok":true,"asset":"/api/uploads/file","unchanged":"/tmp/model.json"}' mime='application/json' elif self.path=='/src/app.js': data=b"fetch('/api/status'); frame.src=`/dxf_rasterizer.html?file=x`;" mime='application/javascript' elif self.path=='/api/uploads/file':data=b'\x00\xff\x01';mime='application/octet-stream' else:data=b'';mime='text/html' self.send_response(200);self.send_header('Content-Type',mime) self.send_header('Content-Length',str(len(data)));self.end_headers();self.wfile.write(data) def do_POST(self): body=self.rfile.read(int(self.headers['Content-Length'])) self.send_response(200);self.send_header('Content-Length',str(len(body))) self.end_headers();self.wfile.write(body) def log_message(self,*args):pass class GatewayTests(unittest.TestCase): @classmethod def setUpClass(cls): cls.backend=ThreadingHTTPServer(('127.0.0.1',0),Backend) gateway.UPSTREAM_PORT=cls.backend.server_port cls.proxy=ThreadingHTTPServer(('127.0.0.1',0),gateway.Gateway) for s in (cls.backend,cls.proxy):threading.Thread(target=s.serve_forever,daemon=True).start() @classmethod def tearDownClass(cls): for s in (cls.proxy,cls.backend):s.shutdown();s.server_close() def request(self,path,method='GET',body=None): c=http.client.HTTPConnection('127.0.0.1',self.proxy.server_port) c.request(method,path,body);r=c.getresponse();result=(r.status,dict(r.getheaders()),r.read());c.close();return result def test_mount_redirect_preserves_job(self): code,headers,_=self.request('/box-sample?job=abc') self.assertEqual(code,308);self.assertEqual(headers['Location'],'/box-sample/?job=abc') def test_api_and_javascript_prefix_without_model_path_change(self): _,headers,body=self.request('/box-sample/api/status') self.assertIn(b'/box-sample/api/uploads/file',body);self.assertIn(b'/tmp/model.json',body) self.assertEqual(int(headers['Content-Length']),len(body)) _,_,script=self.request('/box-sample/src/app.js') self.assertIn(b"fetch('/box-sample/api/status')",script) self.assertIn(b'/box-sample/dxf_rasterizer.html',script) def test_binary_and_post_untouched(self): self.assertEqual(self.request('/box-sample/api/uploads/file')[2],b'\x00\xff\x01') self.assertEqual(self.request('/box-sample/api/analyze','POST',b'{"drawing":"/api/original"}')[2],b'{"drawing":"/api/original"}') def test_other_service_paths_rejected(self): for path in ('/api/status','/box-sample-other/api/status'): self.assertEqual(self.request(path)[0],404) if __name__=='__main__':unittest.main()