Beispiel #1
0
 def _pre_parse(self):
     entries = []
     values = []
     items = self.message.headers.enumerate(self.name)
     parser = header.parser_for(self.name)
     for from_trailer, i, entry in items:
         if from_trailer and header.is_bad_for_trailer(self.name):
             self.message.complain(1026, entry=entry)
             continue
         entries.append(entry)
         if parser is None:
             parsed = entry.value
         else:
             (parsed,
              annotations) = simple_parse(entry.value,
                                          parser,
                                          self.message.complain,
                                          1000,
                                          place=entry,
                                          annotate_classes=known.classes)
             if parsed is not Unavailable:
                 parsed = self._process_parsed(entry, parsed)
                 self.message.annotations[(from_trailer, i)] = annotations
         values.append(parsed)
     return entries, values
Beispiel #2
0
    def target_form(self):
        try:
            target = self.target.encode('iso-8859-1')
        except UnicodeError as e:
            self.complain(1045, error=e)
            return None

        if self.method == m.CONNECT:
            parser = mark(authority_form)
        elif self.method == m.OPTIONS:
            parser = (mark(origin_form) | mark(asterisk_form)
                      | mark(absolute_form))
        else:
            parser = mark(origin_form) | mark(absolute_form)

        r = simple_parse(target,
                         parser,
                         self.complain,
                         1045,
                         place=u'request target')
        if okay(r):
            (symbol, _) = r
            return symbol
        else:
            return None
Beispiel #3
0
    def _process_parsed(self, entry, parsed):
        if parsed == u'clear':
            return parsed

        # Parse every parameter's value according to its defined parser.
        for alternative in parsed:
            params = alternative.param.sequence
            for i in range(len(params)):
                (name, value) = params[i]
                parser = alt_svc_param.parser_for(name)
                if parser is not None:
                    value = simple_parse(value, parser,
                                         self.message.complain, 1259,
                                         place=entry, param=name, value=value)
                params[i] = (name, value)

        return parsed
Beispiel #4
0
 def _process_directive(self, entry, directive_with_argument):
     directive, argument = directive_with_argument
     parser = self.knowledge_module.parser_for(directive)
     if argument is None:
         if self.knowledge_module.argument_required(directive):
             self.message.complain(1156, entry=entry, directive=directive)
             argument = Unavailable
     else:
         if self.knowledge_module.no_argument(directive):
             self.message.complain(1157, entry=entry, directive=directive)
             argument = None
         elif parser is not None:
             argument = simple_parse(argument, parser,
                                     self.message.complain, 1158,
                                     place=entry,
                                     directive=directive, value=argument)
     return Parametrized(directive, argument)
Beispiel #5
0
 def target_form(self):
     if self.method == m.CONNECT:
         symbol = mark(authority_form)
     elif self.method == m.OPTIONS:
         symbol = (mark(origin_form) | mark(asterisk_form)
                   | mark(absolute_form))
     else:
         symbol = mark(origin_form) | mark(absolute_form)
     r = simple_parse(self.target,
                      symbol,
                      self.complain,
                      1045,
                      place=u'request target')
     if okay(r):
         (symbol, _) = r
         return symbol
     else:
         return r
Beispiel #6
0
 def _process_directive(self, entry, directive_with_argument):
     directive, argument = directive_with_argument
     parser = self.knowledge_module.parser_for(directive)
     if argument is None:
         if self.knowledge_module.argument_required(directive):
             self.message.complain(1156, entry=entry, directive=directive)
             argument = Unavailable
     else:
         if self.knowledge_module.no_argument(directive):
             self.message.complain(1157, entry=entry, directive=directive)
             argument = None
         elif parser is not None:
             argument = simple_parse(argument,
                                     parser,
                                     self.message.complain,
                                     1158,
                                     place=entry,
                                     directive=directive,
                                     value=argument)
     return Parametrized(directive, argument)
Beispiel #7
0
    def target_form(self):
        try:
            target = self.target.encode('iso-8859-1')
        except UnicodeError as e:
            self.complain(1045, error=e)
            return None

        if self.method == m.CONNECT:
            parser = mark(authority_form)
        elif self.method == m.OPTIONS:
            parser = (mark(origin_form) | mark(asterisk_form) |
                      mark(absolute_form))
        else:
            parser = mark(origin_form) | mark(absolute_form)

        r = simple_parse(target, parser,
                         self.complain, 1045, place=u'request target')
        if okay(r):
            (symbol, _) = r
            return symbol
        else:
            return None
Beispiel #8
0
    def _process_parsed(self, entry, parsed):
        if parsed == u'clear':
            return parsed

        # Parse every parameter's value according to its defined parser.
        parsed = copy.deepcopy(parsed)
        for alternative in parsed:
            params = alternative.param.sequence
            for i in range(len(params)):
                (name, value) = params[i]
                parser = alt_svc_param.parser_for(name)
                if parser is not None:
                    value = simple_parse(value,
                                         parser,
                                         self.message.complain,
                                         1259,
                                         place=entry,
                                         param=name,
                                         value=value)
                params[i] = (name, value)

        return parsed
Beispiel #9
0
def check_request(req):
    """Apply all checks to the request `req`."""
    complain = req.complain
    method = req.method
    version = req.version
    headers = req.headers
    body = req.body

    req.silence(notice_id for (notice_id, in_resp) in headers.httpolice_silence
                if not in_resp)

    message.check_message(req)

    # Check the syntax of request method and target.
    simple_parse(method,
                 rfc7230.method,
                 complain,
                 1292,
                 place=u'request method')
    _ = req.target_form

    if method != method.upper() and method.upper() in m:
        complain(1295, uppercase=Method(method.upper()))

    if body and headers.content_type.is_absent:
        complain(1041)

    if (version in [http10, http11] and method_info.defines_body(method)
            and headers.content_length.is_absent
            and headers.transfer_encoding.is_absent):
        complain(1021)

    if (method_info.defines_body(method) == False) and (body == b'') and \
            headers.content_length.is_present:
        complain(1022)

    if tc.chunked in headers.te:
        complain(1028)

    if version == http2:
        if headers.te and headers.te != [u'trailers']:
            complain(1244, header=headers.te)
    else:
        if headers.te and u'TE' not in headers.connection:
            complain(1029)

    if version == http11 and headers.host.is_absent:
        complain(1031)
    if headers.host.is_present and req.header_entries[0].name != h.host:
        complain(1032)

    for hdr in headers:
        if header.is_for_request(hdr.name) == False:
            complain(1063, header=hdr)
        elif header.is_representation_metadata(hdr.name) and \
                req.has_body == False:
            complain(1053, header=hdr)

    if body:
        if method == m.GET:
            complain(1056)
        elif method == m.HEAD:
            complain(1057)
        elif method == m.DELETE:
            complain(1059)
        elif method == m.CONNECT:
            complain(1061)

    if method == m.OPTIONS and body and headers.content_type.is_absent:
        complain(1062)

    if headers.expect == u'100-continue' and req.has_body == False:
        complain(1066)

    if headers.max_forwards.is_present and method not in [m.OPTIONS, m.TRACE]:
        complain(1067)

    if headers.referer.is_okay:
        if req.is_tls == False:
            parsed = urlparse(headers.referer.value)
            if parsed.scheme == u'https':
                complain(1068)

    if headers.user_agent.is_absent:
        complain(1070)
    elif headers.user_agent.is_okay:
        products = [p for p in headers.user_agent if isinstance(p, Versioned)]
        if products and all(product.is_library(p.item) for p in products):
            complain(1093, library=products[0])

    for x in headers.accept_encoding:
        if x.item in [cc.x_gzip, cc.x_compress] and x.param is not None:
            complain(1116, coding=x.item)

    if headers.if_match.is_okay and headers.if_match != u'*':
        if any(tag.weak for tag in headers.if_match):
            complain(1120)

    if method == m.HEAD:
        for hdr in headers:
            if header.is_precondition(hdr.name):
                complain(1131, header=hdr)

    if method in [m.CONNECT, m.OPTIONS, m.TRACE]:
        for hdr in headers:
            if hdr.name in [
                    h.if_modified_since, h.if_unmodified_since, h.if_match,
                    h.if_none_match, h.if_range
            ]:
                complain(1130, header=hdr)
    elif method not in [m.GET, m.HEAD]:
        if headers.if_modified_since.is_present:
            complain(1122)

    if headers.range.is_present and method != m.GET:
        complain(1132)

    if headers.if_range.is_present and headers.range.is_absent:
        complain(1134)

    if isinstance(headers.if_range.value, EntityTag) and headers.if_range.weak:
        complain(1135)

    for direct in headers.cache_control:
        if cache_directive.is_for_request(direct.item) == False:
            complain(1152, directive=direct.item)
        if direct == cache.no_cache and direct.param is not None:
            complain(1159, directive=direct.item)

    if headers.cache_control.no_cache and u'no-cache' not in headers.pragma:
        complain(1161)

    for warning in headers.warning:
        if 100 <= warning.code <= 199:
            complain(1165, code=warning.code)

    if method_info.is_cacheable(method) == False:
        for direct in headers.cache_control:
            if direct.item in [
                    cache.max_age, cache.max_stale, cache.min_fresh,
                    cache.no_cache, cache.no_store, cache.only_if_cached
            ]:
                complain(1171, directive=direct)

    for direct1, direct2 in [(cache.max_stale, cache.min_fresh),
                             (cache.stale_if_error, cache.min_fresh),
                             (cache.max_stale, cache.no_cache),
                             (cache.max_age, cache.no_cache)]:
        if headers.cache_control[direct1] and headers.cache_control[direct2]:
            complain(1193, directive1=direct1, directive2=direct2)

    for hdr in [headers.authorization, headers.proxy_authorization]:
        if hdr.is_okay:
            scheme, credentials = hdr.value
            if scheme == auth.basic:
                _check_basic_auth(req, hdr, credentials)
            elif scheme == auth.bearer:
                _check_bearer_auth(req, hdr, credentials)
            elif not credentials:
                complain(1274, header=hdr)

    if method == m.PATCH and headers.content_type.is_okay:
        if media_type.is_patch(headers.content_type.item) == False:
            complain(1213)

    for protocol in headers.upgrade:
        if protocol.item == upgrade.h2c:
            if req.is_tls:
                complain(1233)
            if headers.http2_settings.is_absent:
                complain(1231)

    if headers.http2_settings and u'HTTP2-Settings' not in headers.connection:
        complain(1230)

    if headers.http2_settings.is_okay:
        if not _is_urlsafe_base64(headers.http2_settings.value):
            complain(1234)

    if u'access_token' in req.query_params:
        complain(1270)
        if req.is_tls == False:
            complain(1271, where=req.target)
        if not headers.cache_control.no_store:
            complain(1272)

    if okay(req.url_encoded_data) and u'access_token' in req.url_encoded_data:
        if req.is_tls == False:
            complain(1271, where=req.displayable_body)

    for hdr in [
            headers.accept, headers.accept_charset, headers.accept_encoding,
            headers.accept_language
    ]:
        for (wildcard, value) in _accept_subsumptions(hdr):
            complain(1276, header=hdr, wildcard=wildcard, value=value)
            # No need to report more than one subsumption per header.
            break

    for dup_pref in duplicates(name for ((name, _), _) in headers.prefer):
        complain(1285, name=dup_pref)

    if headers.prefer.respond_async and method_info.is_safe(method):
        complain(1287)

    if headers.prefer.return_ == u'minimal' and method == m.GET:
        complain(1288)

    if (pref.return_, u'minimal') in headers.prefer.without_params and \
       (pref.return_, u'representation') in headers.prefer.without_params:
        complain(1289)

    if (pref.handling, u'strict') in headers.prefer.without_params and \
       (pref.handling, u'lenient') in headers.prefer.without_params:
        complain(1290)
