Repository: pallets/werkzeug

Issue:
Cookies with certain keys are ignored
I have a cookie called `version=xxx` in Headers, but it ignored by flask, using `request.cookies.get('version')` can't get the cookie.

I check the code then found these:

```python
# _internal.py

_cookie_params = {
    b"expires",
    b"path",
    b"comment",
    b"max-age",
    b"secure",
    b"httponly",
    b"version",
}

# Ignore parameters.  We have no interest in them.
if key.lower() not in _cookie_params:
    yield _cookie_unquote(key), _cookie_unquote(value)
```

I don't know the comment *"We have no interest in them"* mean. Is there anyone can explain that for me?  I will be appreciate for that.


Discussion:
This is about the params of a cookie, not about the cookie name. If a cookie with such a name gets ignored, it's a bug.
@ThiefMaster It seems like a bug,

```python
def _cookie_parse_impl(b):
    """Lowlevel cookie parsing facility that operates on bytes."""
    i = 0
    n = len(b)

    while i < n:
        match = _cookie_re.search(b + b";", i)
        if not match:
            break

        key = match.group("key").strip()
        value = match.group("val") or b""
        i = match.end(0)

        # Ignore parameters.  We have no interest in them.
        if key.lower() not in _cookie_params:
            yield _cookie_unquote(key), _cookie_unquote(value)
```

Maybe it should be `if value.lower() in _cookie_params`, if that, I will submit a pull request to fix it.
I check the RFC 6265, it seems like there are some attributes have different usage. https://tools.ietf.org/html/rfc6265#section-5.2

But I don't find the `version` attribute.
This appears to be a bug. I think the intention of the code was to ignore parameters that would only be relevant in a response's `Set-Cookie` if they were present in a request's `Cookie` header, but it ended up excluding the keys, not the parameters. Here's an example, this always returns "not set".

```python
from werkzeug.serving import run_simple
from werkzeug.wrappers import Request, Response


@Request.application
def app(request):
    rv = Response("not set")

    if "version" in request.cookies:
        rv.data = request.cookies["version"]
    else:
        rv.set_cookie("version", "2")

    return rv


if __name__ == "__main__":
    run_simple("localhost", 5000, app)
```

Resolving patch:
diff --git a/src/werkzeug/_internal.py b/src/werkzeug/_internal.py
--- a/src/werkzeug/_internal.py
+++ b/src/werkzeug/_internal.py
@@ -26,15 +26,6 @@
 _logger = None
 _signature_cache = WeakKeyDictionary()
 _epoch_ord = date(1970, 1, 1).toordinal()
-_cookie_params = {
-    b"expires",
-    b"path",
-    b"comment",
-    b"max-age",
-    b"secure",
-    b"httponly",
-    b"version",
-}
 _legal_cookie_chars = (
     string.ascii_letters + string.digits + u"/=!#$%&'*+-.^_`|~:"
 ).encode("ascii")
@@ -310,9 +301,7 @@ def _cookie_parse_impl(b):
         value = match.group("val") or b""
         i = match.end(0)
 
-        # Ignore parameters.  We have no interest in them.
-        if key.lower() not in _cookie_params:
-            yield _cookie_unquote(key), _cookie_unquote(value)
+        yield _cookie_unquote(key), _cookie_unquote(value)
 
 
 def _encode_idna(domain):


Test patch:
diff --git a/tests/test_http.py b/tests/test_http.py
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -483,10 +483,13 @@ def test_empty_keys_are_ignored(self):
     def test_cookie_quoting(self):
         val = http.dump_cookie("foo", "?foo")
         strict_eq(val, 'foo="?foo"; Path=/')
-        strict_eq(dict(http.parse_cookie(val)), {"foo": u"?foo"})
-
+        strict_eq(dict(http.parse_cookie(val)), {"foo": u"?foo", "Path": u"/"})
         strict_eq(dict(http.parse_cookie(r'foo="foo\054bar"')), {"foo": u"foo,bar"})
 
+    def test_parse_set_cookie_directive(self):
+        val = 'foo="?foo"; version="0.1";'
+        strict_eq(dict(http.parse_cookie(val)), {"foo": u"?foo", "version": u"0.1"})
+
     def test_cookie_domain_resolving(self):
         val = http.dump_cookie("foo", "bar", domain=u"\N{SNOWMAN}.com")
         strict_eq(val, "foo=bar; Domain=xn--n3h.com; Path=/")