Comments (3)
The Accept machinery is actually a little bit bugged:
- The parser fails on media types like "text/html;level=2;q=0.4" (taken from the rfc rfc2616). I've written a simple working implementation (probably slow), the diff vs 0.7.1 follows
- best_match is based only on the "quality" parameter, not the media type specificity, so sometimes it gives uncorrect results (see the following tests)
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
from werkzeug.
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 Accept: */*
(which is the default for curl, for example), best_match
should return the default instead of the first element in the list.
from werkzeug.
#1507 and #1574 have improved how LanguageAccept
and MIMEAccept
matching works. Please open a new issue if there's something specific that's not working.
from werkzeug.
Related Issues (20)
- Built-in converters do not check syntax of the parameters
- send_file not inserting quote around filename HOT 2
- Some relative redirect strings incorrectly bypass iri_to_uri normalization. HOT 1
- docs: update urlparse import
- test.Client is incorrectly using isinstance check instead of issubclass
- Request not closed with Unicode characters in headers
- Double slashes aren't being handled correctly
- send_file does not include mimetype .webp images HOT 2
- `Rule.endpoint` type annotation doesn't comply with the documentation
- werkzeug > 2.2.2 throws WinError 10038 during flask debug app reload HOT 2
- ProxyFix with x_port should skip standard 80 or 443 ports HOT 6
- `pyright` in strict mode errors when using `formparser.MultiPartParser.parse`
- MultiDict does not handle None values HOT 1
- Test regression with pytest-8.0.0: `tests/test_exceptions.py::test_response_body[RequestRedirect]` HOT 2
- Add "421 Misdirected Request" http exception
- Update runtime dependencies HOT 1
- Random "ssl.SSLEOFError: EOF occurred in violation of protocol" when handling HTTP 206 HOT 2
- OSError: [WinError 10038] An operation was attempted on something that is not a socket HOT 2
- `FileStorage.name` should be the filename HOT 2
- Use of Python 2 `print` statement in quickstart docs
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from werkzeug.