Skip to content

Providing a better abstract layer for Client/Server for implementing future current and future http protocols #11743

@Vizonex

Description

@Vizonex

Is your feature request related to a problem?

Recently I've been attempting to implement http/2 and http/3 into this library but I've been having a bit of difficulty on figuring out how aiohttp should handle these and future protocols. What I have determined is that we need to provide a smarter abstract layer or try an approach similar to httpx.

I think it should be done in this order and I'll start with the client's end.

Client -> Abstract Layer for Http/1.1 Http/2 and Http/3 -> Server

Server end is more or less the same where we can replace the Server and median if we wish...

Low Level Server Layer (example: aioquic, h2, or the current aiohttp http 1.1 ) -> Abstract Layer -> Aiohttp Application

When accepting TCP Connections there are flags for accepting these protocols on connections. We can use it to determine which protocol we end up going with on both the client and server's end as we wish...

Code is from h2 documentation and I've snipped out the unimportant details

    # we can check to see what alpn protocols are in use on connection to determine which protocol gets set...
    ctx.set_alpn_protocols(["h2", "http/1.1"])

While each protocol is vastly different from each over. A rewrite into this format In a future release would benefit more people and make aiohttp a more desirable library later down the road.

Describe the solution you'd like

In here I'll lay out an abstract class object that handles this sending of requests and responses for both clients and servers.

from abc import ABC, abstractmethod

from aiohttp import ClientRequest, ClientResponse
from aiohttp.web import Request, Response



class AbstractClientProtocol(ABC):
    # My main goal was visualizing an abstract layering system 
    # for future protocols so __init__ did not feel important

    @abstractmethod
    async def send_request(req:ClientRequest) -> None:...

    @abstractmethod
    async def get_response(self) -> ClientResponse:...

    # Otherwise I was thinking we try
    @abstractmethod
    def on_response(self, resp:ClientResponse):...

# From there we can build on top of it and pass whatever is needed...
class Http11ClientProtocol(AbstractClientProtocol):
    pass

class Http2ClientProtocol(AbstractClientProtocol):
    pass

class Http3ClientProtocol(AbstractClientProtocol):
    pass


class AbstractServerProtocol(ABC):

    # I did however understand that each protocol is vastly different
    # from each other however if we can just provide handlers for
    # request and responses that will be enough to prove my point and idea.
    @abstractmethod
    async def on_request(self, req:Request) -> None:...

    @abstractmethod
    async def on_response(self, resp:Response) -> None:...


class Http11ServerProtocol(AbstractServerProtocol):
    pass

class Http2ServerProtocol(AbstractServerProtocol):
    pass

class Http3ServerProtocol(AbstractServerProtocol):
    pass

Describe alternatives you've considered

The alternative http clients that implement http2 or http3 or both vs aiohttp are currently

  • curl-cffi (looks to be aimed towards webscrapers)
  • cycurl (I've contributed here but it's been a long time)
  • httpx (it's a little sluggish due to only being pure python)

Server backend implementations

  • hypercorn (http/2 and http/3 supported)
  • aioquic (hypercorn works off this library)

Related component

Client, Server

Additional context

No response

Code of Conduct

  • I agree to follow the aio-libs Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions