New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CherryPy should handle If-Range's properly #1760
base: main
Are you sure you want to change the base?
Conversation
cherrypy/lib/static.py
Outdated
@@ -174,7 +176,21 @@ def _serve_fileobj(fileobj, content_type, content_length, debug=False): | |||
cherrypy.log(message, 'TOOLS.STATIC') | |||
raise cherrypy.HTTPError(416, message) | |||
|
|||
if r: | |||
IF_RANGE_IN_PAST = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it's a variable and not a constant, you should use lowercase
cherrypy/lib/static.py
Outdated
# and the server sends back a 206 Partial Content answer with | ||
# the appropriate body. If the condition is not fulfilled, | ||
# the full resource is sent back, with a 200 OK status. | ||
if datetime.datetime(*parsedate(request.headers.get('If-Range'))[:6]) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We prefer wrapping clause with braces instead of escaping EOL
Thanks for cleaning this up for me, I'm still getting used to the coding conventions on this project, as well as my IDE doing things for me that don't match what the convention is! |
No worries, just try to follow PEP8 + PEP257 at first :) |
cherrypy/lib/static.py
Outdated
@@ -174,7 +176,22 @@ def _serve_fileobj(fileobj, content_type, content_length, debug=False): | |||
cherrypy.log(message, 'TOOLS.STATIC') | |||
raise cherrypy.HTTPError(416, message) | |||
|
|||
if r: | |||
is_if_range_in_past = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this check would be moved before httputil.get_ranges()
call, so that we could skip calling another heavy function.
Also, this whole check could be put into its own function (maybe in httputil
) for readability.
It looks like flake8 made checks stricter so this will need to be fixed separately. |
cherrypy/lib/static.py
Outdated
# the appropriate body. If the condition is not fulfilled, | ||
# the full resource is sent back, with a 200 OK status. | ||
# Ref: https://tools.ietf.org/html/rfc7233#section-3.2 | ||
if datetime(*parsedate(if_range_header)[:6]) < datetime.now(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will probably fail with E-Tag value:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Range
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll write a change for this. Do you think searching for exactly two double quotes will be enough for detecting ETAG vs Date? That's what I'm working with at the moment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably go for try/except
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it should probably go to httputil
module
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Migrated to httputil, and caught exception when there is an ETag instead of an httpdate. However, I treat the ETag as an always-fail condition as to my knowledge we don't support that yet? Correct me if I'm wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually supported in caching
tool: https://github.com/cherrypy/cherrypy/search?q=expires&unscoped_q=expires&type=Code
And it just occurred to me that maybe this check should be done there, not in this module.
There's also a tool called expires
+ there's tests for etag as well.
Could you please explore this?
This pull request introduces 2 alerts when merging 2da1314 into e10b984 - view on LGTM.com new alerts:
Comment posted by LGTM.com |
Correct passes_if_range_check to not take request object, but rather take given if_range_header
This pull request introduces 1 alert when merging 302c2d9 into b648977 - view on LGTM.com new alerts:
Comment posted by LGTM.com |
Co-Authored-By: duper51 <ianotto24@gmail.com>
Co-Authored-By: duper51 <ianotto24@gmail.com>
This pull request introduces 1 alert when merging 64a52cc into b648977 - view on LGTM.com new alerts:
Comment posted by LGTM.com |
…heck Invert logic in matches_if_range_check to save on indentation
# Conflicts: # cherrypy/lib/httputil.py
This pull request introduces 1 alert when merging 13e149b into b648977 - view on LGTM.com new alerts:
Comment posted by LGTM.com |
Co-Authored-By: duper51 <ianotto24@gmail.com>
Co-Authored-By: duper51 <ianotto24@gmail.com>
This pull request introduces 1 alert when merging ae98c9b into b648977 - view on LGTM.com new alerts:
Comment posted by LGTM.com |
flake8 fixes
ensure old functionality is still present (logging parameter for non-requested byterange)
@@ -66,6 +67,29 @@ def protocol_from_http(protocol_str): | |||
return int(protocol_str[5]), int(protocol_str[7]) | |||
|
|||
|
|||
def matches_if_range_check(if_range_header): | |||
""" | |||
Determines if an If-Range header is present and passes its conditions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imperative plz.
Determines if an If-Range header is present and passes its conditions. | |
Determine if an If-Range header conditions are fulfilled. |
stop = content_length | ||
r_len = stop - start | ||
if_range_valid = httputil.matches_if_range_check( | ||
request.headers.get('Range') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
plz add a trailing comma here
request.headers.get('Range') | |
request.headers.get('Range'), |
if if_range_valid: | ||
r = httputil.get_ranges( | ||
request.headers.get('Range'), | ||
content_length |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trailing comma plz
content_length | |
content_length, |
Codecov Report
@@ Coverage Diff @@
## master #1760 +/- ##
==========================================
+ Coverage 60.32% 81% +20.68%
==========================================
Files 104 104
Lines 18156 13654 -4502
==========================================
+ Hits 10953 11061 +108
+ Misses 7203 2593 -4610 |
What kind of change does this PR introduce?
What is the related issue number (starting with
#
)Fixes #1699
What is the current behavior? (You can also link to an open issue here)
#1699
What is the new behavior (if this is a feature change)?
In the presence of an
If-Range
header, CP will check if the time is before the current time, and if so, return the entire file as opposed to respecting theRange
header. This is the RFC compliant way to handle this.Other information:
Checklist:
and description in grammatically correct, complete sentences