Beispiel #10
0
def _check_bearer_challenge(resp, hdr, challenge):
    # The ``Bearer`` authentication scheme is actually defined
    # for proxies as well as for servers (RFC 6750 Section 1).
    # Squid even seems to support it:
    # http://wiki.squid-cache.org/Features/BearerAuthentication .
    # However, generalizing these checks to proxies is kind of a pain,
    # so for now we only handle the ``WWW-Authenticate`` series.
    # If this is ever extended to proxies, the notices must be adjusted.
    # Also note that some text in RFC 6750 only applies to servers
    # (where it says "resource server").
    if hdr.name != h.www_authenticate:
        return

    req = resp.request
    request_has_token = None
    if req:
        if req.is_tls == False:
            resp.complain(1263)

        # Did the request contain a bearer token in one of the defined forms?
        request_has_token = (
            (
                req.headers.authorization.is_okay and
                req.headers.authorization.value.item == auth.bearer
            ) or
            (
                okay(req.url_encoded_data) and
                u'access_token' in req.url_encoded_data
            ) or
            u'access_token' in req.query_params
        )

    params = challenge.param

    if isinstance(params, six.text_type) or not params:
        # ``token68`` form or no parameters at all.
        resp.complain(1264)
        return

    for dupe in params.duplicates():
        if dupe in [u'realm', u'scope', u'error', u'error_description',
                    u'error_uri']:
            resp.complain(1265, param=dupe)

    for param in [u'scope', u'error', u'error_description', u'error_uri']:
        if param in params:
            parser = getattr(rfc6749, param)
            simple_parse(params[param], parser,
                         resp.complain, 1266, param=param, value=params[param])

    if resp.status == st.unauthorized and u'error' not in params and \
            req and req.headers.authorization.is_okay and \
            req.headers.authorization.value.item == auth.bearer:
        # We don't report this if the token was passed in the URI or body,
        # because the server may not implement those forms at all.
        resp.complain(1267)

    if u'error' in params:
        error_code = params[u'error']
        expected_status = {
            u'invalid_request': st.bad_request,
            u'invalid_token': st.unauthorized,
            u'insufficient_scope': st.forbidden,
        }.get(error_code)
        if expected_status and resp.status != expected_status:
            resp.complain(1268, error_code=error_code,
                          expected_status=expected_status)

    if req and req.headers.authorization.is_absent and not request_has_token:
        for param in [u'error', u'error_description', u'error_uri']:
            if param in params:
                resp.complain(1269, param=param)
