Hooking 기능

ahttp_client 패키지에서 후킹이란 HTTP 요청이 있기 전과 후에 데이터를 처리하는 기능을 의미합니다.세션 단위와 후킹과 요청 단위의 후킹으로 나누어집니다.

후킹 기능은 보통 아래와 같이 이용됩니다.

  • Before Hook (HTTP 요청 이전):
    • 인증과 같이 필요한 HTTP 구성요소를 설정합니다.

    • 인수가 올바르게 입력되었는지 검증합니다.

  • After Hook (HTTP 요청 이후):
    • 원본 데이터를 데이터클래스에 파싱합니다.

    • HTTP 상태 코드에 따라 적절한 조치합니다.

세션 후킹(Session Hooking)

세션 단위의 후킹은 메소드를 오버라이딩하는 방식으로 만듭니다.

세션 단위의 후킹 예제
 1class GithubService(Session):
 2    def __init__(self, token: str):
 3        self._token = token  # Private Attribute
 4        super().__init__("https://api.github.com")
 5
 6    # overridding before_hook method
 7    async def before_hook(self, req_obj: RequestCore, path: str):
 8        req_obj.headers["Authorization"] = self._token
 9        req_obj.headers["Accepts"] = "application/vnd.github+json;"
10        return req_obj, path
11
12    # overridding after_hook method
13    async def after_hook(self, response: aiohttp.ClientResponse):
14        if response.status_code != 200:
15            raise HTTPException()
16        return response
17
18    @request("GET", "/users/{user}/repos")
19    def list_repositories(
20        self, user: Annotated[str, Path]
21    ) -> dict[str, Any]:
22        return await response.json()

`GithubSerivce`에서 before_hook와 after_hook 메소드를 오버라이딩을 통해 후킹을 정의하였습니다.

HTTP 요청이 있기 전에는 인증에 필요한 토큰을 비공개 속성 값으로 정의해주었고, before_hook 메소드를 통해 header에 키를 삽입하였습니다. list_repositories 메소드와 같이, GithubSerivce 객체에 소속되어 있는 메소드가 호출된다면, HTTP 요청이 있기 전에 before_hook 메소드를 먼저 거치고 HTTP 요청을 진행합니다.

HTTP 요청이 끝난다면, after_hook 메소드가 호출됩니다. after_hook 메소드에서는 HTTP 상태 코드를 확인하며, 상태 코드의 값이 200이 아니라면, HTTPException(사전에 정의된 예외) 를 발생시킵니다.

요청 후킹(Request Hooking)

요청 단위의 후킹은 데코레이터 메소드를 이용하여 생성하게 됩니다.

요청 단위의 후킹 예제
 1token = "GITHUB TOKEN"
 2
 3@Session.single_session(base_url="https://api.github.com")
 4@request("GET", "/repos/{user}/{repo}/topics", directly_response=True)
 5def repository_topic(
 6    self,
 7    user: Annotated[str, Path],
 8    repo: Annotated[str, Path]
 9) -> list[str]:
10    pass
11
12# before_hook method
13@repository_topic.before_hook
14async def before_hook(self, req_obj: RequestCore, path: str):
15    req_obj.headers["Authorization"] = token
16    req_obj.headers["Accepts"] = "application/vnd.github+json;"
17    return req_obj, path
18
19# after_hook method
20@repository_topic.after_hook
21async def after_hook(self, response: aiohttp.ClientResponse):
22    data = await response.json()
23    return data["names"]

깃허브 레포스토리의 주제를 가져오기 위해, repository_topic 메소드를 정의하였습니다. 그리고 repository_topic 메소드에 있는 before_hook 그리고 after_hook 데코레이터 함수를 이용하여 후킹을 정의하였습니다.

before_hook 메소드에서는 필요한 구성 요소(인증키 등)를 HTTP 요청이 있기 전에 삽입하는 역할을 합니다.

after_hook 메소드는 응답받은 결과를 정제하여 반환하는 역할을 하며, 불필요한 키를 제거합니다.