We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Case insensitive lookup of header values in http proxy events
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->

Http headers are meant to be case insensitive, but lambda events use case sensitive dicts for the header keys.

For example getting the `Authorization` header you will need to do a case insensitive look up to support if the header is `authorization`. So you end up doing something like this.

```python3
authorization = None
for key, value in self.headers.items():
    if name.lower() == 'authorization'
        authorization = value
```

**Describe the solution you'd like**
<!-- A clear and concise description of what you want to happen. -->

> Linked pull request : #185

Update `BaseProxyEvent.get_header_value` method to support case insensitive lookups by default

```python3
authorization = event.get_header_value("authorization")
```

```python3
    def get_header_value(
        self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False
    ) -> Optional[str]:
        """Get header value by name

        Parameters
        ----------
        name: str
            Header name
        default_value: str, optional
            Default value if no value was found by name
        case_sensitive: bool
            Whether to use a case sensitive look up
        Returns
        -------
        str, optional
            Header value
        """
        if case_sensitive:
            return self.headers.get(name, default_value)
        
        return next((value for key, value in self.headers.items() if name.lower() == key.lower()), default_value)
```

**Questions**

* Should we default to case insensitive look ups? This is what most people would want?
* Just return the first match? Or support returning all matches?

**Describe alternatives you've considered**
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
Use the requests CaseInsensitiveDict or port it :
* https://github.com/psf/requests/blob/333fa8d3f201f68b82d9e8f26be4987e869fd3bf/requests/structures.py#L15

