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
port: int,
    bind_addresses: List[str],
    handler: Callable = None,
    asynchronous: bool = True,
    ssl_creds: Tuple[str, str] = None,
    max_content_length: int = None,
    send_timeout: int = None,
):
    """
    Run an HTTP2-capable Web server on the given port, processing incoming requests via a `handler` function.
    :param port: port to bind to
    :param bind_addresses: addresses to bind to
    :param handler: callable that receives the request and returns a response
    :param asynchronous: whether to start the server asynchronously in the background
    :param ssl_creds: optional tuple with SSL cert file names (cert file, key file)
    :param max_content_length: maximum content length of uploaded payload
    :param send_timeout: timeout (in seconds) for sending the request payload over the wire
    """
    ensure_event_loop()
    app = Quart(__name__, static_folder=None)
    app.config["MAX_CONTENT_LENGTH"] = max_content_length or DEFAULT_MAX_CONTENT_LENGTH
    if send_timeout:
        app.config["BODY_TIMEOUT"] = send_timeout
    @app.route("/", methods=HTTP_METHODS, defaults={"path": ""})
    @app.route("/<path:path>", methods=HTTP_METHODS)
    async def index(path=None):