prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  docs should not use underscores in http headers for auth
  **Version**
  any
  
  **Describe the bug**
  https://docs.pulpproject.org/pulpcore/authentication/webserver.html#webserver-auth-with-reverse-proxy says:
  > With nginx providing authentication, all it can do is pass REMOTE_USER (or similar name) to the application webserver, i.e. gunicorn. You can pass the header as part of the proxy request in nginx with a config line like:
  >     
  >    proxy_set_header REMOTE_USER $remote_user;
  
  But since gunicorn 22.0 (more precisely https://github.com/benoitc/gunicorn/commit/72b8970dbf2bf3444eb2e8b12aeff1a3d5922a9a/  https://github.com/benoitc/gunicorn/issues/2799) headers with underscores are forbidden by default.
  
  If the docs would use a dash, so `proxy_set_header REMOTE-USER …` things would work :)
  
  **Additional context**
  Grant made me file this, and I did not want to post a screenshot of our colorful conversation ;)
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `pulpcore/app/tasks/repository.py`
  Content:
  ```
  1 from gettext import gettext as _
  2 from logging import getLogger
  3 
  4 from django.db import transaction
  5 
  6 from pulpcore.app import models, serializers
  7 
  8 log = getLogger(__name__)
  9 
  10 
  11 def delete(repo_id):
  12     """
  13     Delete a :class:`~pulpcore.app.models.Repository`
  14 
  15     Args:
  16         repo_id (int): The name of the repository to be deleted
  17     """
  18 
  19     models.Repository.objects.filter(pk=repo_id).delete()
  20 
  21 
  22 def update(repo_id, partial=True, data=None):
  23     """
  24     Updates a :class:`~pulpcore.app.models.Repository`
  25 
  26     Args:
  27         repo_id (int): The id of the repository to be updated
  28         partial (bool): Boolean to allow partial updates. If set to False, values for all
  29                         required fields must be passed or a validation error will be raised.
  30                         Defaults to True
  31         data (QueryDict): dict of attributes to change and their new values; if None, no attempt to
  32                      update the repository object will be made
  33     """
  34     instance = models.Repository.objects.get(pk=repo_id)
  35     serializer = serializers.RepositorySerializer(instance, data=data, partial=partial)
  36     serializer.is_valid(raise_exception=True)
  37     serializer.save()
  38 
  39 
  40 def delete_version(pk):
  41     """
  42     Delete a repository version by squashing its changes with the next newer version. This ensures
  43     that the content set for each version stays the same.
  44 
  45     There must be a newer version to squash into. If we deleted the latest version, the next content
  46     change would create a new one of the same number, which would violate the immutability
  47     guarantee.
  48 
  49     Args:
  50         pk (int): the primary key for a RepositoryVersion to delete
  51 
  52     Raises:
  53         models.RepositoryVersion.DoesNotExist: if there is not a newer version to squash into.
  54             TODO: something more friendly
  55     """
  56     with transaction.atomic():
  57         try:
  58             version = models.RepositoryVersion.objects.get(pk=pk)
  59         except models.RepositoryVersion.DoesNotExist:
  60             log.info(_('The repository version was not found. Nothing to do.'))
  61             return
  62 
  63         log.info(_('Deleting and squashing version %(v)d of repository %(r)s'),
  64                  {'v': version.number, 'r': version.repository.name})
  65 
  66         version.delete()
  67 
  68 
  69 def add_and_remove(repository_pk, add_content_units, remove_content_units, base_version_pk=None):
  70     """
  71     Create a new repository version by adding and then removing content units.
  72 
  73     Args:
  74         repository_pk (int): The primary key for a Repository for which a new Repository Version
  75             should be created.
  76         add_content_units (list): List of PKs for :class:`~pulpcore.app.models.Content` that
  77             should be added to the previous Repository Version for this Repository.
  78         remove_content_units (list): List of PKs for:class:`~pulpcore.app.models.Content` that
  79             should be removed from the previous Repository Version for this Repository.
  80         base_version_pk (int): the primary key for a RepositoryVersion whose content will be used
  81             as the initial set of content for our new RepositoryVersion
  82     """
  83     repository = models.Repository.objects.get(pk=repository_pk)
  84 
  85     if base_version_pk:
  86         base_version = models.RepositoryVersion.objects.get(pk=base_version_pk)
  87     else:
  88         base_version = None
  89 
  90     if '*' in remove_content_units:
  91         latest = models.RepositoryVersion.latest(repository)
  92         remove_content_units = latest.content.values_list('pk', flat=True)
  93 
  94     with models.RepositoryVersion.create(repository, base_version=base_version) as new_version:
  95         new_version.remove_content(models.Content.objects.filter(pk__in=remove_content_units))
  96         new_version.add_content(models.Content.objects.filter(pk__in=add_content_units))
  97
  ```
  --- 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/pulpcore/app/tasks/repository.py b/pulpcore/app/tasks/repository.py
  --- a/pulpcore/app/tasks/repository.py
  +++ b/pulpcore/app/tasks/repository.py
  @@ -89,7 +89,10 @@
   
       if '*' in remove_content_units:
           latest = models.RepositoryVersion.latest(repository)
  -        remove_content_units = latest.content.values_list('pk', flat=True)
  +        if latest:
  +            remove_content_units = latest.content.values_list('pk', flat=True)
  +        else:
  +            remove_content_units = []
   
       with models.RepositoryVersion.create(repository, base_version=base_version) as new_version:
           new_version.remove_content(models.Content.objects.filter(pk__in=remove_content_units))
  