Beispiel #11
0
def _check_bearer_challenge(resp, hdr, challenge):
    # The ``Bearer`` authentication scheme is actually defined
    # for proxies as well as for servers (RFC 6750 Section 1).
    # Squid even seems to support it:
    # http://wiki.squid-cache.org/Features/BearerAuthentication .
    # However, generalizing these checks to proxies is kind of a pain,
    # so for now we only handle the ``WWW-Authenticate`` series.
    # If this is ever extended to proxies, the notices must be adjusted.
    # Also note that some text in RFC 6750 only applies to servers
    # (where it says "resource server").
    if hdr.name != h.www_authenticate:  # pragma: no cover
        return

    req = resp.request
    request_has_token = None
    if req:
        if req.is_tls == False:
            resp.complain(1263)

        # Did the request contain a bearer token in one of the defined forms?
        request_has_token = ((req.headers.authorization.is_okay and
                              req.headers.authorization.item == auth.bearer)
                             or (okay(req.url_encoded_data)
                                 and u'access_token' in req.url_encoded_data)
                             or u'access_token' in req.query_params)

    params = challenge.param

    if isinstance(params, six.text_type) or not params:
        # ``token68`` form or no parameters at all.
        resp.complain(1264)
        return

    for dupe in params.duplicates():
        if dupe in [
                u'realm', u'scope', u'error', u'error_description',
                u'error_uri'
        ]:
            resp.complain(1265, param=dupe)

    for param in [u'scope', u'error', u'error_description', u'error_uri']:
        if param in params:
            parser = getattr(rfc6749, param)
            simple_parse(params[param],
                         parser,
                         resp.complain,
                         1266,
                         param=param,
                         value=params[param])

    if resp.status == st.unauthorized and u'error' not in params and \
            req and req.headers.authorization.is_okay and \
            req.headers.authorization.item == auth.bearer:
        # We don't report this if the token was passed in the URI or body,
        # because the server may not implement those forms at all.
        resp.complain(1267)

    if u'error' in params:
        error_code = params[u'error']
        expected_status = {
            u'invalid_request': st.bad_request,
            u'invalid_token': st.unauthorized,
            u'insufficient_scope': st.forbidden,
        }.get(error_code)
        if expected_status and resp.status != expected_status:
            resp.complain(1268,
                          error_code=error_code,
                          expected_status=expected_status)

    if req and req.headers.authorization.is_absent and not request_has_token:
        for param in [u'error', u'error_description', u'error_uri']:
            if param in params:
                resp.complain(1269, param=param)
Beispiel #12
0
def check_response_itself(resp):
    resp.silence(notice_id
                 for (notice_id, _) in resp.headers.httpolice_silence)

    message.check_message(resp)

    complain = resp.complain
    version = resp.version
    status = resp.status
    headers = resp.headers
    body = resp.body

    # Check syntax of reason phrase.
    if okay(resp.reason):
        simple_parse(resp.reason,
                     rfc7230.reason_phrase,
                     complain,
                     1294,
                     place=u'reason phrase')

    if not (100 <= status <= 599):
        complain(1167)

    if status.informational and u'close' in headers.connection:
        complain(1198)

    if status.informational or status == st.no_content:
        if headers.transfer_encoding.is_present:
            complain(1018)
        if headers.content_length.is_present:
            complain(1023)

    for hdr in headers:
        if header.is_for_response(hdr.name) == False:
            complain(1064, header=hdr)
        elif header.is_representation_metadata(hdr.name) and \
                status.informational:
            complain(1052, header=hdr)

    if status == st.switching_protocols:
        if headers.upgrade.is_absent:
            complain(1048)
        if version == http2:
            complain(1246)

    if status == st.no_content and body:
        complain(1240)

    if status == st.reset_content and body:
        complain(1076)

    if headers.location.is_absent:
        if status == st.moved_permanently:
            complain(1078)
        if status == st.found:
            complain(1079)
        if status == st.see_other:
            complain(1080)
        if status == st.temporary_redirect:
            complain(1084)
        if status == st.permanent_redirect:
            complain(1205)

    if status == st.use_proxy:
        complain(1082)
    if status == 306:
        complain(1083)
    if status == st.payment_required:
        complain(1088)

    if status == st.method_not_allowed and headers.allow.is_absent:
        complain(1089)

    if status == st.request_timeout and u'close' not in headers.connection:
        complain(1094)

    if headers.date.is_absent and (status.successful or status.redirection
                                   or status.client_error):
        complain(1110)

    if status == st.created and headers.location.is_okay and \
            urlparse(headers.location.value).fragment:
        complain(1111)

    if headers.location.is_present and \
            not status.redirection and status != st.created:
        complain(1112)

    if headers.retry_after.is_present and \
            not status.redirection and \
            status not in [st.payload_too_large, st.service_unavailable,
                           st.too_many_requests]:
        complain(1113)

    if headers.date < headers.last_modified.value:
        complain(1118)

    if status == st.not_modified:
        for hdr in headers:
            # RFC 7232 says "Last-Modified might be useful
            # if the response does not have an ETag field",
            # but really it doesn't hurt even if there is an ETag,
            # and this is widely seen in practice.
            if hdr.name in [h.etag, h.last_modified]:
                continue
            elif header.is_representation_metadata(hdr.name):
                complain(1127, header=hdr)

    if headers.content_range.is_present and \
            status not in [st.partial_content, st.range_not_satisfiable]:
        complain(1147)

    if status == st.partial_content:
        if headers.content_type == media.multipart_byteranges:
            _check_multipart_byteranges(resp)
            if headers.content_range.is_present:
                complain(1143)
        elif headers.content_range.is_absent:
            complain(1138)

    for direct in headers.cache_control:
        if cache_directive.is_for_response(direct.item) == False:
            complain(1153, directive=direct.item)

    if u'no-cache' in headers.pragma:
        complain(1162)

    if resp.from_cache:
        if headers.age.is_absent:
            complain(1166)
        if headers.cache_control.no_cache in [True, []]:
            complain(1175)
        if headers.cache_control.no_store:
            complain(1176)

        if status_code.is_cacheable(status) == NOT_AT_ALL:
            complain(1202)
        elif status_code.is_cacheable(status) == NOT_BY_DEFAULT:
            if headers.expires.is_absent and headers.cache_control.is_absent:
                complain(1177)

    if resp.heuristic_expiration:
        if headers.age > (24 * 60 * 60) and \
                warn.heuristic_expiration not in headers.warning:
            complain(1180)
        if headers.expires.is_present:
            complain(1181)
        elif headers.cache_control.max_age is not None:
            complain(1182)

    if resp.stale:
        if warn.response_is_stale not in headers.warning:
            complain(1186)
        if headers.cache_control.must_revalidate:
            complain(1187)

    for direct1, direct2 in [(cache.public, cache.no_store),
                             (cache.private, cache.public),
                             (cache.private, cache.no_store),
                             (cache.must_revalidate,
                              cache.stale_while_revalidate),
                             (cache.must_revalidate, cache.stale_if_error)]:
        if headers.cache_control[direct1] and headers.cache_control[direct2]:
            complain(1193, directive1=direct1, directive2=direct2)

    for direct1, direct2 in [(cache.max_age, cache.no_cache),
                             (cache.max_age, cache.no_store),
                             (cache.s_maxage, cache.private),
                             (cache.s_maxage, cache.no_cache),
                             (cache.s_maxage, cache.no_store)]:
        if headers.cache_control[direct1] and \
                headers.cache_control[direct2] in [True, []]:
            complain(1238, directive1=direct1, directive2=direct2)

    if headers.vary != u'*' and h.host in headers.vary:
        complain(1235)

    if status == st.unauthorized and headers.www_authenticate.is_absent:
        complain(1194)

    if status == st.proxy_authentication_required and \
            headers.proxy_authenticate.is_absent:
        complain(1195)

    for hdr in [headers.www_authenticate, headers.proxy_authenticate]:
        for challenge in hdr:
            if challenge.item == auth.basic:
                _check_basic_challenge(resp, hdr, challenge)
            if challenge.item == auth.bearer:
                _check_bearer_challenge(resp, hdr, challenge)

    if headers.allow.is_present and headers.accept_patch.is_present and \
            m.PATCH not in headers.allow:
        complain(1217)

    if headers.strict_transport_security.is_okay:
        if hsts.max_age not in headers.strict_transport_security:
            complain(1218)
        if headers.strict_transport_security.max_age == 0 and \
                headers.strict_transport_security.includesubdomains:
            complain(1219)
        for dupe in duplicates(d.item
                               for d in headers.strict_transport_security):
            complain(1220, directive=dupe)

    for patch_type in headers.accept_patch:
        if media_type.is_patch(patch_type.item) == False:
            complain(1227, patch_type=patch_type.item)

    if resp.transformed_by_proxy and headers.via.is_absent:
        complain(1046)

    if status == st.unavailable_for_legal_reasons:
        if not any(rel.blocked_by in link.param.get(u'rel', [])
                   for link in headers.link):
            complain(1243)

    if headers.content_disposition.is_okay:
        params = headers.content_disposition.param
        for name in params.duplicates():
            complain(1247, param=name)

        filename = params.get(u'filename')
        if filename is not None:
            if contains_percent_encodes(filename):
                complain(1248)
            if u'"' in filename or u'\\' in filename:
                # These must have been backslash-escaped.
                complain(1249)
            if not is_ascii(filename):
                complain(1250)

        filename_ext = params.get(u'filename*')
        if filename_ext is not None:
            if filename is None:
                complain(1251)
            elif params.index(u'filename*') < params.index(u'filename'):
                complain(1252)
            if filename_ext.charset != u'UTF-8':
                complain(1255)

    if headers.alt_svc.is_present:
        if version == http2:
            complain(1258)
        if status == st.misdirected_request:
            complain(1260)
Beispiel #13
0
def check_message(msg):
    """Run all checks that apply to any message (both request and response)."""
    complain = msg.complain
    version = msg.version
    headers = msg.headers

    for hdr in headers:
        # Check the header name syntax.
        simple_parse(hdr.name, rfc7230.field_name,
                     complain, 1293, header=hdr, place=u'field name')
        # Force parsing every header present in the message
        # according to its syntax rules.
        _ = hdr.value
        if header.deprecated(hdr.name):
            complain(1197, header=hdr)
        if hdr.name.startswith(u'X-') and hdr.name not in h:    # not in known
            complain(1277, header=hdr)

    # Force checking the payload according to various rules.
    _ = msg.decoded_body
    _ = msg.unicode_body
    _ = msg.json_data
    _ = msg.xml_data
    _ = msg.multipart_data
    _ = msg.url_encoded_data

    if version == http11 and headers.trailer.is_present and \
            tc.chunked not in headers.transfer_encoding:
        # HTTP/2 supports trailers but has no notion of "chunked".
        complain(1054)

    for entry in msg.trailer_entries:
        if entry.name not in headers.trailer:
            complain(1030, header=entry)

    if headers.transfer_encoding.is_present and \
            headers.content_length.is_present:
        complain(1020)

    for opt in headers.connection:
        if header.is_bad_for_connection(FieldName(opt)):
            complain(1034, header=headers[FieldName(opt)])

    if headers.content_type.is_okay:
        if media_type.deprecated(headers.content_type.item):
            complain(1035)
        for dupe in headers.content_type.param.duplicates():
            complain(1042, param=dupe)

    if headers.content_type == media.application_json and \
            u'charset' in headers.content_type.param:
        complain(1280, header=headers.content_type)

    if headers.upgrade.is_present and u'upgrade' not in headers.connection:
        complain(1050)

    if headers.date > datetime.utcnow() + timedelta(seconds=10):
        complain(1109)

    for warning in headers.warning:
        if warning.code < 100 or warning.code > 299:
            complain(1163, code=warning.code)
        if okay(warning.date) and headers.date != warning.date:
            complain(1164, code=warning.code)

    if msg.transformed_by_proxy:
        if warn.transformation_applied not in headers.warning:
            complain(1191)
        if headers.cache_control.no_transform:
            complain(1192)

    for pragma in headers.pragma:
        if pragma != u'no-cache':
            complain(1160, pragma=pragma.item)

    if version == http2:
        for hdr in headers:
            if hdr.name in [h.connection, h.transfer_encoding, h.keep_alive]:
                complain(1244, header=hdr)
            elif hdr.name == h.upgrade:
                complain(1245)

    for protocol in headers.upgrade:
        if protocol.item == u'h2':
            complain(1228)
        if protocol.item == upgrade.h2c and msg.is_tls:
            complain(1233)
Beispiel #14
0
def _check_alt_authority(complain, value):
    return simple_parse(value,
                        maybe_str(uri_host) + ':' + port,
                        complain,
                        1257,
                        authority=value)
Beispiel #15
0
def _check_alt_authority(complain, value):
    return simple_parse(value,
                        maybe_str(uri_host) + ':' + port,
                        complain, 1257, authority=value)