Отправьте «304 Not Modified» для изображений, хранящихся в хранилище данных - PullRequest
5 голосов
/ 01 мая 2010

Я сохраняю загруженные пользователем изображения в хранилище данных Google App Engine как db.Blob, как предложено в документах . Затем я подаю эти изображения на /images/<id>.jpg.

Сервер всегда отправляет ответ 200 OK, что означает, что браузер должен загружать одно и то же изображение несколько раз (== медленнее) и что сервер должен отправлять одно и то же изображение несколько раз (== дороже).

Поскольку большинство этих изображений, вероятно, никогда не изменятся, я бы хотел отправить ответ 304 Not Modified. Я думаю о том, чтобы вычислить какой-то хэш изображения, когда пользователь загружает его, а затем использовать его, чтобы узнать, есть ли у пользователя это изображение (возможно, отправить хэш как Etag?)

Я нашел этот ответ и этот ответ , который довольно хорошо объясняет логику, но у меня есть 2 вопроса:

  1. Можно ли отправить Etag в Google App Engine?
  2. Кто-нибудь реализовал такую ​​логику и / или есть ли фрагмент кода?

Ответы [ 4 ]

8 голосов
/ 01 мая 2010

Bloggart использует эту технику. Взгляните на этот пост .

class StaticContentHandler(webapp.RequestHandler):
  def output_content(self, content, serve=True):
    self.response.headers['Content-Type'] = content.content_type
    last_modified = content.last_modified.strftime(HTTP_DATE_FMT)
    self.response.headers['Last-Modified'] = last_modified
    self.response.headers['ETag'] = '"%s"' % (content.etag,)
    if serve:
      self.response.out.write(content.body)
    else:
      self.response.set_status(304)

  def get(self, path):
    content = get(path)
    if not content:
      self.error(404)
      return

    serve = True
    if 'If-Modified-Since' in self.request.headers:
      last_seen = datetime.datetime.strptime(
          self.request.headers['If-Modified-Since'],
          HTTP_DATE_FMT)
      if last_seen >= content.last_modified.replace(microsecond=0):
        serve = False
    if 'If-None-Match' in self.request.headers:
      etags = [x.strip('" ')
               for x in self.request.headers['If-None-Match'].split(',')]
      if content.etag in etags:
        serve = False
    self.output_content(content, serve)
0 голосов
/ 28 декабря 2012

почему код использует это:

 self.response.headers['ETag'] = '"%s"' % (content.etag,)

вместо этого:

 self.response.headers['ETag'] = '"%s"' % content.etag

Я думаю, что это то же самое и будет использовать второе, если кто-то не объяснит причины.

0 голосов
/ 21 октября 2010

Кстати, благодаря webob, webapp.RequestHandler предоставляет простой способ проверки If-None-Match.

if etag in self.request.if_none_match:
    pass # do something
0 голосов
/ 02 мая 2010

Здесь может быть более простое решение. Это требует, чтобы вы никогда не перезаписывали данные, связанные с каким-либо идентификатором, например, изменение изображения приведет к созданию нового идентификатора (и, следовательно, нового URL).

Просто установите заголовок Expires из вашего обработчика запросов на далекое будущее, например, сейчас + год. Это приведет к тому, что клиенты будут кэшировать изображение и не будут запрашивать обновление, пока не наступит это время.

У этого подхода есть некоторые компромиссы, такие как обеспечение того, что новые URL-адреса внедряются при изменении изображений, поэтому вы должны решить сами. Jbochi предлагает другую альтернативу, которая добавляет больше логики в обработчик запросов изображения.

...