import tornado
from tornado.httpclient import AsyncHTTPClient

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."""

    SUPPORTED_METHODS = ("GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS")

    # Methods where an HTTP body isn't valid
    _BODYLESS_METHODS = {"GET", "HEAD", "OPTIONS"}

    async def _proxy(self, path):
        new_url = f"{self.request.protocol}://{self.request.host}/api/v2/{path}"
        if self.request.query:
            new_url += "?" + self.request.query

        client = AsyncHTTPClient()
        try:
            response = await client.fetch(
                new_url,
                method=self.request.method,
                headers=self.request.headers,
                body=None if self.request.method in self._BODYLESS_METHODS 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)
        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)
        self.finish()

    async def get(self, path):
        await self._proxy(path)

    async def post(self, path):
        await self._proxy(path)

    async def put(self, path):
        await self._proxy(path)

    async def delete(self, path):
        await self._proxy(path)

    async def patch(self, path):
        await self._proxy(path)