**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->
From the Http 1.1 spec, https headers are not supposed to be case sensitive:  https://www.w3.org/Protocols/rfc2616/rfc2616.html

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `aws_lambda_powertools/utilities/data_classes/common.py`
Content:
```
1 from typing import Any, Dict, Optional
2 
3 
4 class DictWrapper:
5     """Provides a single read only access to a wrapper dict"""
6 
7     def __init__(self, data: Dict[str, Any]):
8         self._data = data
9 
10     def __getitem__(self, key: str) -> Any:
11         return self._data[key]
12 
13     def get(self, key: str) -> Optional[Any]:
14         return self._data.get(key)
15 
16 
17 class BaseProxyEvent(DictWrapper):
18     @property
19     def headers(self) -> Dict[str, str]:
20         return self["headers"]
21 
22     @property
23     def query_string_parameters(self) -> Optional[Dict[str, str]]:
24         return self.get("queryStringParameters")
25 
26     @property
27     def is_base64_encoded(self) -> bool:
28         return self.get("isBase64Encoded")
29 
30     @property
31     def body(self) -> Optional[str]:
32         return self.get("body")
33 
34     def get_query_string_value(self, name: str, default_value: Optional[str] = None) -> Optional[str]:
35         """Get query string value by name
36 
37         Parameters
38         ----------
39         name: str
40             Query string parameter name
41         default_value: str, optional
42             Default value if no value was found by name
43         Returns
44         -------
45         str, optional
46             Query string parameter value
47         """
48         params = self.query_string_parameters
49         return default_value if params is None else params.get(name, default_value)
50 
51     def get_header_value(self, name: str, default_value: Optional[str] = None) -> Optional[str]:
52         """Get header value by name
53 
54         Parameters
55         ----------
56         name: str
57             Header name
58         default_value: str, optional
59             Default value if no value was found by name
60         Returns
61         -------
62         str, optional
63             Header value
64         """
65         return self.headers.get(name, default_value)
66
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py
--- a/aws_lambda_powertools/utilities/data_classes/common.py
+++ b/aws_lambda_powertools/utilities/data_classes/common.py
@@ -48,7 +48,9 @@
         params = self.query_string_parameters
         return default_value if params is None else params.get(name, default_value)
 
-    def get_header_value(self, name: str, default_value: Optional[str] = None) -> Optional[str]:
+    def get_header_value(
+        self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False
+    ) -> Optional[str]:
         """Get header value by name
 
         Parameters
@@ -57,9 +59,14 @@
             Header name
         default_value: str, optional
             Default value if no value was found by name
+        case_sensitive: bool
+            Whether to use a case sensitive look up
         Returns
         -------
         str, optional
             Header value
         """
-        return self.headers.get(name, default_value)
+        if case_sensitive:
+            return self.headers.get(name, default_value)
+
+        return next((value for key, value in self.headers.items() if name.lower() == key.lower()), default_value)

{"golden_diff": "diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py\n--- a/aws_lambda_powertools/utilities/data_classes/common.py\n+++ b/aws_lambda_powertools/utilities/data_classes/common.py\n@@ -48,7 +48,9 @@\n         params = self.query_string_parameters\n         return default_value if params is None else params.get(name, default_value)\n \n-    def get_header_value(self, name: str, default_value: Optional[str] = None) -> Optional[str]:\n+    def get_header_value(\n+        self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False\n+    ) -> Optional[str]:\n         \"\"\"Get header value by name\n \n         Parameters\n@@ -57,9 +59,14 @@\n             Header name\n         default_value: str, optional\n             Default value if no value was found by name\n+        case_sensitive: bool\n+            Whether to use a case sensitive look up\n         Returns\n         -------\n         str, optional\n             Header value\n         \"\"\"\n-        return self.headers.get(name, default_value)\n+        if case_sensitive:\n+            return self.headers.get(name, default_value)\n+\n+        return next((value for key, value in self.headers.items() if name.lower() == key.lower()), default_value)\n", "issue": "Case insensitive lookup of header values in http proxy events\n**Is your feature request related to a problem? Please describe.**\r\n<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->\r\n\r\nHttp headers are meant to be case insensitive, but lambda events use case sensitive dicts for the header keys.\r\n\r\nFor example getting the `Authorization` header you will need to do a case insensitive look up to support if the header is `authorization`. So you end up doing something like this.\r\n\r\n```python3\r\nauthorization = None\r\nfor key, value in self.headers.items():\r\n    if name.lower() == 'authorization'\r\n        authorization = value\r\n```\r\n\r\n**Describe the solution you'd like**\r\n<!-- A clear and concise description of what you want to happen. -->\r\n\r\n> Linked pull request : #185\r\n\r\nUpdate `BaseProxyEvent.get_header_value` method to support case insensitive lookups by default\r\n\r\n```python3\r\nauthorization = event.get_header_value(\"authorization\")\r\n```\r\n\r\n```python3\r\n    def get_header_value(\r\n        self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False\r\n    ) -> Optional[str]:\r\n        \"\"\"Get header value by name\r\n\r\n        Parameters\r\n        ----------\r\n        name: str\r\n            Header name\r\n        default_value: str, optional\r\n            Default value if no value was found by name\r\n        case_sensitive: bool\r\n            Whether to use a case sensitive look up\r\n        Returns\r\n        -------\r\n        str, optional\r\n            Header value\r\n        \"\"\"\r\n        if case_sensitive:\r\n            return self.headers.get(name, default_value)\r\n        \r\n        return next((value for key, value in self.headers.items() if name.lower() == key.lower()), default_value)\r\n```\r\n\r\n**Questions**\r\n\r\n* Should we default to case insensitive look ups? This is what most people would want?\r\n* Just return the first match? Or support returning all matches?\r\n\r\n**Describe alternatives you've considered**\r\n<!-- A clear and concise description of any alternative solutions or features you've considered. -->\r\nUse the requests CaseInsensitiveDict or port it :\r\n* https://github.com/psf/requests/blob/333fa8d3f201f68b82d9e8f26be4987e869fd3bf/requests/structures.py#L15\r\n\r\n**Additional context**\r\n<!-- Add any other context or screenshots about the feature request here. -->\r\nFrom the Http 1.1 spec, https headers are not supposed to be case sensitive:  https://www.w3.org/Protocols/rfc2616/rfc2616.html\n", "before_files": [{"content": "from typing import Any, Dict, Optional\n\n\nclass DictWrapper:\n    \"\"\"Provides a single read only access to a wrapper dict\"\"\"\n\n    def __init__(self, data: Dict[str, Any]):\n        self._data = data\n\n    def __getitem__(self, key: str) -> Any:\n        return self._data[key]\n\n    def get(self, key: str) -> Optional[Any]:\n        return self._data.get(key)\n\n\nclass BaseProxyEvent(DictWrapper):\n    @property\n    def headers(self) -> Dict[str, str]:\n        return self[\"headers\"]\n\n    @property\n    def query_string_parameters(self) -> Optional[Dict[str, str]]:\n        return self.get(\"queryStringParameters\")\n\n    @property\n    def is_base64_encoded(self) -> bool:\n        return self.get(\"isBase64Encoded\")\n\n    @property\n    def body(self) -> Optional[str]:\n        return self.get(\"body\")\n\n    def get_query_string_value(self, name: str, default_value: Optional[str] = None) -> Optional[str]:\n        \"\"\"Get query string value by name\n\n        Parameters\n        ----------\n        name: str\n            Query string parameter name\n        default_value: str, optional\n            Default value if no value was found by name\n        Returns\n        -------\n        str, optional\n            Query string parameter value\n        \"\"\"\n        params = self.query_string_parameters\n        return default_value if params is None else params.get(name, default_value)\n\n    def get_header_value(self, name: str, default_value: Optional[str] = None) -> Optional[str]:\n        \"\"\"Get header value by name\n\n        Parameters\n        ----------\n        name: str\n            Header name\n        default_value: str, optional\n            Default value if no value was found by name\n        Returns\n        -------\n        str, optional\n            Header value\n        \"\"\"\n        return self.headers.get(name, default_value)\n", "path": "aws_lambda_powertools/utilities/data_classes/common.py"}], "after_files": [{"content": "from typing import Any, Dict, Optional\n\n\nclass DictWrapper:\n    \"\"\"Provides a single read only access to a wrapper dict\"\"\"\n\n    def __init__(self, data: Dict[str, Any]):\n        self._data = data\n\n    def __getitem__(self, key: str) -> Any:\n        return self._data[key]\n\n    def get(self, key: str) -> Optional[Any]:\n        return self._data.get(key)\n\n\nclass BaseProxyEvent(DictWrapper):\n    @property\n    def headers(self) -> Dict[str, str]:\n        return self[\"headers\"]\n\n    @property\n    def query_string_parameters(self) -> Optional[Dict[str, str]]:\n        return self.get(\"queryStringParameters\")\n\n    @property\n    def is_base64_encoded(self) -> bool:\n        return self.get(\"isBase64Encoded\")\n\n    @property\n    def body(self) -> Optional[str]:\n        return self.get(\"body\")\n\n    def get_query_string_value(self, name: str, default_value: Optional[str] = None) -> Optional[str]:\n        \"\"\"Get query string value by name\n\n        Parameters\n        ----------\n        name: str\n            Query string parameter name\n        default_value: str, optional\n            Default value if no value was found by name\n        Returns\n        -------\n        str, optional\n            Query string parameter value\n        \"\"\"\n        params = self.query_string_parameters\n        return default_value if params is None else params.get(name, default_value)\n\n    def get_header_value(\n        self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False\n    ) -> Optional[str]:\n        \"\"\"Get header value by name\n\n        Parameters\n        ----------\n        name: str\n            Header name\n        default_value: str, optional\n            Default value if no value was found by name\n        case_sensitive: bool\n            Whether to use a case sensitive look up\n        Returns\n        -------\n        str, optional\n            Header value\n        \"\"\"\n        if case_sensitive:\n            return self.headers.get(name, default_value)\n\n        return next((value for key, value in self.headers.items() if name.lower() == key.lower()), default_value)\n", "path": "aws_lambda_powertools/utilities/data_classes/common.py"}]}