Skip to content

Instantly share code, notes, and snippets.

@vfaronov
Last active August 5, 2017 20:07
Show Gist options
  • Save vfaronov/890ec14572d4ccacfa54616e39a43783 to your computer and use it in GitHub Desktop.
Save vfaronov/890ec14572d4ccacfa54616e39a43783 to your computer and use it in GitHub Desktop.
Experimental RFC 7239 parser
import re
import types
_HTTP_QUOTED_STRING = r'"(?:[^\\"]|\\.)*"'
_HTTP_TOKEN = r"[!#\$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+"
_PAIR = '{token}=(?:{token}|{quoted_string})'.format(
token=_HTTP_TOKEN, quoted_string=_HTTP_QUOTED_STRING)
_LEXER_RE = re.compile('{pair}|.'.format(pair=_PAIR))
def parse_forwarded(field_values):
all_elems = []
for field_value in field_values:
name = None
elem = {}
elems = [types.MappingProxyType(elem)]
need_separator = False
for match in _LEXER_RE.finditer(field_value):
s = match.group(0)
if len(s) > 1: # pair
if need_separator:
break
(name, value) = s.split('=', 1)
if value[0] == '"':
value = re.sub(r'\\(.)', r'\1', value[1:-1])
elem[name.lower()] = value
need_separator = True
elif s == ',':
need_separator = False
elem = {}
elems.append(types.MappingProxyType(elem))
elif s == ';':
need_separator = False
elif s != ' ' and s != '\t':
break
else:
# Didn't ``break`` -- this `field_value` is correct
all_elems.extend(elems)
return all_elems
def test_parse_forwarded():
assert parse_forwarded(['for=1.2.3.4']) == [{'for': '1.2.3.4'}]
assert parse_forwarded(['for=1.2.3.4;,']) == [{'for': '1.2.3.4'}, {}]
assert parse_forwarded(['for=1.2.3.4;by="', 'for=5.6.7.8']) == \
[{'for': '5.6.7.8'}]
assert parse_forwarded([
r' For=1.2.3.4;By=_unknown;;Secret="Wow, \"secrets\"!"; ']
) == [{'for': '1.2.3.4', 'by': '_unknown', 'secret': 'Wow, "secrets"!'}]
assert parse_forwarded([r'foo-bar="\"\"\\\\\a\b\c\"\\\\\""']) == \
[{'foo-bar': r'""\\abc"\\"'}]
assert parse_forwarded([r'foo-bar="\"\"\\\\\a\b\c\"\\\\""']) == []
assert parse_forwarded([r'for=_1 by=_2']) == []
assert parse_forwarded([r'for="_1"by="_2"']) == []
assert parse_forwarded([r'for=_1/by=_2']) == []
assert parse_forwarded([r'"for=1.2.3.4"']) == []
assert parse_forwarded([r'xyzzy="' + '\\' * 10000 + '"']) == \
[{'xyzzy': '\\' * 5000}]
if __name__ == '__main__':
test_parse_forwarded()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment