Use Nginx ETag algo

There is a situation where the ETag can be generated by Nginx,
but then used by Django: when the user starts editing a layer,
the js client will send the ETag received from Nginx to uMap
as value to check is there is an editing conflict.
This commit is contained in:
Yohan Boniface 2023-02-25 21:50:39 +01:00
parent a8dee3fa07
commit 2bd4008f97

View file

@ -718,8 +718,11 @@ class GZipMixin(object):
def etag(self): def etag(self):
path = self.path() path = self.path()
with open(path, mode='rb') as f: # Align ETag with Nginx one, because when using X-Send-File, If-None-Match
return '"%s"' % hashlib.md5(f.read()).hexdigest() # and If-Modified-Since are handled by Nginx.
# https://github.com/nginx/nginx/blob/4ace957c4e08bcbf9ef5e9f83b8e43458bead77f/src/http/ngx_http_core_module.c#L1675-L1709
statobj = os.stat(path)
return 'W/"%x-%x"' % (int(statobj.st_mtime), statobj.st_size)
class DataLayerView(GZipMixin, BaseDetailView): class DataLayerView(GZipMixin, BaseDetailView):
@ -742,8 +745,8 @@ class DataLayerView(GZipMixin, BaseDetailView):
content_type='application/json' content_type='application/json'
) )
response["Last-Modified"] = http_date(statobj.st_mtime) response["Last-Modified"] = http_date(statobj.st_mtime)
response['ETag'] = '"%s"' % hashlib.md5(force_bytes(response.content)).hexdigest() # noqa response['ETag'] = self.etag()
response['Content-Length'] = len(response.content) response['Content-Length'] = statobj.st_size
response['Vary'] = 'Accept-Encoding' response['Vary'] = 'Accept-Encoding'
if path.endswith(self.EXT): if path.endswith(self.EXT):
response['Content-Encoding'] = 'gzip' response['Content-Encoding'] = 'gzip'
@ -765,6 +768,7 @@ class DataLayerCreate(FormLessEditMixin, GZipMixin, CreateView):
def form_valid(self, form): def form_valid(self, form):
form.instance.map = self.kwargs['map_inst'] form.instance.map = self.kwargs['map_inst']
self.object = form.save() self.object = form.save()
# Simple response with only metadatas (including new id)
response = simple_json_response(**self.object.metadata) response = simple_json_response(**self.object.metadata)
response['ETag'] = self.etag() response['ETag'] = self.etag()
return response return response
@ -776,6 +780,8 @@ class DataLayerUpdate(FormLessEditMixin, GZipMixin, UpdateView):
def form_valid(self, form): def form_valid(self, form):
self.object = form.save() self.object = form.save()
# Simple response with only metadatas (client should not reload all data
# on save)
response = simple_json_response(**self.object.metadata) response = simple_json_response(**self.object.metadata)
response['ETag'] = self.etag() response['ETag'] = self.etag()
return response return response