Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
7a40fef1
Kaydet (Commit)
7a40fef1
authored
Haz 05, 2015
tarafından
Denis Cornehl
Kaydeden (comit)
Tim Graham
Agu 15, 2015
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #24935 -- Refactored common conditional GET handling.
üst
1f7b25c1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
130 additions
and
109 deletions
+130
-109
common.py
django/middleware/common.py
+9
-14
http.py
django/middleware/http.py
+12
-22
cache.py
django/utils/cache.py
+101
-5
http.py
django/views/decorators/http.py
+8
-68
No files found.
django/middleware/common.py
Dosyayı görüntüle @
7a40fef1
import
hashlib
import
logging
import
re
...
...
@@ -7,6 +6,7 @@ from django.conf import settings
from
django.core
import
urlresolvers
from
django.core.exceptions
import
PermissionDenied
from
django.core.mail
import
mail_managers
from
django.utils.cache
import
get_conditional_response
,
set_response_etag
from
django.utils.encoding
import
force_text
logger
=
logging
.
getLogger
(
'django.request'
)
...
...
@@ -113,20 +113,15 @@ class CommonMiddleware(object):
return
self
.
response_redirect_class
(
self
.
get_full_path_with_slash
(
request
))
if
settings
.
USE_ETAGS
:
if
not
response
.
has_header
(
'ETag'
):
set_response_etag
(
response
)
if
response
.
has_header
(
'ETag'
):
etag
=
response
[
'ETag'
]
elif
response
.
streaming
:
etag
=
None
else
:
etag
=
'"
%
s"'
%
hashlib
.
md5
(
response
.
content
)
.
hexdigest
()
if
etag
is
not
None
:
if
(
200
<=
response
.
status_code
<
300
and
request
.
META
.
get
(
'HTTP_IF_NONE_MATCH'
)
==
etag
):
cookies
=
response
.
cookies
response
=
http
.
HttpResponseNotModified
()
response
.
cookies
=
cookies
else
:
response
[
'ETag'
]
=
etag
return
get_conditional_response
(
request
,
etag
=
response
[
'ETag'
],
response
=
response
,
)
return
response
...
...
django/middleware/http.py
Dosyayı görüntüle @
7a40fef1
from
django.utils.cache
import
get_conditional_response
from
django.utils.http
import
http_date
,
parse_http_date_safe
...
...
@@ -14,28 +15,17 @@ class ConditionalGetMiddleware(object):
if
not
response
.
streaming
and
not
response
.
has_header
(
'Content-Length'
):
response
[
'Content-Length'
]
=
str
(
len
(
response
.
content
))
# If-None-Match must be ignored if original result would be anything
# other than a 2XX or 304 status. 304 status would result in no change.
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
if
200
<=
response
.
status_code
<
300
and
response
.
has_header
(
'ETag'
):
if_none_match
=
request
.
META
.
get
(
'HTTP_IF_NONE_MATCH'
)
if
if_none_match
==
response
[
'ETag'
]:
# Setting the status is enough here. The response handling path
# automatically removes content for this status code (in
# http.conditional_content_removal()).
response
.
status_code
=
304
etag
=
response
.
get
(
'ETag'
)
last_modified
=
response
.
get
(
'Last-Modified'
)
if
last_modified
:
last_modified
=
parse_http_date_safe
(
last_modified
)
# If-Modified-Since must be ignored if the original result was not a 200.
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
if
response
.
status_code
==
200
and
response
.
has_header
(
'Last-Modified'
):
if_modified_since
=
request
.
META
.
get
(
'HTTP_IF_MODIFIED_SINCE'
)
if
if_modified_since
is
not
None
:
if_modified_since
=
parse_http_date_safe
(
if_modified_since
)
if
if_modified_since
is
not
None
:
last_modified
=
parse_http_date_safe
(
response
[
'Last-Modified'
])
if
last_modified
is
not
None
and
last_modified
<=
if_modified_since
:
# Setting the status code is enough here (same reasons as
# above).
response
.
status_code
=
304
if
etag
or
last_modified
:
return
get_conditional_response
(
request
,
etag
=
etag
,
last_modified
=
last_modified
,
response
=
response
,
)
return
response
django/utils/cache.py
Dosyayı görüntüle @
7a40fef1
...
...
@@ -19,18 +19,24 @@ An example: i18n middleware would need to distinguish caches by the
from
__future__
import
unicode_literals
import
hashlib
import
logging
import
re
import
time
from
django.conf
import
settings
from
django.core.cache
import
caches
from
django.http
import
HttpResponse
,
HttpResponseNotModified
from
django.utils.encoding
import
force_bytes
,
force_text
,
iri_to_uri
from
django.utils.http
import
http_date
from
django.utils.http
import
(
http_date
,
parse_etags
,
parse_http_date_safe
,
quote_etag
,
)
from
django.utils.timezone
import
get_current_timezone_name
from
django.utils.translation
import
get_language
cc_delim_re
=
re
.
compile
(
r'\s*,\s*'
)
logger
=
logging
.
getLogger
(
'django.request'
)
def
patch_cache_control
(
response
,
**
kwargs
):
"""
...
...
@@ -97,9 +103,99 @@ def get_max_age(response):
pass
def
_
set_response_etag
(
response
):
def
set_response_etag
(
response
):
if
not
response
.
streaming
:
response
[
'ETag'
]
=
'"
%
s"'
%
hashlib
.
md5
(
response
.
content
)
.
hexdigest
()
response
[
'ETag'
]
=
quote_etag
(
hashlib
.
md5
(
response
.
content
)
.
hexdigest
())
return
response
def
_precondition_failed
(
request
):
logger
.
warning
(
'Precondition Failed:
%
s'
,
request
.
path
,
extra
=
{
'status_code'
:
412
,
'request'
:
request
,
},
)
return
HttpResponse
(
status
=
412
)
def
_not_modified
(
request
,
response
=
None
):
if
response
:
# We need to keep the cookies, see ticket #4994.
cookies
=
response
.
cookies
response
=
HttpResponseNotModified
()
response
.
cookies
=
cookies
return
response
else
:
return
HttpResponseNotModified
()
def
get_conditional_response
(
request
,
etag
=
None
,
last_modified
=
None
,
response
=
None
):
# Get HTTP request headers
if_modified_since
=
request
.
META
.
get
(
'HTTP_IF_MODIFIED_SINCE'
)
if
if_modified_since
:
if_modified_since
=
parse_http_date_safe
(
if_modified_since
)
if_unmodified_since
=
request
.
META
.
get
(
'HTTP_IF_UNMODIFIED_SINCE'
)
if
if_unmodified_since
:
if_unmodified_since
=
parse_http_date_safe
(
if_unmodified_since
)
if_none_match
=
request
.
META
.
get
(
'HTTP_IF_NONE_MATCH'
)
if_match
=
request
.
META
.
get
(
'HTTP_IF_MATCH'
)
etags
=
[]
if
if_none_match
or
if_match
:
# There can be more than one ETag in the request, so we
# consider the list of values.
try
:
etags
=
parse_etags
(
if_none_match
or
if_match
)
except
ValueError
:
# In case of an invalid ETag, ignore all ETag headers.
# Apparently Opera sends invalidly quoted headers at times
# (we should be returning a 400 response, but that's a
# little extreme) -- this is bug #10681.
if_none_match
=
None
if_match
=
None
# If-None-Match must be ignored if original result would be anything
# other than a 2XX or 304 status. 304 status would result in no change.
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
if
response
and
not
(
200
<=
response
.
status_code
<
300
):
if_none_match
=
None
if_match
=
None
# If-Modified-Since must be ignored if the original result was not a 200.
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
if
response
and
response
.
status_code
!=
200
:
if_modified_since
=
None
if_unmodified_since
=
None
if
not
((
if_match
and
if_modified_since
)
or
(
if_none_match
and
if_unmodified_since
)
or
(
if_modified_since
and
if_unmodified_since
)
or
(
if_match
and
if_none_match
)):
# We only get here if no undefined combinations of headers are
# specified.
if
((
if_none_match
and
(
etag
in
etags
or
'*'
in
etags
and
etag
))
and
(
not
if_modified_since
or
(
last_modified
and
if_modified_since
and
last_modified
<=
if_modified_since
))):
if
request
.
method
in
(
'GET'
,
'HEAD'
):
return
_not_modified
(
request
,
response
)
else
:
return
_precondition_failed
(
request
)
elif
(
if_match
and
((
not
etag
and
'*'
in
etags
)
or
(
etag
and
etag
not
in
etags
)
or
(
last_modified
and
if_unmodified_since
and
last_modified
>
if_unmodified_since
))):
return
_precondition_failed
(
request
)
elif
(
not
if_none_match
and
request
.
method
in
(
'GET'
,
'HEAD'
)
and
last_modified
and
if_modified_since
and
last_modified
<=
if_modified_since
):
return
_not_modified
(
request
,
response
)
elif
(
not
if_match
and
last_modified
and
if_unmodified_since
and
last_modified
>
if_unmodified_since
):
return
_precondition_failed
(
request
)
return
response
...
...
@@ -119,9 +215,9 @@ def patch_response_headers(response, cache_timeout=None):
cache_timeout
=
0
# Can't have max-age negative
if
settings
.
USE_ETAGS
and
not
response
.
has_header
(
'ETag'
):
if
hasattr
(
response
,
'render'
)
and
callable
(
response
.
render
):
response
.
add_post_render_callback
(
_
set_response_etag
)
response
.
add_post_render_callback
(
set_response_etag
)
else
:
response
=
_
set_response_etag
(
response
)
response
=
set_response_etag
(
response
)
if
not
response
.
has_header
(
'Last-Modified'
):
response
[
'Last-Modified'
]
=
http_date
()
if
not
response
.
has_header
(
'Expires'
):
...
...
django/views/decorators/http.py
Dosyayı görüntüle @
7a40fef1
...
...
@@ -6,14 +6,11 @@ import logging
from
calendar
import
timegm
from
functools
import
wraps
from
django.http
import
(
HttpResponse
,
HttpResponseNotAllowed
,
HttpResponseNotModified
,
)
from
django.http
import
HttpResponseNotAllowed
from
django.middleware.http
import
ConditionalGetMiddleware
from
django.utils.cache
import
get_conditional_response
from
django.utils.decorators
import
available_attrs
,
decorator_from_middleware
from
django.utils.http
import
(
http_date
,
parse_etags
,
parse_http_date_safe
,
quote_etag
,
)
from
django.utils.http
import
http_date
,
quote_etag
conditional_page
=
decorator_from_middleware
(
ConditionalGetMiddleware
)
...
...
@@ -56,16 +53,6 @@ require_safe = require_http_methods(["GET", "HEAD"])
require_safe
.
__doc__
=
"Decorator to require that a view only accepts safe methods: GET and HEAD."
def
_precondition_failed
(
request
):
logger
.
warning
(
'Precondition Failed:
%
s'
,
request
.
path
,
extra
=
{
'status_code'
:
412
,
'request'
:
request
},
)
return
HttpResponse
(
status
=
412
)
def
condition
(
etag_func
=
None
,
last_modified_func
=
None
):
"""
Decorator to support conditional retrieval (or change) for a view
...
...
@@ -91,29 +78,6 @@ def condition(etag_func=None, last_modified_func=None):
def
decorator
(
func
):
@wraps
(
func
,
assigned
=
available_attrs
(
func
))
def
inner
(
request
,
*
args
,
**
kwargs
):
# Get HTTP request headers
if_modified_since
=
request
.
META
.
get
(
"HTTP_IF_MODIFIED_SINCE"
)
if
if_modified_since
:
if_modified_since
=
parse_http_date_safe
(
if_modified_since
)
if_unmodified_since
=
request
.
META
.
get
(
"HTTP_IF_UNMODIFIED_SINCE"
)
if
if_unmodified_since
:
if_unmodified_since
=
parse_http_date_safe
(
if_unmodified_since
)
if_none_match
=
request
.
META
.
get
(
"HTTP_IF_NONE_MATCH"
)
if_match
=
request
.
META
.
get
(
"HTTP_IF_MATCH"
)
etags
=
[]
if
if_none_match
or
if_match
:
# There can be more than one ETag in the request, so we
# consider the list of values.
try
:
etags
=
parse_etags
(
if_none_match
or
if_match
)
except
ValueError
:
# In case of invalid etag ignore all ETag headers.
# Apparently Opera sends invalidly quoted headers at times
# (we should be returning a 400 response, but that's a
# little extreme) -- this is Django bug #10681.
if_none_match
=
None
if_match
=
None
# Compute values (if any) for the requested resource.
def
get_last_modified
():
if
last_modified_func
:
...
...
@@ -124,35 +88,11 @@ def condition(etag_func=None, last_modified_func=None):
res_etag
=
etag_func
(
request
,
*
args
,
**
kwargs
)
if
etag_func
else
None
res_last_modified
=
get_last_modified
()
response
=
None
if
not
((
if_match
and
if_modified_since
)
or
(
if_none_match
and
if_unmodified_since
)
or
(
if_modified_since
and
if_unmodified_since
)
or
(
if_match
and
if_none_match
)):
# We only get here if no undefined combinations of headers are
# specified.
if
((
if_none_match
and
(
res_etag
in
etags
or
"*"
in
etags
and
res_etag
))
and
(
not
if_modified_since
or
(
res_last_modified
and
if_modified_since
and
res_last_modified
<=
if_modified_since
))):
if
request
.
method
in
(
"GET"
,
"HEAD"
):
response
=
HttpResponseNotModified
()
else
:
response
=
_precondition_failed
(
request
)
elif
(
if_match
and
((
not
res_etag
and
"*"
in
etags
)
or
(
res_etag
and
res_etag
not
in
etags
)
or
(
res_last_modified
and
if_unmodified_since
and
res_last_modified
>
if_unmodified_since
))):
response
=
_precondition_failed
(
request
)
elif
(
not
if_none_match
and
request
.
method
in
(
"GET"
,
"HEAD"
)
and
res_last_modified
and
if_modified_since
and
res_last_modified
<=
if_modified_since
):
response
=
HttpResponseNotModified
()
elif
(
not
if_match
and
res_last_modified
and
if_unmodified_since
and
res_last_modified
>
if_unmodified_since
):
response
=
_precondition_failed
(
request
)
response
=
get_conditional_response
(
request
,
etag
=
res_etag
,
last_modified
=
res_last_modified
,
)
if
response
is
None
:
response
=
func
(
request
,
*
args
,
**
kwargs
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment