title: Using django-storages and the s3boto backend, How do I add caching info to request headers for an image so browser will cache image?
body: <p>I am using the s3boto backend, not the s3 backend.</p>
  
  <p>In the <a href="http://django-storages.readthedocs.org/en/latest/backends/amazon-S3.html" rel="noreferrer">django-storages docs</a> it says to specify the AWS_HEADERS variable on your 
  settings.py file:</p>
  
  <blockquote>
    <p>AWS_HEADERS (optional)</p>
    
    <p>If you’d like to set headers sent with each file of the storage:</p>
  </blockquote>
  
  <pre><code># see http://developer.yahoo.com/performance/rules.html#expires
  AWS_HEADERS = {
  'Expires': 'Thu, 15 Apr 2010 20:00:00 GMT',
  'Cache-Control': 'max-age=86400',
  }
  </code></pre>
  
  <p>This is not working for me.</p>
  
  <p>Here is my model:</p>
  
  <pre><code>class Photo(models.Model):
      """
          docstring for Photo
          represents a single photo.. a photo can have many things associated to it like
          a project, a portfolio, etc...
      """
  
      def image_upload_to(instance, filename):
          today = datetime.datetime.today()
          return 'user_uploads/%s/%s/%s/%s/%s/%s/original/%s' % (instance.owner.username, today.year, today.month, today.day, today.hour, today.minute, filename)
  
      def thumb_upload_to(instance, filename):
          today = datetime.datetime.today()
          return 'user_uploads/%s/%s/%s/%s/%s/%s/thumb/%s' % (instance.owner.username, today.year, today.month, today.day, today.hour, today.minute, filename)
  
      def medium_upload_to(instance, filename):
          today = datetime.datetime.today()
          return 'user_uploads/%s/%s/%s/%s/%s/%s/medium/%s' % (instance.owner.username, today.year, today.month, today.day, today.hour, today.minute, filename)
  
  
  
      owner = models.ForeignKey(User)
      # take out soon
      projects = models.ManyToManyField('Project', through='Connection', blank=True)
      image = models.ImageField(upload_to=image_upload_to)
      thumb = ThumbnailerImageField(upload_to=thumb_upload_to, resize_source=dict(size=(102,102), crop='center'),)
      medium = ThumbnailerImageField(upload_to=medium_upload_to, resize_source=dict(size=(700,525),))
      title = models.CharField(blank=True, max_length=300)
      caption = models.TextField(blank=True)
      can_view_full_res = models.BooleanField(default=False)
      is_portfolio = models.BooleanField(default=False)
      created_time = models.DateTimeField(blank=False, auto_now_add=True)
      disabled = models.DateTimeField(blank=True, null=True, auto_now_add=False)
      cost = models.FloatField(default=0)
      rating = models.IntegerField(default=0)
      mature_content = models.BooleanField(default=False)
      objects = ViewableManager()
  
      def get_absolute_url(self):
          return "/m/photo/%i/" % self.pk
  
      def get_prev_by_time(self):
          get_prev = Photo.objects.order_by('-created_time').filter(created_time__lt=self.created_time)
          try:
              return get_prev[0]
          except IndexError:
              return None
  
      def get_next_by_time(self):
          get_next = Photo.objects.order_by('created_time').filter(created_time__gt=self.created_time)
          try:
              return get_next[0]
          except IndexError:
              return None
  
      def __unicode__(self):
          return(self.title)
  </code></pre>
  
  <p>This is what is on my template where I have the image... </p>
  
  <pre><code>&lt;img class='shadow' src='{{ object.medium.url }}'&gt;
  </code></pre>
  
  <p>Here are the request and response headers:</p>
  
  <pre><code>Request URL:https://MY_UPLOAD_CONTAINER.s3.amazonaws.com/user_uploads/travismillward/2012/3/23/3/0/medium/_0677866898.jpg?Signature=s%2ByKsWDxrDJbyeVHd%2BDS3JlByts%3D&amp;Expires=1332529522&amp;AWSAccessKeyId=MY_ACCESS_KEYID
  Request Method:GET
  Status Code:200 OK
  Request Headersview parsed
  GET /user_uploads/travismillward/2012/3/23/3/0/medium/_0677866898.jpg?Signature=s%2ByKsWDxrDJbyeVHd%2BDS3JlByts%3D&amp;Expires=1332529522&amp;AWSAccessKeyId=MY_ACCESS_KEYID HTTP/1.1
  Host: MY_UPLOAD_CONTAINER.s3.amazonaws.com
  Connection: keep-alive
  Cache-Control: max-age=0
  User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.83 Safari/535.11
  Accept: */*
  Referer: http://localhost:8000/m/photo/1/
  Accept-Encoding: gzip,deflate,sdch
  Accept-Language: en-US,en;q=0.8
  Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
  Query String Parametersview URL encoded
  Signature:s+yKsWDxrDJbyeVHd+DS3JlByts=
  Expires:1332529522
  AWSAccessKeyId:MY_ACCESS_KEYID
  Response Headersview parsed
  HTTP/1.1 200 OK
  x-amz-id-2: wOWRRDi5TItAdiYSPf8X4z4I4v5/Zu8XLhwlxmZa8w8w1Jph8WQkenihVJI/ZKnV
  x-amz-request-id: THE_X_AMZ_REQUEST_ID
  Date: Fri, 23 Mar 2012 18:05:24 GMT
  Cache-Control: max-age=86400
  Last-Modified: Fri, 23 Mar 2012 09:00:13 GMT
  ETag: "6e34e718a349e0bf9e4aefc1afad3d7d"
  Accept-Ranges: bytes
  Content-Type: image/jpeg
  Content-Length: 91600
  Server: AmazonS3
  </code></pre>
  
  <p>When I paste the path to the image into the address bar it WILL cache the image and give me a 304... Here are those request and response headers:</p>
  
  <pre><code>Request URL:https://MY_UPLOAD_CONTAINER.s3.amazonaws.com/user_uploads/travismillward/2012/3/23/3/0/medium/_0677866898.jpg?Signature=evsDZiw3QGsjPacG4CHn6Ji2dDA%3D&amp;Expires=1332528782&amp;AWSAccessKeyId=MY_ACCESS_KEYID
  Request Method:GET
  Status Code:304 Not Modified
  Request Headersview parsed
  GET /user_uploads/travismillward/2012/3/23/3/0/medium/_0677866898.jpg?Signature=evsDZiw3QGsjPacG4CHn6Ji2dDA%3D&amp;Expires=1332528782&amp;AWSAccessKeyId=MY_ACCESS_KEYID HTTP/1.1
  Host: MY_UPLOAD_CONTAINER.s3.amazonaws.com
  Connection: keep-alive
  Cache-Control: max-age=0
  User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.83 Safari/535.11
  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  Referer: http://localhost:8000/m/photo/1/
  Accept-Encoding: gzip,deflate,sdch
  Accept-Language: en-US,en;q=0.8
  Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
  If-None-Match: "6e34e718a349e0bf9e4aefc1afad3d7d"
  If-Modified-Since: Fri, 23 Mar 2012 09:00:13 GMT
  Query String Parametersview URL encoded
  Signature:evsDZiw3QGsjPacG4CHn6Ji2dDA=
  Expires:1332528782
  AWSAccessKeyId:MY_ACCESS_KEYID
  Response Headersview parsed
  HTTP/1.1 304 Not Modified
  x-amz-id-2: LfdHa10SdWnx4UH1rc62NfUDeiNVGRzBX73CR+6GDrXJgv9zo+vyQ9A3HCr1YLVa
  x-amz-request-id: THE_X_AMZ_REQUEST_ID
  Date: Fri, 23 Mar 2012 18:01:16 GMT
  Last-Modified: Fri, 23 Mar 2012 09:00:13 GMT
  ETag: "6e34e718a349e0bf9e4aefc1afad3d7d"
  Server: AmazonS3
  </code></pre>