prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Better avatar uploads caching
  Right now, we cache resizes on the server, but these responses are unable to be cached by any browser or proxy.
  
  To fix this we need to:
  - [ ] Send a proper `Cache-Control` header that tells the browser it's allowed to cache it. Something like `Cache-Control: max-age=315360000`
  - [ ] Urls that don't change, so they _can_ be cached. Right now, uploaded avatars reuse the same `UserAvatar.ident`, which means we get the same url even if we change the file. So we can't cache.
  - [ ] Remove `Set-Cookie` header on response (this may be tricky but @mattrobenolt can help). `Set-Cookie` header kills all caching.
  - [ ] Remove `Vary` header. We don't need to Vary on anything, and right now it's `Vary: Accept-Encoding, Cookie`, which basically makes caching useless. (this may be tricky as well, but @mattrobenolt can help)
  
  @macqueen 
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/sentry/middleware/locale.py`
  Content:
  ```
  1 """
  2 sentry.middleware.locale
  3 ~~~~~~~~~~~~~~~~~~~~~~~~
  4 
  5 :copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
  6 :license: BSD, see LICENSE for more details.
  7 """
  8 
  9 from __future__ import absolute_import
  10 
  11 import pytz
  12 
  13 from django.middleware.locale import LocaleMiddleware
  14 
  15 from sentry.models import UserOption
  16 from sentry.utils.safe import safe_execute
  17 
  18 
  19 class SentryLocaleMiddleware(LocaleMiddleware):
  20     def process_request(self, request):
  21         # No locale for static media
  22         # This avoids touching user session, which means we avoid
  23         # setting `Vary: Cookie` as a response header which will
  24         # break HTTP caching entirely.
  25         self.__is_static = request.path_info[:9] == '/_static/'
  26         if self.__is_static:
  27             return
  28 
  29         safe_execute(self.load_user_conf, request,
  30                      _with_transaction=False)
  31 
  32         super(SentryLocaleMiddleware, self).process_request(request)
  33 
  34     def load_user_conf(self, request):
  35         if not request.user.is_authenticated():
  36             return
  37 
  38         language = UserOption.objects.get_value(
  39             user=request.user, project=None, key='language', default=None)
  40         if language:
  41             request.session['django_language'] = language
  42 
  43         timezone = UserOption.objects.get_value(
  44             user=request.user, project=None, key='timezone', default=None)
  45         if timezone:
  46             request.timezone = pytz.timezone(timezone)
  47 
  48     def process_response(self, request, response):
  49         # If static bound, we don't want to run the normal process_response since this
  50         # adds an extra `Vary: Accept-Language`. Static files don't need this and is
  51         # less effective for caching.
  52         try:
  53             if self.__is_static:
  54                 return response
  55         except AttributeError:
  56             # catch ourselves in case __is_static never got set.
  57             # It's possible that process_request never ran.
  58             pass
  59         return super(SentryLocaleMiddleware, self).process_response(request, response)
  60
  ```
  
  Path: `src/sentry/api/endpoints/useravatar.py`
  Content:
  ```
  1 from __future__ import absolute_import
  2 
  3 from PIL import Image
  4 
  5 from django.conf import settings
  6 
  7 from rest_framework import status
  8 from rest_framework.response import Response
  9 
  10 from sentry.api.bases.user import UserEndpoint
  11 from sentry.api.serializers import serialize
  12 from sentry.models import UserAvatar, File
  13 from sentry.utils.compat import StringIO
  14 
  15 
  16 MIN_DIMENSION = 256
  17 
  18 MAX_DIMENSION = 1024
  19 
  20 
  21 class UserAvatarEndpoint(UserEndpoint):
  22     FILE_TYPE = 'avatar.file'
  23 
  24     def get(self, request, user):
  25         return Response(serialize(user, request.user))
  26 
  27     def is_valid_size(self, width, height):
  28         if width != height:
  29             return False
  30         if width < MIN_DIMENSION:
  31             return False
  32         if width > MAX_DIMENSION:
  33             return False
  34         return True
  35 
  36     def put(self, request, user):
  37         if user != request.user:
  38             return Response(status=status.HTTP_403_FORBIDDEN)
  39 
  40         photo_string = request.DATA.get('avatar_photo')
  41         photo = None
  42         if photo_string:
  43             photo_string = photo_string.decode('base64')
  44             if len(photo_string) > settings.SENTRY_MAX_AVATAR_SIZE:
  45                 return Response(status=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE)
  46             with Image.open(StringIO(photo_string)) as img:
  47                 width, height = img.size
  48                 if not self.is_valid_size(width, height):
  49                     return Response(status=status.HTTP_400_BAD_REQUEST)
  50             file_name = '%s.png' % user.id
  51             photo = File.objects.create(name=file_name, type=self.FILE_TYPE)
  52             photo.putfile(StringIO(photo_string))
  53 
  54         avatar, _ = UserAvatar.objects.get_or_create(user=user)
  55         if avatar.file and photo:
  56             avatar.file.delete()
  57             avatar.clear_cached_photos()
  58         if photo:
  59             avatar.file = photo
  60 
  61         avatar_type = request.DATA.get('avatar_type')
  62 
  63         if not avatar.file and avatar_type == 'upload':
  64             return Response(status=status.HTTP_400_BAD_REQUEST)
  65 
  66         if avatar_type:
  67             try:
  68                 avatar.avatar_type = [i for i, n in UserAvatar.AVATAR_TYPES if n == avatar_type][0]
  69             except IndexError:
  70                 return Response(status=status.HTTP_400_BAD_REQUEST)
  71 
  72         avatar.save()
  73         return Response(serialize(user, request.user))
  74
  ```
  
  Path: `src/sentry/web/frontend/user_avatar.py`
  Content:
  ```
  1 from __future__ import absolute_import
  2 
  3 from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound
  4 from django.views.generic import View
  5 
  6 from sentry.models import UserAvatar
  7 
  8 
  9 class UserAvatarPhotoView(View):
  10 
  11     def get_file_name(self, user):
  12         return '%s.png' % user.id
  13 
  14     def get(self, request, *args, **kwargs):
  15         avatar_id = kwargs['avatar_id']
  16         try:
  17             avatar = UserAvatar.objects.get(ident=avatar_id)
  18         except UserAvatar.DoesNotExist:
  19             return HttpResponseNotFound()
  20 
  21         photo = avatar.file
  22         if not photo:
  23             return HttpResponseNotFound()
  24 
  25         size = request.GET.get('s')
  26         photo_file = photo.getfile()
  27         if size:
  28             try:
  29                 size = int(size)
  30             except ValueError:
  31                 return HttpResponseBadRequest()
  32             else:
  33                 photo_file = avatar.get_cached_photo(size)
  34         return HttpResponse(photo_file, content_type='image/png')
  35
  ```
  --- 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/src/sentry/api/endpoints/useravatar.py b/src/sentry/api/endpoints/useravatar.py
  --- a/src/sentry/api/endpoints/useravatar.py
  +++ b/src/sentry/api/endpoints/useravatar.py
  @@ -1,5 +1,7 @@
   from __future__ import absolute_import
   
  +from uuid import uuid4
  +
   from PIL import Image
   
   from django.conf import settings
  @@ -57,6 +59,7 @@
               avatar.clear_cached_photos()
           if photo:
               avatar.file = photo
  +            avatar.ident = uuid4().hex
   
           avatar_type = request.DATA.get('avatar_type')
   
  diff --git a/src/sentry/middleware/locale.py b/src/sentry/middleware/locale.py
  --- a/src/sentry/middleware/locale.py
  +++ b/src/sentry/middleware/locale.py
  @@ -22,8 +22,9 @@
           # This avoids touching user session, which means we avoid
           # setting `Vary: Cookie` as a response header which will
           # break HTTP caching entirely.
  -        self.__is_static = request.path_info[:9] == '/_static/'
  -        if self.__is_static:
  +        self.__skip_caching = (request.path_info[:9] == '/_static/' or
  +                               request.path_info[:8] == '/avatar/')
  +        if self.__skip_caching:
               return
   
           safe_execute(self.load_user_conf, request,
  @@ -50,10 +51,10 @@
           # adds an extra `Vary: Accept-Language`. Static files don't need this and is
           # less effective for caching.
           try:
  -            if self.__is_static:
  +            if self.__skip_caching:
                   return response
           except AttributeError:
  -            # catch ourselves in case __is_static never got set.
  +            # catch ourselves in case __skip_caching never got set.
               # It's possible that process_request never ran.
               pass
           return super(SentryLocaleMiddleware, self).process_response(request, response)
  diff --git a/src/sentry/web/frontend/user_avatar.py b/src/sentry/web/frontend/user_avatar.py
  --- a/src/sentry/web/frontend/user_avatar.py
  +++ b/src/sentry/web/frontend/user_avatar.py
  @@ -4,6 +4,7 @@
   from django.views.generic import View
   
   from sentry.models import UserAvatar
  +from sentry.web.frontend.generic import FOREVER_CACHE
   
   
   class UserAvatarPhotoView(View):
  @@ -31,4 +32,7 @@
                   return HttpResponseBadRequest()
               else:
                   photo_file = avatar.get_cached_photo(size)
  -        return HttpResponse(photo_file, content_type='image/png')
  +
  +        res = HttpResponse(photo_file, content_type='image/png')
  +        res['Cache-Control'] = FOREVER_CACHE
  +        return res
  
verification_info: {"golden_diff": "diff --git a/src/sentry/api/endpoints/useravatar.py b/src/sentry/api/endpoints/useravatar.py\n--- a/src/sentry/api/endpoints/useravatar.py\n+++ b/src/sentry/api/endpoints/useravatar.py\n@@ -1,5 +1,7 @@\n from __future__ import absolute_import\n \n+from uuid import uuid4\n+\n from PIL import Image\n \n from django.conf import settings\n@@ -57,6 +59,7 @@\n             avatar.clear_cached_photos()\n         if photo:\n             avatar.file = photo\n+            avatar.ident = uuid4().hex\n \n         avatar_type = request.DATA.get('avatar_type')\n \ndiff --git a/src/sentry/middleware/locale.py b/src/sentry/middleware/locale.py\n--- a/src/sentry/middleware/locale.py\n+++ b/src/sentry/middleware/locale.py\n@@ -22,8 +22,9 @@\n         # This avoids touching user session, which means we avoid\n         # setting `Vary: Cookie` as a response header which will\n         # break HTTP caching entirely.\n-        self.__is_static = request.path_info[:9] == '/_static/'\n-        if self.__is_static:\n+        self.__skip_caching = (request.path_info[:9] == '/_static/' or\n+                               request.path_info[:8] == '/avatar/')\n+        if self.__skip_caching:\n             return\n \n         safe_execute(self.load_user_conf, request,\n@@ -50,10 +51,10 @@\n         # adds an extra `Vary: Accept-Language`. Static files don't need this and is\n         # less effective for caching.\n         try:\n-            if self.__is_static:\n+            if self.__skip_caching:\n                 return response\n         except AttributeError:\n-            # catch ourselves in case __is_static never got set.\n+            # catch ourselves in case __skip_caching never got set.\n             # It's possible that process_request never ran.\n             pass\n         return super(SentryLocaleMiddleware, self).process_response(request, response)\ndiff --git a/src/sentry/web/frontend/user_avatar.py b/src/sentry/web/frontend/user_avatar.py\n--- a/src/sentry/web/frontend/user_avatar.py\n+++ b/src/sentry/web/frontend/user_avatar.py\n@@ -4,6 +4,7 @@\n from django.views.generic import View\n \n from sentry.models import UserAvatar\n+from sentry.web.frontend.generic import FOREVER_CACHE\n \n \n class UserAvatarPhotoView(View):\n@@ -31,4 +32,7 @@\n                 return HttpResponseBadRequest()\n             else:\n                 photo_file = avatar.get_cached_photo(size)\n-        return HttpResponse(photo_file, content_type='image/png')\n+\n+        res = HttpResponse(photo_file, content_type='image/png')\n+        res['Cache-Control'] = FOREVER_CACHE\n+        return res\n", "issue": "Better avatar uploads caching\nRight now, we cache resizes on the server, but these responses are unable to be cached by any browser or proxy.\n\nTo fix this we need to:\n- [ ] Send a proper `Cache-Control` header that tells the browser it's allowed to cache it. Something like `Cache-Control: max-age=315360000`\n- [ ] Urls that don't change, so they _can_ be cached. Right now, uploaded avatars reuse the same `UserAvatar.ident`, which means we get the same url even if we change the file. So we can't cache.\n- [ ] Remove `Set-Cookie` header on response (this may be tricky but @mattrobenolt can help). `Set-Cookie` header kills all caching.\n- [ ] Remove `Vary` header. We don't need to Vary on anything, and right now it's `Vary: Accept-Encoding, Cookie`, which basically makes caching useless. (this may be tricky as well, but @mattrobenolt can help)\n\n@macqueen \n\n", "before_files": [{"content": "\"\"\"\nsentry.middleware.locale\n~~~~~~~~~~~~~~~~~~~~~~~~\n\n:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.\n:license: BSD, see LICENSE for more details.\n\"\"\"\n\nfrom __future__ import absolute_import\n\nimport pytz\n\nfrom django.middleware.locale import LocaleMiddleware\n\nfrom sentry.models import UserOption\nfrom sentry.utils.safe import safe_execute\n\n\nclass SentryLocaleMiddleware(LocaleMiddleware):\n    def process_request(self, request):\n        # No locale for static media\n        # This avoids touching user session, which means we avoid\n        # setting `Vary: Cookie` as a response header which will\n        # break HTTP caching entirely.\n        self.__is_static = request.path_info[:9] == '/_static/'\n        if self.__is_static:\n            return\n\n        safe_execute(self.load_user_conf, request,\n                     _with_transaction=False)\n\n        super(SentryLocaleMiddleware, self).process_request(request)\n\n    def load_user_conf(self, request):\n        if not request.user.is_authenticated():\n            return\n\n        language = UserOption.objects.get_value(\n            user=request.user, project=None, key='language', default=None)\n        if language:\n            request.session['django_language'] = language\n\n        timezone = UserOption.objects.get_value(\n            user=request.user, project=None, key='timezone', default=None)\n        if timezone:\n            request.timezone = pytz.timezone(timezone)\n\n    def process_response(self, request, response):\n        # If static bound, we don't want to run the normal process_response since this\n        # adds an extra `Vary: Accept-Language`. Static files don't need this and is\n        # less effective for caching.\n        try:\n            if self.__is_static:\n                return response\n        except AttributeError:\n            # catch ourselves in case __is_static never got set.\n            # It's possible that process_request never ran.\n            pass\n        return super(SentryLocaleMiddleware, self).process_response(request, response)\n", "path": "src/sentry/middleware/locale.py"}, {"content": "from __future__ import absolute_import\n\nfrom PIL import Image\n\nfrom django.conf import settings\n\nfrom rest_framework import status\nfrom rest_framework.response import Response\n\nfrom sentry.api.bases.user import UserEndpoint\nfrom sentry.api.serializers import serialize\nfrom sentry.models import UserAvatar, File\nfrom sentry.utils.compat import StringIO\n\n\nMIN_DIMENSION = 256\n\nMAX_DIMENSION = 1024\n\n\nclass UserAvatarEndpoint(UserEndpoint):\n    FILE_TYPE = 'avatar.file'\n\n    def get(self, request, user):\n        return Response(serialize(user, request.user))\n\n    def is_valid_size(self, width, height):\n        if width != height:\n            return False\n        if width < MIN_DIMENSION:\n            return False\n        if width > MAX_DIMENSION:\n            return False\n        return True\n\n    def put(self, request, user):\n        if user != request.user:\n            return Response(status=status.HTTP_403_FORBIDDEN)\n\n        photo_string = request.DATA.get('avatar_photo')\n        photo = None\n        if photo_string:\n            photo_string = photo_string.decode('base64')\n            if len(photo_string) > settings.SENTRY_MAX_AVATAR_SIZE:\n                return Response(status=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE)\n            with Image.open(StringIO(photo_string)) as img:\n                width, height = img.size\n                if not self.is_valid_size(width, height):\n                    return Response(status=status.HTTP_400_BAD_REQUEST)\n            file_name = '%s.png' % user.id\n            photo = File.objects.create(name=file_name, type=self.FILE_TYPE)\n            photo.putfile(StringIO(photo_string))\n\n        avatar, _ = UserAvatar.objects.get_or_create(user=user)\n        if avatar.file and photo:\n            avatar.file.delete()\n            avatar.clear_cached_photos()\n        if photo:\n            avatar.file = photo\n\n        avatar_type = request.DATA.get('avatar_type')\n\n        if not avatar.file and avatar_type == 'upload':\n            return Response(status=status.HTTP_400_BAD_REQUEST)\n\n        if avatar_type:\n            try:\n                avatar.avatar_type = [i for i, n in UserAvatar.AVATAR_TYPES if n == avatar_type][0]\n            except IndexError:\n                return Response(status=status.HTTP_400_BAD_REQUEST)\n\n        avatar.save()\n        return Response(serialize(user, request.user))\n", "path": "src/sentry/api/endpoints/useravatar.py"}, {"content": "from __future__ import absolute_import\n\nfrom django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound\nfrom django.views.generic import View\n\nfrom sentry.models import UserAvatar\n\n\nclass UserAvatarPhotoView(View):\n\n    def get_file_name(self, user):\n        return '%s.png' % user.id\n\n    def get(self, request, *args, **kwargs):\n        avatar_id = kwargs['avatar_id']\n        try:\n            avatar = UserAvatar.objects.get(ident=avatar_id)\n        except UserAvatar.DoesNotExist:\n            return HttpResponseNotFound()\n\n        photo = avatar.file\n        if not photo:\n            return HttpResponseNotFound()\n\n        size = request.GET.get('s')\n        photo_file = photo.getfile()\n        if size:\n            try:\n                size = int(size)\n            except ValueError:\n                return HttpResponseBadRequest()\n            else:\n                photo_file = avatar.get_cached_photo(size)\n        return HttpResponse(photo_file, content_type='image/png')\n", "path": "src/sentry/web/frontend/user_avatar.py"}], "after_files": [{"content": "\"\"\"\nsentry.middleware.locale\n~~~~~~~~~~~~~~~~~~~~~~~~\n\n:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.\n:license: BSD, see LICENSE for more details.\n\"\"\"\n\nfrom __future__ import absolute_import\n\nimport pytz\n\nfrom django.middleware.locale import LocaleMiddleware\n\nfrom sentry.models import UserOption\nfrom sentry.utils.safe import safe_execute\n\n\nclass SentryLocaleMiddleware(LocaleMiddleware):\n    def process_request(self, request):\n        # No locale for static media\n        # This avoids touching user session, which means we avoid\n        # setting `Vary: Cookie` as a response header which will\n        # break HTTP caching entirely.\n        self.__skip_caching = (request.path_info[:9] == '/_static/' or\n                               request.path_info[:8] == '/avatar/')\n        if self.__skip_caching:\n            return\n\n        safe_execute(self.load_user_conf, request,\n                     _with_transaction=False)\n\n        super(SentryLocaleMiddleware, self).process_request(request)\n\n    def load_user_conf(self, request):\n        if not request.user.is_authenticated():\n            return\n\n        language = UserOption.objects.get_value(\n            user=request.user, project=None, key='language', default=None)\n        if language:\n            request.session['django_language'] = language\n\n        timezone = UserOption.objects.get_value(\n            user=request.user, project=None, key='timezone', default=None)\n        if timezone:\n            request.timezone = pytz.timezone(timezone)\n\n    def process_response(self, request, response):\n        # If static bound, we don't want to run the normal process_response since this\n        # adds an extra `Vary: Accept-Language`. Static files don't need this and is\n        # less effective for caching.\n        try:\n            if self.__skip_caching:\n                return response\n        except AttributeError:\n            # catch ourselves in case __skip_caching never got set.\n            # It's possible that process_request never ran.\n            pass\n        return super(SentryLocaleMiddleware, self).process_response(request, response)\n", "path": "src/sentry/middleware/locale.py"}, {"content": "from __future__ import absolute_import\n\nfrom uuid import uuid4\n\nfrom PIL import Image\n\nfrom django.conf import settings\n\nfrom rest_framework import status\nfrom rest_framework.response import Response\n\nfrom sentry.api.bases.user import UserEndpoint\nfrom sentry.api.serializers import serialize\nfrom sentry.models import UserAvatar, File\nfrom sentry.utils.compat import StringIO\n\n\nMIN_DIMENSION = 256\n\nMAX_DIMENSION = 1024\n\n\nclass UserAvatarEndpoint(UserEndpoint):\n    FILE_TYPE = 'avatar.file'\n\n    def get(self, request, user):\n        return Response(serialize(user, request.user))\n\n    def is_valid_size(self, width, height):\n        if width != height:\n            return False\n        if width < MIN_DIMENSION:\n            return False\n        if width > MAX_DIMENSION:\n            return False\n        return True\n\n    def put(self, request, user):\n        if user != request.user:\n            return Response(status=status.HTTP_403_FORBIDDEN)\n\n        photo_string = request.DATA.get('avatar_photo')\n        photo = None\n        if photo_string:\n            photo_string = photo_string.decode('base64')\n            if len(photo_string) > settings.SENTRY_MAX_AVATAR_SIZE:\n                return Response(status=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE)\n            with Image.open(StringIO(photo_string)) as img:\n                width, height = img.size\n                if not self.is_valid_size(width, height):\n                    return Response(status=status.HTTP_400_BAD_REQUEST)\n            file_name = '%s.png' % user.id\n            photo = File.objects.create(name=file_name, type=self.FILE_TYPE)\n            photo.putfile(StringIO(photo_string))\n\n        avatar, _ = UserAvatar.objects.get_or_create(user=user)\n        if avatar.file and photo:\n            avatar.file.delete()\n            avatar.clear_cached_photos()\n        if photo:\n            avatar.file = photo\n            avatar.ident = uuid4().hex\n\n        avatar_type = request.DATA.get('avatar_type')\n\n        if not avatar.file and avatar_type == 'upload':\n            return Response(status=status.HTTP_400_BAD_REQUEST)\n\n        if avatar_type:\n            try:\n                avatar.avatar_type = [i for i, n in UserAvatar.AVATAR_TYPES if n == avatar_type][0]\n            except IndexError:\n                return Response(status=status.HTTP_400_BAD_REQUEST)\n\n        avatar.save()\n        return Response(serialize(user, request.user))\n", "path": "src/sentry/api/endpoints/useravatar.py"}, {"content": "from __future__ import absolute_import\n\nfrom django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound\nfrom django.views.generic import View\n\nfrom sentry.models import UserAvatar\nfrom sentry.web.frontend.generic import FOREVER_CACHE\n\n\nclass UserAvatarPhotoView(View):\n\n    def get_file_name(self, user):\n        return '%s.png' % user.id\n\n    def get(self, request, *args, **kwargs):\n        avatar_id = kwargs['avatar_id']\n        try:\n            avatar = UserAvatar.objects.get(ident=avatar_id)\n        except UserAvatar.DoesNotExist:\n            return HttpResponseNotFound()\n\n        photo = avatar.file\n        if not photo:\n            return HttpResponseNotFound()\n\n        size = request.GET.get('s')\n        photo_file = photo.getfile()\n        if size:\n            try:\n                size = int(size)\n            except ValueError:\n                return HttpResponseBadRequest()\n            else:\n                photo_file = avatar.get_cached_photo(size)\n\n        res = HttpResponse(photo_file, content_type='image/png')\n        res['Cache-Control'] = FOREVER_CACHE\n        return res\n", "path": "src/sentry/web/frontend/user_avatar.py"}]}