verification_info: {"golden_diff": "diff --git a/pulpcore/app/tasks/repository.py b/pulpcore/app/tasks/repository.py\n--- a/pulpcore/app/tasks/repository.py\n+++ b/pulpcore/app/tasks/repository.py\n@@ -89,7 +89,10 @@\n \n     if '*' in remove_content_units:\n         latest = models.RepositoryVersion.latest(repository)\n-        remove_content_units = latest.content.values_list('pk', flat=True)\n+        if latest:\n+            remove_content_units = latest.content.values_list('pk', flat=True)\n+        else:\n+            remove_content_units = []\n \n     with models.RepositoryVersion.create(repository, base_version=base_version) as new_version:\n         new_version.remove_content(models.Content.objects.filter(pk__in=remove_content_units))\n", "issue": "docs should not use underscores in http headers for auth\n**Version**\r\nany\r\n\r\n**Describe the bug**\r\nhttps://docs.pulpproject.org/pulpcore/authentication/webserver.html#webserver-auth-with-reverse-proxy says:\r\n> With nginx providing authentication, all it can do is pass REMOTE_USER (or similar name) to the application webserver, i.e. gunicorn. You can pass the header as part of the proxy request in nginx with a config line like:\r\n>     \r\n>    proxy_set_header REMOTE_USER $remote_user;\r\n\r\nBut since gunicorn 22.0 (more precisely https://github.com/benoitc/gunicorn/commit/72b8970dbf2bf3444eb2e8b12aeff1a3d5922a9a/  https://github.com/benoitc/gunicorn/issues/2799) headers with underscores are forbidden by default.\r\n\r\nIf the docs would use a dash, so `proxy_set_header REMOTE-USER \u2026` things would work :)\r\n\r\n**Additional context**\r\nGrant made me file this, and I did not want to post a screenshot of our colorful conversation ;)\n", "before_files": [{"content": "from gettext import gettext as _\nfrom logging import getLogger\n\nfrom django.db import transaction\n\nfrom pulpcore.app import models, serializers\n\nlog = getLogger(__name__)\n\n\ndef delete(repo_id):\n    \"\"\"\n    Delete a :class:`~pulpcore.app.models.Repository`\n\n    Args:\n        repo_id (int): The name of the repository to be deleted\n    \"\"\"\n\n    models.Repository.objects.filter(pk=repo_id).delete()\n\n\ndef update(repo_id, partial=True, data=None):\n    \"\"\"\n    Updates a :class:`~pulpcore.app.models.Repository`\n\n    Args:\n        repo_id (int): The id of the repository to be updated\n        partial (bool): Boolean to allow partial updates. If set to False, values for all\n                        required fields must be passed or a validation error will be raised.\n                        Defaults to True\n        data (QueryDict): dict of attributes to change and their new values; if None, no attempt to\n                     update the repository object will be made\n    \"\"\"\n    instance = models.Repository.objects.get(pk=repo_id)\n    serializer = serializers.RepositorySerializer(instance, data=data, partial=partial)\n    serializer.is_valid(raise_exception=True)\n    serializer.save()\n\n\ndef delete_version(pk):\n    \"\"\"\n    Delete a repository version by squashing its changes with the next newer version. This ensures\n    that the content set for each version stays the same.\n\n    There must be a newer version to squash into. If we deleted the latest version, the next content\n    change would create a new one of the same number, which would violate the immutability\n    guarantee.\n\n    Args:\n        pk (int): the primary key for a RepositoryVersion to delete\n\n    Raises:\n        models.RepositoryVersion.DoesNotExist: if there is not a newer version to squash into.\n            TODO: something more friendly\n    \"\"\"\n    with transaction.atomic():\n        try:\n            version = models.RepositoryVersion.objects.get(pk=pk)\n        except models.RepositoryVersion.DoesNotExist:\n            log.info(_('The repository version was not found. Nothing to do.'))\n            return\n\n        log.info(_('Deleting and squashing version %(v)d of repository %(r)s'),\n                 {'v': version.number, 'r': version.repository.name})\n\n        version.delete()\n\n\ndef add_and_remove(repository_pk, add_content_units, remove_content_units, base_version_pk=None):\n    \"\"\"\n    Create a new repository version by adding and then removing content units.\n\n    Args:\n        repository_pk (int): The primary key for a Repository for which a new Repository Version\n            should be created.\n        add_content_units (list): List of PKs for :class:`~pulpcore.app.models.Content` that\n            should be added to the previous Repository Version for this Repository.\n        remove_content_units (list): List of PKs for:class:`~pulpcore.app.models.Content` that\n            should be removed from the previous Repository Version for this Repository.\n        base_version_pk (int): the primary key for a RepositoryVersion whose content will be used\n            as the initial set of content for our new RepositoryVersion\n    \"\"\"\n    repository = models.Repository.objects.get(pk=repository_pk)\n\n    if base_version_pk:\n        base_version = models.RepositoryVersion.objects.get(pk=base_version_pk)\n    else:\n        base_version = None\n\n    if '*' in remove_content_units:\n        latest = models.RepositoryVersion.latest(repository)\n        remove_content_units = latest.content.values_list('pk', flat=True)\n\n    with models.RepositoryVersion.create(repository, base_version=base_version) as new_version:\n        new_version.remove_content(models.Content.objects.filter(pk__in=remove_content_units))\n        new_version.add_content(models.Content.objects.filter(pk__in=add_content_units))\n", "path": "pulpcore/app/tasks/repository.py"}], "after_files": [{"content": "from gettext import gettext as _\nfrom logging import getLogger\n\nfrom django.db import transaction\n\nfrom pulpcore.app import models, serializers\n\nlog = getLogger(__name__)\n\n\ndef delete(repo_id):\n    \"\"\"\n    Delete a :class:`~pulpcore.app.models.Repository`\n\n    Args:\n        repo_id (int): The name of the repository to be deleted\n    \"\"\"\n\n    models.Repository.objects.filter(pk=repo_id).delete()\n\n\ndef update(repo_id, partial=True, data=None):\n    \"\"\"\n    Updates a :class:`~pulpcore.app.models.Repository`\n\n    Args:\n        repo_id (int): The id of the repository to be updated\n        partial (bool): Boolean to allow partial updates. If set to False, values for all\n                        required fields must be passed or a validation error will be raised.\n                        Defaults to True\n        data (QueryDict): dict of attributes to change and their new values; if None, no attempt to\n                     update the repository object will be made\n    \"\"\"\n    instance = models.Repository.objects.get(pk=repo_id)\n    serializer = serializers.RepositorySerializer(instance, data=data, partial=partial)\n    serializer.is_valid(raise_exception=True)\n    serializer.save()\n\n\ndef delete_version(pk):\n    \"\"\"\n    Delete a repository version by squashing its changes with the next newer version. This ensures\n    that the content set for each version stays the same.\n\n    There must be a newer version to squash into. If we deleted the latest version, the next content\n    change would create a new one of the same number, which would violate the immutability\n    guarantee.\n\n    Args:\n        pk (int): the primary key for a RepositoryVersion to delete\n\n    Raises:\n        models.RepositoryVersion.DoesNotExist: if there is not a newer version to squash into.\n            TODO: something more friendly\n    \"\"\"\n    with transaction.atomic():\n        try:\n            version = models.RepositoryVersion.objects.get(pk=pk)\n        except models.RepositoryVersion.DoesNotExist:\n            log.info(_('The repository version was not found. Nothing to do.'))\n            return\n\n        log.info(_('Deleting and squashing version %(v)d of repository %(r)s'),\n                 {'v': version.number, 'r': version.repository.name})\n\n        version.delete()\n\n\ndef add_and_remove(repository_pk, add_content_units, remove_content_units, base_version_pk=None):\n    \"\"\"\n    Create a new repository version by adding and then removing content units.\n\n    Args:\n        repository_pk (int): The primary key for a Repository for which a new Repository Version\n            should be created.\n        add_content_units (list): List of PKs for :class:`~pulpcore.app.models.Content` that\n            should be added to the previous Repository Version for this Repository.\n        remove_content_units (list): List of PKs for:class:`~pulpcore.app.models.Content` that\n            should be removed from the previous Repository Version for this Repository.\n        base_version_pk (int): the primary key for a RepositoryVersion whose content will be used\n            as the initial set of content for our new RepositoryVersion\n    \"\"\"\n    repository = models.Repository.objects.get(pk=repository_pk)\n\n    if base_version_pk:\n        base_version = models.RepositoryVersion.objects.get(pk=base_version_pk)\n    else:\n        base_version = None\n\n    if '*' in remove_content_units:\n        latest = models.RepositoryVersion.latest(repository)\n        if latest:\n            remove_content_units = latest.content.values_list('pk', flat=True)\n        else:\n            remove_content_units = []\n\n    with models.RepositoryVersion.create(repository, base_version=base_version) as new_version:\n        new_version.remove_content(models.Content.objects.filter(pk__in=remove_content_units))\n        new_version.add_content(models.Content.objects.filter(pk__in=add_content_units))\n", "path": "pulpcore/app/tasks/repository.py"}]}