def test_parser_edge_cases(): # Our parser implementation is general enough that # some of its branches are not being exercised by our regular tests, # so I had to come up with these contrived examples to test them. p = many(rfc7230.tchar) > named(u'p') p1 = '1' * p > named(u'p1') p2 = '11' * p * skip('\n') > named(u'p2') assert parse(p1 | p2, b'11abc') == (u'1', [u'1', u'a', u'b', u'c']) assert parse(p1 | p2, b'11abc\n') == (u'11', [u'a', u'b', u'c']) p = recursive() > named(u'p') p.rec = (rfc7230.tchar * p | subst(None) << empty) assert parse(p, b'abc') == (u'a', (u'b', (u'c', None))) p = literal('ab') > named(u'p') p0 = subst(u'') << empty | p > named(u'p0') p1 = 'xab' * p0 > named(u'p1') p2 = 'x' * string(p0) * '!' > named(u'p2') assert parse(p1 | p2, b'xabab') == (u'xab', u'ab') assert parse(p1 | p2, b'xabab!') == (u'x', u'abab', u'!') p = empty | literal('a') > named(u'p') p0 = p * 'x' > named(u'x') assert parse(p0, b'x') == u'x'
def transfer_coding(no_trailers=False, no_q=False): exclude = _built_in_codings if no_trailers: exclude = exclude + ['trailers'] r = transfer_extension(exclude, no_q) for name in _built_in_codings: r = r | _empty_params << (TransferCoding << literal(name)) return r > named(u'transfer-coding', RFC(7230), is_pivot=True)
def media_range(no_q=False): return Parametrized << ( ( literal('*/*') | type_ + '/' + '*' | MediaType << type_ + '/' + subtype ) * ( MultiDict << many( skip(OWS * ';' * OWS) * parameter(exclude=['q'] if no_q else []) ) ) ) > named(u'media-range', RFC(7231), is_pivot=True)
def comma_list(element): # RFC Errata ID: 5257 return _collect_elements << (maybe(group(element) * skip(OWS)) % many( skip(literal(',') * OWS) * maybe(group(element) * skip(OWS)))) > named( u'#rule', RFC(7230, section=u'7'))
# -*- coding: utf-8; -*- from httpolice.citation import RFC from httpolice.parse import (auto, empty, fill_names, literal, maybe_str, octet_range, pivot, string, string1, string_times, subst) from httpolice.syntax.common import ALPHA, DIGIT, HEXDIG pct_encoded = '%' + HEXDIG + HEXDIG > auto sub_delims = (literal('!') | '$' | '&' | "'" | '(' | ')' | '*' | '+' | ',' | ';' | '=') > auto unreserved = ALPHA | DIGIT | '-' | '.' | '_' | '~' > auto pchar = unreserved | sub_delims | ':' | '@' | pct_encoded > auto segment = string(pchar) > auto segment_nz = string1(pchar) > auto segment_nz_nc = string1(unreserved | sub_delims | '@' | pct_encoded) > auto scheme = ALPHA + string(ALPHA | DIGIT | '+' | '-' | '.') > pivot userinfo = string(unreserved | sub_delims | ':' | pct_encoded) > pivot dec_octet = (DIGIT | octet_range(0x31, 0x39) + DIGIT | '1' + DIGIT + DIGIT | '2' + octet_range(0x30, 0x34) + DIGIT | '25' + octet_range(0x30, 0x35)) > auto IPv4address = (dec_octet + '.' + dec_octet + '.' + dec_octet + '.' + dec_octet) > pivot h16 = string_times(1, 4, HEXDIG) > auto ls32 = (h16 + ':' + h16) | IPv4address > auto IPv6address = (
def comma_list(element): return _collect_elements << maybe( (subst([None, None]) << literal(',') | (lambda x: [x]) << group(element)) + many(skip(OWS * ',') * maybe(skip(OWS) * element))) > named( u'#rule', RFC(7230, section=(7, )))
pivot, recursive, skip, string, string1, string_excluding, string_times, subst) from httpolice.structure import (CaseInsensitive, ConnectionOption, FieldName, HTTPVersion, Method, MultiDict, Parametrized, StatusCode, TransferCoding, UpgradeToken, Versioned) from httpolice.syntax.common import (ALPHA, CRLF, DIGIT, DQUOTE, HEXDIG, HTAB, SP, VCHAR) from httpolice.syntax.rfc3986 import (absolute_URI, authority, host as uri_host, port, query, relative_part, segment) obs_text = octet_range(0x80, 0xFF) > auto tchar = (literal('!') | '#' | '$' | '%' | '&' | "'" | '*' | '+' | '-' | '.' | '^' | '_' | '`' | '|' | '~' | DIGIT | ALPHA) > auto token = string1(tchar) > auto def token__excluding(excluding): return string_excluding(tchar, [''] + list(excluding)) def quoted_pair(sensible_for): # In RFC 7230, ``<quoted-pair>`` is a single rule, # but we parametrize it to report no. 1017 depending on the context. @can_complain def check_sensible(complain, c): if c not in sensible_for: complain(1017, char=c) return c
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 (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 from httpolice.syntax.rfc7232 import entity_tag bytes_unit = RangeUnit << literal('bytes') > auto other_range_unit = RangeUnit << token__excluding(['bytes']) > auto range_unit = bytes_unit | other_range_unit > pivot acceptable_ranges = (CaseInsensitive << literal('none') | comma_list1(range_unit)) > pivot Accept_Ranges = acceptable_ranges > pivot @can_complain def _well_formed1(complain, first, last): if (last is not None) and (first > last): complain(1133) return (first, last) first_byte_pos = int << string1(DIGIT) > auto last_byte_pos = int << string1(DIGIT) > auto byte_range_spec = _well_formed1 << (first_byte_pos * skip('-') * maybe(last_byte_pos)) > pivot suffix_length = int << string1(DIGIT) > auto
accept_ext = (skip(OWS * ';' * OWS) * token * maybe(skip('=') * (token | quoted_string))) > pivot def _prepend_q(q, xs): return MultiDict([(CaseInsensitive(u'q'), q)] + xs) accept_params = _prepend_q << weight * many(accept_ext) > pivot Accept = comma_list(Parametrized << ( media_range(no_q=True) * maybe(accept_params, MultiDict()))) > pivot charset = Charset << token > pivot Accept_Charset = comma_list1(Parametrized << ( (charset | Charset << literal('*')) * maybe(weight))) > pivot codings = (content_coding | ContentCoding << literal('identity') | literal('*')) > pivot Accept_Encoding = comma_list(Parametrized << codings * maybe(weight)) > pivot Accept_Language = comma_list1(Parametrized << language_range * maybe(weight)) > pivot delay_seconds = int << string1(DIGIT) > pivot Retry_After = HTTP_date | delay_seconds > pivot Allow = comma_list(method) > pivot Content_Encoding = comma_list1(content_coding) > pivot Content_Language = comma_list1(language_tag) > pivot Content_Location = absolute_URI | partial_URI > pivot
from httpolice.citation import RFC from httpolice.parse import auto, fill_names, literal, many, pivot, skip from httpolice.structure import CaseInsensitive, MultiDict, Parametrized from httpolice.syntax.rfc2616 import value from httpolice.syntax.rfc5987 import ext_value from httpolice.syntax.rfc7230 import OWS, token, token__excluding # This has been slightly adapted to the rules of RFC 7230. # The ``OWS`` are derived from the "implied ``*LWS``" requirement. # We have no need to special-case "inline" and "attachment", simplify. disposition_type = CaseInsensitive << token > pivot filename_parm = ( (CaseInsensitive << literal('filename')) * skip(OWS * '=' * OWS) * value | (CaseInsensitive << literal('filename*')) * skip(OWS * '=' * OWS) * ext_value) > pivot # ``token`` is a superset of ``ext-token``, # and special-casing ``ext-token`` requires # something more complex than our `string_excluding`. # Until then, we can simplify a bit. disp_ext_parm = ( (CaseInsensitive << token__excluding(['filename', 'filename*'])) * skip(OWS * '=' * OWS) * value) > pivot disposition_parm = filename_parm | disp_ext_parm > auto content_disposition = Parametrized << ( disposition_type *
Cache_Control = comma_list1(cache_directive) > pivot # RFC 7234 does not, strictly speaking, define these productions: no_cache = comma_list(field_name) > pivot private = comma_list(field_name) > pivot Expires = HTTP_date > pivot def extension_pragma(exclude_no_cache=False): return Parametrized << ( (token__excluding(['no-cache']) if exclude_no_cache else token) * maybe(skip('=') * (token | quoted_string))) > named( u'extension-pragma', RFC(7234), is_pivot=True) pragma_directive = (CaseInsensitive << literal('no-cache') | extension_pragma(exclude_no_cache=True)) > pivot Pragma = comma_list1(pragma_directive) > pivot warn_code = WarnCode << string_times(3, 3, DIGIT) > pivot warn_agent = uri_host + maybe_str(':' + port) | pseudonym > pivot warn_text = quoted_string > pivot warn_date = skip(DQUOTE) * HTTP_date * skip(DQUOTE) > pivot warning_value = WarningValue << (warn_code * skip(SP) * warn_agent * skip(SP) * warn_text * maybe(skip(SP) * warn_date)) > pivot Warning_ = comma_list1(warning_value) > pivot fill_names(globals(), RFC(7234))
def comma_list(element): # RFC Errata ID: 5257 return _collect_elements << ( maybe(group(element) * skip(OWS)) % many(skip(literal(',') * OWS) * maybe(group(element) * skip(OWS))) ) > named(u'#rule', RFC(7230, section=u'7'))
# RFC 7240 Section 2: "Empty or zero-length values on both # the preference token and within parameters are equivalent # to no value being specified at all." (name, value) = x if isinstance(x, tuple) else (x, None) return Parametrized(name, None if value == u'' else value) def preference_parameter(head=False): # The head (first) ``preference-parameter`` of a ``preference`` # contains the actual preference name, which we want to annotate. name_cls = Preference if head else CaseInsensitive return ( _normalize_empty_value << (parameter(name_cls=name_cls) | name_cls << token) ) > named(u'preference-parameter', RFC(7240, errata=4439), is_pivot=True) preference = Parametrized << ( preference_parameter(head=True) * many(skip(OWS * ';') * maybe(skip(OWS) * preference_parameter())) ) > named(u'preference', RFC(7240, errata=4439), is_pivot=True) Prefer = comma_list1(preference) > pivot Preference_Applied = comma_list1(preference_parameter(head=True)) > pivot return_ = CaseInsensitive << (literal('representation') | 'minimal') > pivot wait = delay_seconds > auto handling = CaseInsensitive << (literal('strict') | 'lenient') > pivot fill_names(globals(), RFC(7240))
# -*- coding: utf-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.syntax.common import CHAR, DIGIT, SP, VCHAR from httpolice.syntax.rfc7230 import comma_list1, token__excluding from httpolice.syntax.rfc7231 import HTTP_date from httpolice.syntax.rfc7232 import entity_tag 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 Accept_Ranges = acceptable_ranges > pivot @can_complain def _well_formed1(complain, first, last): if (last is not None) and (first > last): complain(1133) return (first, last) first_byte_pos = int << string1(DIGIT) > auto last_byte_pos = int << string1(DIGIT) > auto byte_range_spec = _well_formed1 << (first_byte_pos * skip('-') * maybe(last_byte_pos)) > pivot
from httpolice.citation import RFC from httpolice.parse import (auto, fill_names, literal, maybe_str, octet_range, pivot, string, string1, string_times) from httpolice.structure import LanguageTag from httpolice.syntax.common import ALPHA, DIGIT singleton = (DIGIT | octet_range(0x41, 0x57) | octet_range(0x59, 0x5A) | octet_range(0x61, 0x77) | octet_range(0x79, 0x7A)) > auto alphanum = ALPHA | DIGIT > auto irregular = (literal('en-GB-oed') | 'i-ami' | 'i-bnn' | 'i-default' | 'i-enochian' | 'i-hak' | 'i-klingon' | 'i-lux' | 'i-mingo' | 'i-navajo' | 'i-pwn' | 'i-tao' | 'i-tay' | 'i-tsu' | 'sgn-BE-FR' | 'sgn-BE-NL' | 'sgn-CH-DE') > auto regular = (literal('art-lojban') | 'cel-gaulish' | 'no-bok' | 'no-nyn' | 'zh-guoyu' | 'zh-hakka' | 'zh-min' | 'zh-min-nan' | 'zh-xiang') > auto grandfathered = irregular | regular > pivot privateuse = 'x' + string1('-' + string_times(1, 8, alphanum)) > pivot extlang = (string_times(3, 3, ALPHA) + string_times(0, 2, '-' + string_times(3, 3, ALPHA))) > pivot language = (string_times(2, 3, ALPHA) + maybe_str('-' + extlang) | string_times(4, 4, ALPHA) | string_times(5, 8, ALPHA)) > pivot script = string_times(4, 4, ALPHA) > pivot region = string_times(2, 2, ALPHA) | string_times(3, 3, DIGIT) > pivot variant = (string_times(5, 8, alphanum) | (DIGIT + string_times(3, 3, alphanum))) > pivot
from httpolice.syntax.rfc2616 import LOALPHA from httpolice.syntax.rfc3986 import URI, URI_reference as URI_Reference from httpolice.syntax.rfc5646 import Language_Tag from httpolice.syntax.rfc5987 import ext_value, parmname__excluding from httpolice.syntax.rfc6838 import subtype_name, type_name from httpolice.syntax.rfc7230 import OWS, comma_list, quoted_string # RFC 5988 refers to HTML 4.01 for the ``MediaDesc`` rule, # but HTML 4.01 doesn't actually define a grammar for that; # it only gives a vague idea of what it is supposed to be. # So we use a fairly permissive form. # Also, from RFC 5988 Section 5.4: # "its value MUST be quoted if it contains a semicolon (';') or comma (',')". _MediaDesc = string((VCHAR | HTAB | SP) - literal('"')) _MediaDesc_no_delim = string((VCHAR | HTAB | SP) - literal('"') - literal(';') - literal(',')) # This has been slightly adapted to the rules of RFC 7230. # The ``OWS`` are derived from the "implied ``*LWS``" requirement. ptokenchar = (literal('!') | '#' | '$' | '%' | '&' | "'" | '(' | ')' | '*' | '+' | '-' | '.' | '/' | DIGIT | ':' | '<' | '=' | '>' | '?' | '@' | ALPHA | '[' | ']' | '^' | '_' | '`' | '{' | '|' | '}' | '~') > auto ptoken = string1(ptokenchar) > auto media_type = MediaType << type_name + '/' + subtype_name > pivot
# -*- coding: utf-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 (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 from httpolice.syntax.rfc7232 import entity_tag bytes_unit = RangeUnit << literal('bytes') > auto other_range_unit = RangeUnit << token__excluding(['bytes']) > auto range_unit = bytes_unit | other_range_unit > pivot acceptable_ranges = (CaseInsensitive << literal('none') | comma_list1(range_unit)) > pivot Accept_Ranges = acceptable_ranges > pivot @can_complain def _well_formed1(complain, first, last): if (last is not None) and (first > last): complain(1133) return (first, last) first_byte_pos = int << string1(DIGIT) > auto last_byte_pos = int << string1(DIGIT) > auto byte_range_spec = _well_formed1 << (first_byte_pos * skip('-') * maybe(last_byte_pos)) > pivot
from httpolice.citation import RFC from httpolice.parse import (can_complain, fill_names, literal, many, maybe_str, parse, pivot, skip, subst) from httpolice.structure import AltSvcParam, MultiDict, Parametrized from httpolice.syntax.rfc7230 import (OWS, comma_list1, port, quoted_string, tchar, token, uri_host) from httpolice.syntax.rfc7234 import delta_seconds from httpolice.util.data import iterbytes from httpolice.util.text import force_bytes, force_unicode # pylint: enable=import-error clear = literal('clear', case_sensitive=True) > pivot @can_complain def _check_protocol_id(complain, encoded_id): # Since there is only one correct way to encode # an ALPN protocol ID into an RFC 7838 ``protocol-id``, # we just compute it and compare to what's in the message. decoded_id = pct_decode(force_bytes(encoded_id)) correct_encoded_id = u'' for c in iterbytes(decoded_id): if (tchar - '%').match(c): correct_encoded_id += force_unicode(c) else: correct_encoded_id += pct_encode(c, safe='').upper() if encoded_id != correct_encoded_id: complain(1256, actual=encoded_id, correct=correct_encoded_id)
protocol_id = _check_protocol_id << token > pivot @can_complain def _check_alt_authority(complain, value): return parse(value, maybe_str(uri_host) + ':' + port, complain, 1257, authority=value) alt_authority = _check_alt_authority << quoted_string > pivot alternative = protocol_id * skip('=') * alt_authority > pivot parameter = ((AltSvcParam << token) * skip('=') * (token | quoted_string)) > pivot alt_value = Parametrized << ( alternative * (MultiDict << many(skip(OWS * ';' * OWS) * parameter))) > pivot Alt_Svc = clear | comma_list1(alt_value) > pivot ma = delta_seconds > pivot persist = subst(True) << literal('1') > pivot Alt_Used = uri_host + maybe_str(':' + port) > pivot fill_names(globals(), RFC(7838))
# -*- coding: utf-8; -*- from httpolice.citation import RFC from httpolice.parse import (auto, empty, fill_names, literal, maybe_str, octet_range, pivot, string, string1, string_times, subst) from httpolice.syntax.common import ALPHA, DIGIT, HEXDIG pct_encoded = '%' + HEXDIG + HEXDIG > auto sub_delims = (literal('!') | '$' | '&' | "'" | '(' | ')' | '*' | '+' | ',' | ';' | '=') > auto unreserved = ALPHA | DIGIT | '-' | '.' | '_' | '~' > auto pchar = unreserved | sub_delims | ':' | '@' | pct_encoded > auto segment = string(pchar) > auto segment_nz = string1(pchar) > auto segment_nz_nc = string1(unreserved | sub_delims | '@' | pct_encoded) > auto scheme = ALPHA + string(ALPHA | DIGIT | '+' | '-' | '.') > pivot userinfo = string(unreserved | sub_delims | ':' | pct_encoded) > pivot dec_octet = (DIGIT | octet_range(0x31, 0x39) + DIGIT | '1' + DIGIT + DIGIT | '2' + octet_range(0x30, 0x34) + DIGIT | '25' + octet_range(0x30, 0x35)) > auto IPv4address = (dec_octet + '.' + dec_octet + '.' + dec_octet + '.' + dec_octet) > pivot h16 = string_times(1, 4, HEXDIG) > auto ls32 = (h16 + ':' + h16) | IPv4address > auto IPv6address = ( string_times(6, 6, h16 + ':') + ls32 | '::' + string_times(5, 5, h16 + ':') + ls32 | maybe_str(h16) + '::' + string_times(4, 4, h16 + ':') + ls32
# -*- coding: utf-8; -*- from httpolice.citation import RFC from httpolice.parse import (auto, fill_names, literal, maybe_str, octet_range, pivot, string, string1, string_times) from httpolice.structure import LanguageTag from httpolice.syntax.common import ALPHA, DIGIT singleton = (DIGIT | octet_range(0x41, 0x57) | octet_range(0x59, 0x5A) | octet_range(0x61, 0x77) | octet_range(0x79, 0x7A)) > auto alphanum = ALPHA | DIGIT > auto irregular = (literal('en-GB-oed') | 'i-ami' | 'i-bnn' | 'i-default' | 'i-enochian' | 'i-hak' | 'i-klingon' | 'i-lux' | 'i-mingo' | 'i-navajo' | 'i-pwn' | 'i-tao' | 'i-tay' | 'i-tsu' | 'sgn-BE-FR' | 'sgn-BE-NL' | 'sgn-CH-DE') > auto
from six.moves.urllib.parse import quote as pct_encode import six from httpolice.citation import RFC from httpolice.parse import (can_complain, fill_names, literal, many, maybe_str, parse, pivot, skip, subst) from httpolice.structure import AltSvcParam, MultiDict, Parametrized from httpolice.syntax.rfc7230 import (OWS, comma_list1, port, quoted_string, tchar, token, uri_host) from httpolice.syntax.rfc7234 import delta_seconds from httpolice.util.text import force_bytes, force_unicode # pylint: enable=import-error clear = literal('clear', case_sensitive=True) > pivot @can_complain def _check_protocol_id(complain, encoded_id): # Since there is only one correct way to encode # an ALPN protocol ID into an RFC 7838 ``protocol-id``, # we just compute it and compare to what's in the message. decoded_id = pct_decode(force_bytes(encoded_id)) correct_encoded_id = u'' for b in six.iterbytes(decoded_id): c = six.int2byte(b) if (tchar - '%').match(c): correct_encoded_id += force_unicode(c) else: correct_encoded_id += pct_encode(c, safe='').upper()
def media_range(no_q=False): return Parametrized << ( (literal('*/*') | type_ + '/' + '*' | _check_media_type << (MediaType << type_ + '/' + subtype)) * (MultiDict << many( skip(OWS * ';' * OWS) * parameter(exclude=['q'] if no_q else []))) ) > named(u'media-range', RFC(7231), is_pivot=True)
def comma_list(element): return _collect_elements << maybe( (subst([None, None]) << literal(',') | (lambda x: [x]) << group(element)) + many(skip(OWS * ',') * maybe(skip(OWS) * element)) ) > named(u'#rule', RFC(7230, section=(7,)))
# -*- coding: utf-8; -*- from httpolice.parse import (fill_names, literal, maybe, pivot, skip, string1, subst) from httpolice.syntax.common import DIGIT from httpolice.syntax.rfc7230 import RWS, comma_list notice_id = int << string1(DIGIT) > pivot resp = subst(True) << literal('resp') > pivot HTTPolice_Silence = comma_list(notice_id * maybe(skip(RWS) * resp)) > pivot fill_names(globals(), citation=None)
value = parse(value, symbol, complain, 1158, name=name, value=value) r.append((name, value)) if name == u'rev': complain(1226) if u'rel' not in seen: complain(1309) return MultiDict(r) link_param = ((CaseInsensitive << token) * skip(BWS) * maybe( skip(literal('=') * BWS) * (mark(token) | mark(quoted_string)))) > pivot link_value = Parametrized << ( skip('<') * URI_Reference * skip('>') * (_process_params << many(skip(OWS * ';' * OWS) * link_param))) > pivot Link = comma_list(link_value) > pivot anchor = URI_Reference > auto reg_rel_type = CaseInsensitive << (LOALPHA + string(LOALPHA | DIGIT | '.' | '-')) > auto ext_rel_type = URI > auto relation_type = reg_rel_type | ext_rel_type > pivot rel = rev = relation_type % many(skip(string1(SP)) * relation_type) > auto
# -*- coding: utf-8; -*- from httpolice.parse import ( fill_names, literal, maybe, pivot, skip, string1, subst, ) from httpolice.syntax.common import DIGIT from httpolice.syntax.rfc7230 import RWS, comma_list notice_id = int << string1(DIGIT) > pivot resp = subst(True) << literal('resp') > pivot HTTPolice_Silence = comma_list(notice_id * maybe(skip(RWS) * resp)) > pivot fill_names(globals(), citation=None)
from httpolice.parse import (auto, case_sens, fill_names, literal, maybe_str, pivot) from httpolice.syntax.rfc3986 import host, port, scheme from httpolice.syntax.rfc7230 import (comma_list, comma_list1, field_name, method) from httpolice.syntax.rfc7234 import delta_seconds # WHATWG actually uses their own definitions for scheme, host, and port, # but that's a bit too far for HTTPolice, we can live with RFC 3986. origin = scheme + '://' + host + maybe_str(':' + port) > pivot origin_or_null = origin | case_sens('null') > pivot Origin = origin_or_null > pivot Access_Control_Request_Method = method > pivot Access_Control_Request_Headers = comma_list1(field_name) > pivot wildcard = literal('*') > auto Access_Control_Allow_Origin = origin_or_null | wildcard > pivot Access_Control_Allow_Credentials = case_sens('true') > pivot Access_Control_Expose_Headers = comma_list(field_name) > pivot Access_Control_Max_Age = delta_seconds > pivot Access_Control_Allow_Methods = comma_list(method) > pivot Access_Control_Allow_Headers = comma_list(field_name) > pivot X_Content_Type_Options = literal('nosniff') > pivot Cross_Origin_Resource_Policy = (case_sens('same-origin') | case_sens('same-site')) > pivot fill_names(globals(), Citation(u'WHATWG Fetch', u'https://fetch.spec.whatwg.org/'))
from httpolice.parse import auto, fill_names, literal, many, pivot, skip from httpolice.structure import CaseInsensitive, MultiDict, Parametrized from httpolice.syntax.rfc2616 import value from httpolice.syntax.rfc5987 import ext_value from httpolice.syntax.rfc7230 import OWS, token, token__excluding # This has been slightly adapted to the rules of RFC 7230. # The ``OWS`` are derived from the "implied ``*LWS``" requirement. # We have no need to special-case "inline" and "attachment", simplify. disposition_type = CaseInsensitive << token > pivot filename_parm = ( (CaseInsensitive << literal('filename')) * skip(OWS * '=' * OWS) * value | (CaseInsensitive << literal('filename*')) * skip(OWS * '=' * OWS) * ext_value) > pivot # ``token`` is a superset of ``ext-token``, # and special-casing ``ext-token`` requires # something more complex than our `string_excluding`. # Until then, we can simplify a bit. disp_ext_parm = ( (CaseInsensitive << token__excluding(['filename', 'filename*'])) * skip(OWS * '=' * OWS) * value) > pivot disposition_parm = filename_parm | disp_ext_parm > auto content_disposition = Parametrized << (
weight = skip(OWS * ';' * OWS * 'q=') * qvalue > pivot accept_ext = (skip(OWS * ';' * OWS) * token * maybe(skip('=') * (token | quoted_string))) > pivot def _prepend_q(q, xs): return MultiDict([(CaseInsensitive(u'q'), q)] + xs) accept_params = _prepend_q << weight * many(accept_ext) > pivot Accept = comma_list( Parametrized << (media_range(no_q=True) * maybe(accept_params, MultiDict()))) > pivot charset = Charset << token > pivot Accept_Charset = comma_list1( Parametrized << ((charset | Charset << literal('*')) * maybe(weight))) > pivot codings = (content_coding | ContentCoding << literal('identity') | literal('*')) > pivot Accept_Encoding = comma_list(Parametrized << codings * maybe(weight)) > pivot Accept_Language = comma_list1( Parametrized << language_range * maybe(weight)) > pivot delay_seconds = int << string1(DIGIT) > pivot Retry_After = HTTP_date | delay_seconds > pivot Allow = comma_list(method) > pivot Content_Encoding = comma_list1(content_coding) > pivot
from httpolice.citation import RFC from httpolice.parse import (auto, can_complain, fill_names, group, literal, many, maybe, maybe_str, named, octet, octet_range, pivot, recursive, skip, string, string1, string_excluding, string_times, subst) from httpolice.structure import (CaseInsensitive, ConnectionOption, FieldName, Method, MultiDict, Parametrized, TransferCoding, UpgradeToken, Versioned) from httpolice.syntax.common import ALPHA, DIGIT, DQUOTE, HTAB, SP, VCHAR from httpolice.syntax.rfc3986 import (absolute_URI, authority, host as uri_host, port, query, relative_part, segment) obs_text = octet_range(0x80, 0xFF) > auto tchar = (literal('!') | '#' | '$' | '%' | '&' | "'" | '*' | '+' | '-' | '.' | '^' | '_' | '`' | '|' | '~' | DIGIT | ALPHA) > auto token = string1(tchar) > auto def token__excluding(excluding): return string_excluding(tchar, [''] + list(excluding)) def quoted_pair(sensible_for): # In RFC 7230, ``<quoted-pair>`` is a single rule, # but we parametrize it to report no. 1017 depending on the context. @can_complain def check_sensible(complain, c): if c not in sensible_for:
Age = delta_seconds > pivot cache_directive = Parametrized << ( (CacheDirective << token) * maybe(skip('=') * (mark(token) | mark(quoted_string)))) > pivot Cache_Control = comma_list1(cache_directive) > pivot Expires = HTTP_date > pivot def extension_pragma(exclude_no_cache=False): return Parametrized << ( (token__excluding(['no-cache']) if exclude_no_cache else token) * maybe(skip('=') * (token | quoted_string)) ) > named(u'extension-pragma', RFC(7234), is_pivot=True) pragma_directive = (CaseInsensitive << literal('no-cache') | extension_pragma(exclude_no_cache=True)) > pivot Pragma = comma_list1(pragma_directive) > pivot warn_code = WarnCode << string_times(3, 3, DIGIT) > pivot warn_agent = uri_host + maybe_str(':' + port) | pseudonym > pivot warn_text = quoted_string > pivot warn_date = skip(DQUOTE) * HTTP_date * skip(DQUOTE) > pivot warning_value = WarningValue << (warn_code * skip(SP) * warn_agent * skip(SP) * warn_text * maybe(skip(SP) * warn_date)) > pivot Warning_ = comma_list1(warning_value) > pivot fill_names(globals(), RFC(7234))
u'anchor': URI_Reference, u'rel': rel, u'rev': rev, u'hreflang': hreflang, u'type': type_, u'title*': ext_value, }.get(name) if symbol is not None: value = parse(value, symbol, complain, 1158, name=name, value=value) r.append((name, value)) if name == u'rev': complain(1226) if u'rel' not in seen: complain(1309) return MultiDict(r) link_param = ( (CaseInsensitive << token) * skip(BWS) * maybe(skip(literal('=') * BWS) * (mark(token) | mark(quoted_string)))) > pivot link_value = Parametrized << ( skip('<') * URI_Reference * skip('>') * (_process_params << many(skip(OWS * ';' * OWS) * link_param))) > pivot Link = comma_list(link_value) > pivot anchor = URI_Reference > auto reg_rel_type = CaseInsensitive << ( LOALPHA + string(LOALPHA | DIGIT | '.' | '-')) > auto ext_rel_type = URI > auto relation_type = reg_rel_type | ext_rel_type > pivot