-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Review Accept.best_match and MIMEAccept._value_matches #20
Labels
Milestone
Comments
The Accept machinery is actually a little bit bugged:
diff --git a/werkzeug/http.py b/werkzeug/http.py
index 32e0307..22bae4b 100644
--- a/werkzeug/http.py
+++ b/werkzeug/http.py
@@ -268,13 +268,25 @@ def parse_accept_header(value, cls=None):
return cls(None)
result = []
- for match in _accept_re.finditer(value):
- quality = match.group(2)
- if not quality:
- quality = 1
+ for item in value.split(","):
+ quality = 1.0
+ if ';' in item:
+ components = item.split(';')
+ mimetype = components[0].strip()
+ params = [x.strip().split("=") for x in components[1:]]
+ media_params = True
+ for key, val in params:
+ if key.strip() == "q":
+ # end of media-range parameters
+ media_params = False
+ quality = max(min(float(val.strip()), 1), 0)
+
+ # accept-extension parameters are currently ignored
+ if media_params:
+ mimetype += ";%s=%s" % (key, val)
else:
- quality = max(min(float(quality), 1), 0)
- result.append((match.group(1), quality))
+ mimetype, params = item.strip(), []
+ result.append((mimetype, quality))
return cls(result) import werkzeug
from werkzeug.wrappers import BaseRequest, AcceptMixin
from werkzeug.test import create_environ
assert werkzeug.__version__.startswith("0.7"), werkzeug.__version__
class Request(BaseRequest, AcceptMixin):
pass
def test1():
# OK
req = Request(create_environ(headers=[('accept', 'audio/*; q=0.2, audio/basic')]))
assert req.accept_mimetypes.values() == ["audio/basic", "audio/*"]
assert req.accept_mimetypes.best_match(['audio/xxx', 'audio/basic']) == "audio/basic"
assert req.accept_mimetypes.best_match(['audio/basic', 'audio/xxx']) == "audio/basic"
def test2():
req = Request(create_environ(headers=[('accept', 'audio/*, audio/basic')]))
assert req.accept_mimetypes.values() == ["audio/basic", "audio/*"] # OK
assert req.accept_mimetypes.best_match(['audio/basic', 'audio/xxx']) == "audio/basic" # OK
# audio/basic is more specific
assert req.accept_mimetypes.best_match(['audio/xxx', 'audio/basic']) == "audio/basic" # FAIL
def test3():
accept = "text/plain; q=0.5, text/html,text/x-dvi; q=0.8, text/x-c"
req = Request(create_environ(headers=[('accept', accept)]))
assert req.accept_mimetypes.best_match(['text/html', 'text/x-c']) == 'text/html' # OK
# I think it should always choose the best match, which in this case is text/html that appears
# first in the accept list. Probably it's just a personal taste.
assert req.accept_mimetypes.best_match(['text/x-c', 'text/html']) == 'text/html' # FAIL
def test4():
accept = "text/*, text/html, text/html;level=1, */*"
req = Request(create_environ(headers=[('accept', accept)]))
values = req.accept_mimetypes.values()
assert values == ["text/html;level=1", "text/html", "text/*", "*/*"], values
# text/html is more specific
assert req.accept_mimetypes.best_match(['text/plain', 'text/html']) == 'text/html'
def test5():
# very rare corner cases
accept = "text/*;q=0.3, text/html;q=0.7, text/html;level=1,text/html;level=2;q=0.4, */*;q=0.5"
req = Request(create_environ(headers=[('accept', accept)]))
values = list(req.accept_mimetypes)
assert req.accept_mimetypes.best_match(['image/jpeg', 'text/plain']) == "image/jpeg" # OK
assert req.accept_mimetypes.best_match(['text/html', 'text/plain']) == "text/html" # OK
# *.* has a quality of 0.5, while text/* 0.3, so image/jpeg should win
assert req.accept_mimetypes.best_match(['text/plain', 'image/jpeg']) == "image/jpeg" # FAIL |
I'm not sure if this should be a separate issue or not, so I'll just post it here for now. It seems to me that with a request that has the header |
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
There was a bug in there and the fix was the switching of two arguments. However it should be ensured that this was the only bug and that it now works as expected. Unfortunately it's slightly underdocumented there.
The text was updated successfully, but these errors were encountered: