Skip to content
This repository has been archived by the owner on Mar 29, 2022. It is now read-only.

Commit

Permalink
Fix notice 1013 for headers that permit both singular and plural values
Browse files Browse the repository at this point in the history
  • Loading branch information
vfaronov committed Jul 18, 2017
1 parent a9802f7 commit c285e49
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 16 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Added

Fixed
-----
- Notice `1013`_ is no longer wrongly reported for some headers
such as ``Vary``.
- Fixed a crash on some pathological values of ``charset`` in ``Content-Type``.

.. _Forwarded: https://tools.ietf.org/html/rfc7239
Expand All @@ -29,6 +31,7 @@ Fixed
.. _1298: http://pythonhosted.org/HTTPolice/notices.html#1298
.. _1296: http://pythonhosted.org/HTTPolice/notices.html#1296
.. _1297: http://pythonhosted.org/HTTPolice/notices.html#1297
.. _1013: http://pythonhosted.org/HTTPolice/notices.html#1013


0.5.2 - 2017-03-24
Expand Down
22 changes: 17 additions & 5 deletions httpolice/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,24 @@ class MultiHeaderView(HeaderView):

def _parse(self):
entries, values = self._pre_parse()
self._value = []
for sub_values in values:
if isinstance(sub_values, Unavailable):
self._value.append(sub_values)
# Some headers, such as ``Vary``, permit both a comma-separated list
# (which can be spread over multiple entries) as well as a singular
# value (which cannot be combined with any other).
singular = [v for v in values
if not isinstance(v, (list, Unavailable))]
if singular:
if len(singular) == len(entries) == 1:
self._value = singular[0]
else:
self._value.extend(sub_values)
self._value = [Unavailable()]
self.message.complain(1013, header=self, entries=entries)
else:
self._value = []
for v in values:
if isinstance(v, Unavailable):
self._value.append(v)
else:
self._value.extend(v)
self._entries = entries

def __iter__(self):
Expand Down
10 changes: 5 additions & 5 deletions httpolice/known/header.csv
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Accept-Features,,,,4229,,,,,,,,,,,,,,,
Accept-Language,,,,7231,5.3.5,,,,rfc7231,Accept_Language,,,True,False,standard,False,True,,multi
Accept-Patch,,,,5789,3.1,,,,rfc5789,Accept_Patch,,,False,True,,,,,multi
Accept-Post,,,,,,,https://www.w3.org/TR/ldp/,,,,,,,,standard,,,,
Accept-Ranges,,,,7233,2.3,,,,rfc7233,Accept_Ranges,,,False,True,standard,,,,single
Accept-Ranges,,,,7233,2.3,,,,rfc7233,Accept_Ranges,,,False,True,standard,,,,multi
Access-Control,,,,,,,http://www.w3.org/2006/appformats/,W3C Web Application Formats Working Group,,,,,,,deprecated,,,,
Access-Control-Allow-Credentials,,,citation,,,,https://www.w3.org/TR/cors/#access-control-allow-credentials-response-header,W3C Cross-Origin Resource Sharing,,,,,,,,,,,
Access-Control-Allow-Headers,,,citation,,,,https://www.w3.org/TR/cors/#access-control-allow-headers-response-header,W3C Cross-Origin Resource Sharing,,,,,,,,,,,
Expand All @@ -21,7 +21,7 @@ Access-Control-Request-Headers,,,citation,,,,https://www.w3.org/TR/cors/#access-
Access-Control-Request-Method,,,citation,,,,https://www.w3.org/TR/cors/#access-control-request-method-request-header,W3C Cross-Origin Resource Sharing,,,,,,,,,,,
Age,,,,7234,5.1,,,,rfc7234,Age,True,True,False,True,standard,,,,single
Allow,,,,7231,7.4.1,,,,rfc7231,Allow,,,False,True,standard,,,,multi
Alt-Svc,,,,7838,3,,,,rfc7838,Alt_Svc,,,False,True,standard,,,,single
Alt-Svc,,,,7838,3,,,,rfc7838,Alt_Svc,,,False,True,standard,,,,multi
Alt-Used,,,,7838,5,,,,rfc7838,Alt_Used,,True,True,False,standard,False,False,,single
Alternates,,,,4229,,,,,,,,,,,,,,,
Apply-To-Redirect-Ref,,,,4437,,,,,,,,,,,,,,,
Expand Down Expand Up @@ -79,9 +79,9 @@ Hobareg,,,,7486,6.1.1,,,,,,,,,,experimental,,,,
Host,,,,7230,5.4,,,,rfc7230,Host,,True,True,False,standard,False,False,,single
IM,,,,4229,,,,,,,,,,,,,,,
If,,,,4918,10.4,,,,,,,True,,,standard,True,,,
If-Match,,,,7232,3.1,,,,rfc7232,If_Match,,True,True,False,standard,True,False,,single
If-Match,,,,7232,3.1,,,,rfc7232,If_Match,,True,True,False,standard,True,False,,multi
If-Modified-Since,,,,7232,3.3,,,,rfc7232,If_Modified_Since,,True,True,False,standard,True,False,,single
If-None-Match,,,,7232,3.2,,,,rfc7232,If_None_Match,,True,True,False,standard,True,False,,single
If-None-Match,,,,7232,3.2,,,,rfc7232,If_None_Match,,True,True,False,standard,True,False,,multi
If-Range,,,,7233,3.2,,,,rfc7233,If_Range,,True,True,False,standard,False,False,,single
If-Schedule-Tag-Match,,,,6638,8.3,,,,,,,True,,,standard,True,,,
If-Unmodified-Since,,,,7232,3.4,,,,rfc7232,If_Unmodified_Since,,True,True,False,standard,True,False,,single
Expand Down Expand Up @@ -176,7 +176,7 @@ Upgrade,,,,7230,6.7,,,,rfc7230,Upgrade,,,True,True,standard,False,False,,multi
Urgency,,,,8030,5.3,,,,,,,,,,standard,,,,
User-Agent,,,,7231,5.5.3,,,,rfc7231,User_Agent,,,True,False,standard,False,False,,single
Variant-Vary,,,,4229,,,,,,,,,,,,,,,
Vary,,,,7231,7.1.4,,,,rfc7231,Vary,True,True,False,True,standard,,,,single
Vary,,,,7231,7.1.4,,,,rfc7231,Vary,True,True,False,True,standard,,,,multi
Version,,,,4229,,,,,,,,,,,,,,,
Via,,,,7230,5.7.1,,,,rfc7230,Via,True,,True,True,standard,False,False,,multi
WWW-Authenticate,,,,7235,4.1,,,,rfc7235,WWW_Authenticate,True,,False,True,standard,,,,multi
Expand Down
8 changes: 4 additions & 4 deletions httpolice/syntax/rfc7233.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from httpolice.citation import RFC
from httpolice.parse import (auto, can_complain, fill_names, literal, maybe,
pivot, skip, string, string1, subst)
from httpolice.structure import ContentRange, RangeSpecifier, RangeUnit
from httpolice.structure import (CaseInsensitive, ContentRange, RangeSpecifier,
RangeUnit)
from httpolice.syntax.common import CHAR, DIGIT, SP, VCHAR
from httpolice.syntax.rfc7230 import comma_list1, token__excluding
from httpolice.syntax.rfc7231 import HTTP_date
Expand All @@ -13,9 +14,8 @@
bytes_unit = RangeUnit << literal('bytes') > auto
other_range_unit = RangeUnit << token__excluding(['bytes']) > auto
range_unit = bytes_unit | other_range_unit > pivot
acceptable_ranges = (
subst([]) << literal('none') |
comma_list1(range_unit)) > pivot
acceptable_ranges = (CaseInsensitive << literal('none') |
comma_list1(range_unit)) > pivot
Accept_Ranges = acceptable_ranges > pivot

@can_complain
Expand Down
19 changes: 19 additions & 0 deletions test/combined_data/1013_4
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
1235

# The presence of no. 1235 here means that we correctly recognize the multiple
# values.

======== BEGIN INBOUND STREAM ========
GET / HTTP/1.1
Host: example.com
User-Agent: demo

======== BEGIN OUTBOUND STREAM ========
HTTP/1.1 200 OK
Date: Thu, 31 Dec 2015 18:26:56 GMT
Vary: accept-encoding
Content-Type: text/plain
Content-Length: 14
Vary: host

Hello world!
20 changes: 20 additions & 0 deletions test/combined_data/1013_5
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
1013 1013

======== BEGIN INBOUND STREAM ========
GET / HTTP/1.1
Host: example.com
User-Agent: demo
If-none-match: *

======== BEGIN OUTBOUND STREAM ========
HTTP/1.1 200 OK
Date: Thu, 31 Dec 2015 18:26:56 GMT
Content-Type: text/plain
Content-Length: 14
Vary: *
Accept-Ranges: none
Alt-Svc: clear
Vary: accept-encoding
Accept-Ranges: none

Hello world!
10 changes: 10 additions & 0 deletions test/test_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,13 @@ def test_prefer():
def test_decode_brotli():
[exch1] = load_from_file('content_encoding_br')
assert exch1.responses[0].decoded_body.startswith(b'Lorem ipsum dolor')


def test_singular_vs_plural():
[exch] = load_from_file('1013_5')
assert exch.request.headers.if_none_match == u'*'
assert exch.responses[0].headers.alt_svc == u'clear'
assert all(isinstance(v, Unavailable)
for v in exch.responses[0].headers.accept_ranges)
assert all(isinstance(v, Unavailable)
for v in exch.responses[0].headers.vary)
4 changes: 2 additions & 2 deletions test/test_syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,8 +354,8 @@ def test_http_date():

def test_acceptable_ranges():
p = rfc7233.acceptable_ranges
assert parse(p, b'none') == []
assert parse(p, b'NONE') == []
assert parse(p, b'none') == u'none'
assert parse(p, b'NONE') == u'none'
assert parse(p, b'none,') == [u'none']
assert parse(p, b', ,Bytes, Pages') == [unit.bytes, u'pages']

Expand Down

0 comments on commit c285e49

Please sign in to comment.