import tornado from tornado.httpclient import AsyncHTTPClient from tornado.httputil import HTTPHeaders _LEGACY_PARAM_TO_HEADER_MAP = { "qrz_username": "X-QRZ-Username", "qrz_password": "X-QRZ-Password", "qrz_session_key": "X-QRZ-Session-Key", "hamqth_username": "X-HamQTH-Username", "hamqth_password": "X-HamQTH-Password", "hamqth_session_id": "X-HamQTH-Session-ID", } class V1RedirectHandler(tornado.web.RequestHandler): """Transparently proxies requests from the old API to the new one, returning whatever the v2 endpoint returns, for endpoints with no breaking changes.""" async def _proxy(self, path): new_url = f"{self.request.protocol}://{self.request.host}/api/v2/{path}" if self.request.query: new_url += f"?{self.request.query}" # Copy the incoming headers so we can add translated legacy credentials without changing the original # request. headers = HTTPHeaders(self.request.headers) for param, header in _LEGACY_PARAM_TO_HEADER_MAP.items(): value = self.get_query_argument(param, default=None) if value: headers[header] = value client = AsyncHTTPClient() try: response = await client.fetch( new_url, method=self.request.method, headers=headers, body=None if self.request.method == "GET" else (self.request.body or b""), raise_error=False, follow_redirects=False, request_timeout=10.0, ) except Exception as e: raise tornado.web.HTTPError(502, reason=str(e)) self.set_status(response.code, response.reason) if isinstance(response.headers, HTTPHeaders): for name, value in response.headers.get_all(): # Let Tornado recompute these for the outgoing response if name.lower() not in ( "content-length", "transfer-encoding", "connection", ): self.add_header(name, value) if response.body: self.write(response.body) async def get(self, path): await self._proxy(path) async def post(self, path): await self._proxy(path)