prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  API V2 cache problem with custom configuration in nginx.conf.in
  API v2 responses doesn't take care about [```X-FORWARDED-PROTO```](https://github.com/GeotrekCE/Geotrek-admin/blob/master/conf/nginx.conf.in#L55) value defined in nginx configuration.
  This header is used by django to know if generated url (pictogram, attachment) is http or https.
  In some cases, custom configuration in nginx.conf.in to work behind haproxy, API response does not match with headers.
  
  For the moment, any change about it in nginx template should be followed by clearing api_v2 cache in admin panel
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `geotrek/api/v2/viewsets.py`
  Content:
  ```
  1 from hashlib import md5
  2 
  3 from django.conf import settings
  4 from django_filters.rest_framework.backends import DjangoFilterBackend
  5 from mapentity.renderers import GeoJSONRenderer
  6 from rest_framework import viewsets, renderers
  7 from rest_framework.authentication import BasicAuthentication, SessionAuthentication
  8 from rest_framework.generics import get_object_or_404
  9 from rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAuthenticated
  10 
  11 from geotrek.api.v2 import pagination as api_pagination, filters as api_filters
  12 from geotrek.api.v2.cache import RetrieveCacheResponseMixin
  13 from geotrek.api.v2.serializers import override_serializer
  14 
  15 
  16 class GeotrekViewSet(RetrieveCacheResponseMixin, viewsets.ReadOnlyModelViewSet):
  17     filter_backends = (
  18         DjangoFilterBackend,
  19         api_filters.GeotrekQueryParamsFilter,
  20         api_filters.GeotrekPublishedFilter,
  21     )
  22     pagination_class = api_pagination.StandardResultsSetPagination
  23     permission_classes = [IsAuthenticatedOrReadOnly, ] if settings.API_IS_PUBLIC else [IsAuthenticated, ]
  24     authentication_classes = [BasicAuthentication, SessionAuthentication]
  25     renderer_classes = [renderers.JSONRenderer, renderers.BrowsableAPIRenderer, ] if settings.DEBUG else [renderers.JSONRenderer, ]
  26     lookup_value_regex = r'\d+'
  27 
  28     def get_ordered_query_params(self):
  29         """ Get multi value query params sorted by key """
  30         parameters = self.request.query_params
  31         sorted_keys = sorted(parameters.keys())
  32         return {k: sorted(parameters.getlist(k)) for k in sorted_keys}
  33 
  34     def get_base_cache_string(self):
  35         """ return cache string as url path + ordered query params """
  36         return f"{self.request.path}:{self.get_ordered_query_params()}:{self.request.accepted_renderer.format}"
  37 
  38     def get_object_cache_key(self, pk):
  39         """ return specific object cache key based on object date_update column"""
  40         # don't directly use get_object or get_queryset to avoid select / prefetch and annotation sql queries
  41         # insure object exists and doesn't raise exception
  42         instance = get_object_or_404(self.get_queryset().model, pk=pk)
  43         date_update = instance.date_update
  44         return f"{self.get_base_cache_string()}:{date_update.isoformat()}"
  45 
  46     def object_cache_key_func(self, **kwargs):
  47         """ cache key md5 for retrieve viewset action """
  48         return md5(self.get_object_cache_key(kwargs.get('kwargs').get('pk')).encode("utf-8")).hexdigest()
  49 
  50     def get_serializer_context(self):
  51         return {
  52             'request': self.request,
  53             'kwargs': self.kwargs
  54         }
  55 
  56 
  57 class GeotrekGeometricViewset(GeotrekViewSet):
  58     filter_backends = GeotrekViewSet.filter_backends + (
  59         api_filters.GeotrekQueryParamsDimensionFilter,
  60         api_filters.GeotrekInBBoxFilter,
  61         api_filters.GeotrekDistanceToPointFilter,
  62     )
  63     distance_filter_field = 'geom'
  64     bbox_filter_field = 'geom'
  65     bbox_filter_include_overlapping = True
  66     renderer_classes = GeotrekViewSet.renderer_classes + [GeoJSONRenderer, ]
  67 
  68     def get_serializer_class(self):
  69         base_serializer_class = super().get_serializer_class()
  70         format_output = self.request.query_params.get('format', 'json')
  71         return override_serializer(format_output, base_serializer_class)
  72
  ```
  --- 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/geotrek/api/v2/viewsets.py b/geotrek/api/v2/viewsets.py
  --- a/geotrek/api/v2/viewsets.py
  +++ b/geotrek/api/v2/viewsets.py
  @@ -33,7 +33,8 @@
   
       def get_base_cache_string(self):
           """ return cache string as url path + ordered query params """
  -        return f"{self.request.path}:{self.get_ordered_query_params()}:{self.request.accepted_renderer.format}"
  +        proto_scheme = self.request.headers.get('X-Forwarded-Proto', self.request.scheme)  # take care about scheme defined in nginx.conf
  +        return f"{self.request.path}:{self.get_ordered_query_params()}:{self.request.accepted_renderer.format}:{proto_scheme}"
   
       def get_object_cache_key(self, pk):
           """ return specific object cache key based on object date_update column"""
  
