In #6778 we found that AWS forwards HTTP headers to Lambdas from clients without modifying their casing. Since users are relying on this behavior, it effectively renders a web server that lowercases headers unusable as proxy for localstack. In general, I think there is a case to be made that web servers should not manipulate the casing of request headers, so that they can function as application-layer proxy to backends that make assumptions about header casing.

The issue of header casing for HTTP/1.1 in hypercorn was addressed with https://github.com/pgjones/hypercorn/issues/66, but later reverted with https://github.com/pgjones/hypercorn/issues/77. Apparently the relevant ASGI spec is being discussed here https://github.com/django/asgiref/issues/246 where I think we should make that case.

If this is a fundamental limitation of ASGI and we cannot get this into hypercorn, then we will be forced to either
- apologize to lambda users and tell them that they need to re-write their lambda code in a way that treats headers in a case-insensitive way
- fork hypercorn and maintain our own version
- use another webserver that does not manipulate HTTP headers, or at least allows access to the raw headers in some way
gateway: Gateway,
    host: str = "localhost",
    port: int = constants.DEFAULT_PORT_EDGE,
    use_reloader: bool = True,
    ssl_creds: Optional[Tuple[Any, Any]] = None,
    **kwargs,
) -> None:
    """
    Serve the given Gateway through a hypercorn server and block until it is completed.
    :param gateway: the Gateway instance to serve
    :param host: the host to expose the server on
    :param port: the port to expose the server on
    :param use_reloader: whether to use the reloader
    :param ssl_creds: the ssl credentials (tuple of certfile and keyfile)
    :param kwargs: any oder parameters that can be passed to the hypercorn.Config object
    """
    config = Config()
    config.bind = f"{host}:{port}"
    config.use_reloader = use_reloader
    if ssl_creds:
        cert_file_name, key_file_name = ssl_creds
        if cert_file_name:
            kwargs["certfile"] = cert_file_name
        if key_file_name:
            kwargs["keyfile"] = key_file_name
    for k, v in kwargs.items():
        setattr(config, k, v)
    loop = asyncio.new_event_loop()
    loop.run_until_complete(serve_hypercorn(AsgiGateway(gateway, event_loop=loop), config))