示例#1
0
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'
示例#2
0
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'
示例#3
0
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)
示例#4
0
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)
示例#5
0
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)
示例#6
0
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'))
示例#7
0
# -*- 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 = (
示例#8
0
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, )))
示例#9
0
                             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
示例#10
0
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
示例#11
0
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
示例#12
0
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 *
示例#13
0
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))
示例#14
0
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'))
示例#15
0
    # 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))
示例#16
0
# -*- 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
示例#17
0
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
示例#18
0
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
示例#19
0
# -*- 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
示例#20
0
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)
示例#21
0
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))
示例#22
0
# -*- 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
示例#23
0
# -*- 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
示例#24
0
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()
示例#25
0
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)
示例#26
0
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,)))
示例#27
0
# -*- 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)
示例#28
0
            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
示例#29
0
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
示例#30
0
# -*- 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)
示例#31
0
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/'))
示例#32
0
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 << (
示例#33
0
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
示例#34
0
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:
示例#35
0
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))
示例#36
0
            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