prompt: 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()
  
  ```
  
golden_diff: 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)
  
verification_info: {"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"}]}