verification_info: {"golden_diff": "diff --git a/geotrek/api/v2/viewsets.py b/geotrek/api/v2/viewsets.py\n--- a/geotrek/api/v2/viewsets.py\n+++ b/geotrek/api/v2/viewsets.py\n@@ -33,7 +33,8 @@\n \n     def get_base_cache_string(self):\n         \"\"\" return cache string as url path + ordered query params \"\"\"\n-        return f\"{self.request.path}:{self.get_ordered_query_params()}:{self.request.accepted_renderer.format}\"\n+        proto_scheme = self.request.headers.get('X-Forwarded-Proto', self.request.scheme)  # take care about scheme defined in nginx.conf\n+        return f\"{self.request.path}:{self.get_ordered_query_params()}:{self.request.accepted_renderer.format}:{proto_scheme}\"\n \n     def get_object_cache_key(self, pk):\n         \"\"\" return specific object cache key based on object date_update column\"\"\"\n", "issue": "API V2 cache problem with custom configuration in nginx.conf.in\nAPI v2 responses doesn't take care about [```X-FORWARDED-PROTO```](https://github.com/GeotrekCE/Geotrek-admin/blob/master/conf/nginx.conf.in#L55) value defined in nginx configuration.\r\nThis header is used by django to know if generated url (pictogram, attachment) is http or https.\r\nIn some cases, custom configuration in nginx.conf.in to work behind haproxy, API response does not match with headers.\r\n\r\nFor the moment, any change about it in nginx template should be followed by clearing api_v2 cache in admin panel\n", "before_files": [{"content": "from hashlib import md5\n\nfrom django.conf import settings\nfrom django_filters.rest_framework.backends import DjangoFilterBackend\nfrom mapentity.renderers import GeoJSONRenderer\nfrom rest_framework import viewsets, renderers\nfrom rest_framework.authentication import BasicAuthentication, SessionAuthentication\nfrom rest_framework.generics import get_object_or_404\nfrom rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAuthenticated\n\nfrom geotrek.api.v2 import pagination as api_pagination, filters as api_filters\nfrom geotrek.api.v2.cache import RetrieveCacheResponseMixin\nfrom geotrek.api.v2.serializers import override_serializer\n\n\nclass GeotrekViewSet(RetrieveCacheResponseMixin, viewsets.ReadOnlyModelViewSet):\n    filter_backends = (\n        DjangoFilterBackend,\n        api_filters.GeotrekQueryParamsFilter,\n        api_filters.GeotrekPublishedFilter,\n    )\n    pagination_class = api_pagination.StandardResultsSetPagination\n    permission_classes = [IsAuthenticatedOrReadOnly, ] if settings.API_IS_PUBLIC else [IsAuthenticated, ]\n    authentication_classes = [BasicAuthentication, SessionAuthentication]\n    renderer_classes = [renderers.JSONRenderer, renderers.BrowsableAPIRenderer, ] if settings.DEBUG else [renderers.JSONRenderer, ]\n    lookup_value_regex = r'\\d+'\n\n    def get_ordered_query_params(self):\n        \"\"\" Get multi value query params sorted by key \"\"\"\n        parameters = self.request.query_params\n        sorted_keys = sorted(parameters.keys())\n        return {k: sorted(parameters.getlist(k)) for k in sorted_keys}\n\n    def get_base_cache_string(self):\n        \"\"\" return cache string as url path + ordered query params \"\"\"\n        return f\"{self.request.path}:{self.get_ordered_query_params()}:{self.request.accepted_renderer.format}\"\n\n    def get_object_cache_key(self, pk):\n        \"\"\" return specific object cache key based on object date_update column\"\"\"\n        # don't directly use get_object or get_queryset to avoid select / prefetch and annotation sql queries\n        # insure object exists and doesn't raise exception\n        instance = get_object_or_404(self.get_queryset().model, pk=pk)\n        date_update = instance.date_update\n        return f\"{self.get_base_cache_string()}:{date_update.isoformat()}\"\n\n    def object_cache_key_func(self, **kwargs):\n        \"\"\" cache key md5 for retrieve viewset action \"\"\"\n        return md5(self.get_object_cache_key(kwargs.get('kwargs').get('pk')).encode(\"utf-8\")).hexdigest()\n\n    def get_serializer_context(self):\n        return {\n            'request': self.request,\n            'kwargs': self.kwargs\n        }\n\n\nclass GeotrekGeometricViewset(GeotrekViewSet):\n    filter_backends = GeotrekViewSet.filter_backends + (\n        api_filters.GeotrekQueryParamsDimensionFilter,\n        api_filters.GeotrekInBBoxFilter,\n        api_filters.GeotrekDistanceToPointFilter,\n    )\n    distance_filter_field = 'geom'\n    bbox_filter_field = 'geom'\n    bbox_filter_include_overlapping = True\n    renderer_classes = GeotrekViewSet.renderer_classes + [GeoJSONRenderer, ]\n\n    def get_serializer_class(self):\n        base_serializer_class = super().get_serializer_class()\n        format_output = self.request.query_params.get('format', 'json')\n        return override_serializer(format_output, base_serializer_class)\n", "path": "geotrek/api/v2/viewsets.py"}], "after_files": [{"content": "from hashlib import md5\n\nfrom django.conf import settings\nfrom django_filters.rest_framework.backends import DjangoFilterBackend\nfrom mapentity.renderers import GeoJSONRenderer\nfrom rest_framework import viewsets, renderers\nfrom rest_framework.authentication import BasicAuthentication, SessionAuthentication\nfrom rest_framework.generics import get_object_or_404\nfrom rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAuthenticated\n\nfrom geotrek.api.v2 import pagination as api_pagination, filters as api_filters\nfrom geotrek.api.v2.cache import RetrieveCacheResponseMixin\nfrom geotrek.api.v2.serializers import override_serializer\n\n\nclass GeotrekViewSet(RetrieveCacheResponseMixin, viewsets.ReadOnlyModelViewSet):\n    filter_backends = (\n        DjangoFilterBackend,\n        api_filters.GeotrekQueryParamsFilter,\n        api_filters.GeotrekPublishedFilter,\n    )\n    pagination_class = api_pagination.StandardResultsSetPagination\n    permission_classes = [IsAuthenticatedOrReadOnly, ] if settings.API_IS_PUBLIC else [IsAuthenticated, ]\n    authentication_classes = [BasicAuthentication, SessionAuthentication]\n    renderer_classes = [renderers.JSONRenderer, renderers.BrowsableAPIRenderer, ] if settings.DEBUG else [renderers.JSONRenderer, ]\n    lookup_value_regex = r'\\d+'\n\n    def get_ordered_query_params(self):\n        \"\"\" Get multi value query params sorted by key \"\"\"\n        parameters = self.request.query_params\n        sorted_keys = sorted(parameters.keys())\n        return {k: sorted(parameters.getlist(k)) for k in sorted_keys}\n\n    def get_base_cache_string(self):\n        \"\"\" return cache string as url path + ordered query params \"\"\"\n        proto_scheme = self.request.headers.get('X-Forwarded-Proto', self.request.scheme)  # take care about scheme defined in nginx.conf\n        return f\"{self.request.path}:{self.get_ordered_query_params()}:{self.request.accepted_renderer.format}:{proto_scheme}\"\n\n    def get_object_cache_key(self, pk):\n        \"\"\" return specific object cache key based on object date_update column\"\"\"\n        # don't directly use get_object or get_queryset to avoid select / prefetch and annotation sql queries\n        # insure object exists and doesn't raise exception\n        instance = get_object_or_404(self.get_queryset().model, pk=pk)\n        date_update = instance.date_update\n        return f\"{self.get_base_cache_string()}:{date_update.isoformat()}\"\n\n    def object_cache_key_func(self, **kwargs):\n        \"\"\" cache key md5 for retrieve viewset action \"\"\"\n        return md5(self.get_object_cache_key(kwargs.get('kwargs').get('pk')).encode(\"utf-8\")).hexdigest()\n\n    def get_serializer_context(self):\n        return {\n            'request': self.request,\n            'kwargs': self.kwargs\n        }\n\n\nclass GeotrekGeometricViewset(GeotrekViewSet):\n    filter_backends = GeotrekViewSet.filter_backends + (\n        api_filters.GeotrekQueryParamsDimensionFilter,\n        api_filters.GeotrekInBBoxFilter,\n        api_filters.GeotrekDistanceToPointFilter,\n    )\n    distance_filter_field = 'geom'\n    bbox_filter_field = 'geom'\n    bbox_filter_include_overlapping = True\n    renderer_classes = GeotrekViewSet.renderer_classes + [GeoJSONRenderer, ]\n\n    def get_serializer_class(self):\n        base_serializer_class = super().get_serializer_class()\n        format_output = self.request.query_params.get('format', 'json')\n        return override_serializer(format_output, base_serializer_class)\n", "path": "geotrek/api/v2/viewsets.py"}]}