Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 1523

Show
Ignore:
Timestamp:
12/11/06 16:16:56
Author:
fumanchu
Message:

2.x backport of [1330] (new cptools.referer) and [1422] (new cptools.accept(media)). See test_misc_tools.py for usage.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/cherrypy-2.x/cherrypy/lib/cptools.py

    r1518 r1523  
    99 
    1010import os 
     11import re 
    1112import stat as _stat 
    1213import sys 
     
    434435    return Builder().build(getObj(s)) 
    435436 
     437 
     438def referer(pattern, accept=True, accept_missing=False, error=403, 
     439            message='Forbidden Referer header.'): 
     440    """Raise HTTPError if Referer header does not pass our test. 
     441     
     442    pattern: a regular expression pattern to test against the Referer. 
     443    accept: if True, the Referer must match the pattern; if False, 
     444        the Referer must NOT match the pattern. 
     445    accept_missing: if True, permit requests with no Referer header. 
     446    error: the HTTP error code to return to the client on failure. 
     447    message: a string to include in the response body on failure. 
     448    """ 
     449    try: 
     450        match = bool(re.match(pattern, cherrypy.request.headers['Referer'])) 
     451        if accept == match: 
     452            return 
     453    except KeyError: 
     454        if accept_missing: 
     455            return 
     456     
     457    raise cherrypy.HTTPError(error, message) 
     458 
     459def accept(media=None): 
     460    """Return the client's preferred media-type (from the given Content-Types). 
     461     
     462    If 'media' is None (the default), no test will be performed. 
     463     
     464    If 'media' is provided, it should be the Content-Type value (as a string) 
     465    or values (as a list or tuple of strings) which the current request 
     466    can emit. The client's acceptable media ranges (as declared in the 
     467    Accept request header) will be matched in order to these Content-Type 
     468    values; the first such string is returned. That is, the return value 
     469    will always be one of the strings provided in the 'media' arg (or None 
     470    if 'media' is None). 
     471     
     472    If no match is found, then HTTPError 406 (Not Acceptable) is raised. 
     473    Note that most web browsers send */* as a (low-quality) acceptable 
     474    media range, which should match any Content-Type. In addition, "...if 
     475    no Accept header field is present, then it is assumed that the client 
     476    accepts all media types." 
     477     
     478    Matching types are checked in order of client preference first, 
     479    and then in the order of the given 'media' values. 
     480     
     481    Note that this function does not honor accept-params (other than "q"). 
     482    """ 
     483    if not media: 
     484        return 
     485    if isinstance(media, basestring): 
     486        media = [media] 
     487     
     488    # Parse the Accept request header, and try to match one 
     489    # of the requested media-ranges (in order of preference). 
     490    ranges = cherrypy.request.headers.elements('Accept') 
     491    if not ranges: 
     492        # Any media type is acceptable. 
     493        return media[0] 
     494    else: 
     495        # Note that 'ranges' is sorted in order of preference 
     496        for element in ranges: 
     497            if element.qvalue > 0: 
     498                if element.value == "*/*": 
     499                    # Matches any type or subtype 
     500                    return media[0] 
     501                elif element.value.endswith("/*"): 
     502                    # Matches any subtype 
     503                    mtype = element.value[:-1]  # Keep the slash 
     504                    for m in media: 
     505                        if m.startswith(mtype): 
     506                            return m 
     507                else: 
     508                    # Matches exact value 
     509                    if element.value in media: 
     510                        return element.value 
     511     
     512    # No suitable media-range found. 
     513    ah = cherrypy.request.headers.get('Accept') 
     514    if ah is None: 
     515        msg = "Your client did not send an Accept header." 
     516    else: 
     517        msg = "Your client sent this Accept header: %s." % ah 
     518    msg += (" But this resource only emits these media types: %s." % 
     519            ", ".join(media)) 
     520    raise cherrypy.HTTPError(406, msg) 
     521 
  • branches/cherrypy-2.x/cherrypy/test/test.py

    r1520 r1523  
    300300        'test_gzip_filter', 
    301301        'test_logdebuginfo_filter', 
     302        'test_misc_tools', 
    302303        'test_objectmapping', 
    303304        'test_response_headers_filter', 

Hosted by WebFaction

Log in as guest/cpguest to create tickets