web/http_headers.py
changeset 9571 aaf83cc07eed
parent 9569 ac0bc417b55f
child 9572 73b2410bdadc
equal deleted inserted replaced
9570:14452b344d19 9571:aaf83cc07eed
     6 
     6 
     7 import types, time
     7 import types, time
     8 from calendar import timegm
     8 from calendar import timegm
     9 import base64
     9 import base64
    10 import re
    10 import re
       
    11 import urlparse
    11 
    12 
    12 def dashCapitalize(s):
    13 def dashCapitalize(s):
    13     ''' Capitalize a string, making sure to treat - as a word seperator '''
    14     ''' Capitalize a string, making sure to treat - as a word seperator '''
    14     return '-'.join([ x.capitalize() for x in s.split('-')])
    15     return '-'.join([ x.capitalize() for x in s.split('-')])
    15 
    16 
   386         return seq
   387         return seq
   387     if len(seq) != 1:
   388     if len(seq) != 1:
   388         raise ValueError('single value required, not %s' % seq)
   389         raise ValueError('single value required, not %s' % seq)
   389     return seq[0]
   390     return seq[0]
   390 
   391 
       
   392 def parseHTTPMethod(method):
       
   393     """Ensure a HTTP method is valid according the rfc2616, but extension-method ones"""
       
   394     method = method.strip()
       
   395     if method not in ("OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE",
       
   396                       "TRACE", "CONNECT"):
       
   397         raise ValueError('Unsupported HTTP method %s' % method)
       
   398     return method
       
   399 
       
   400 def parseAllowOrigin(origin):
       
   401     """Ensure origin is a valid URL-base stuff, or null"""
       
   402     if origin == 'null':
       
   403         return origin
       
   404     p = urlparse.urlparse(origin)
       
   405     if p.params or p.query or p.username or p.path not in ('', '/'):
       
   406         raise ValueError('Incorrect Accept-Control-Allow-Origin value %s' % origin)
       
   407     if p.scheme not in ('http', 'https'):
       
   408         raise ValueError('Unsupported Accept-Control-Allow-Origin URL scheme %s' % origin)
       
   409     if not p.netloc:
       
   410         raise ValueError('Accept-Control-Allow-Origin: host name cannot be unset  (%s)' % origin)
       
   411     return origin
       
   412 
       
   413 def parseAllowCreds(cred):
       
   414     """Can be "true" """
       
   415     if cred:
       
   416         cred = cred.lower()
       
   417     if cred and cred != 'true':
       
   418         raise ValueError('Accept-Control-Allow-Credentials can only be "true" (%s)' % cred)
       
   419     return cred
       
   420 
   391 ##### Generation utilities
   421 ##### Generation utilities
   392 def quoteString(s):
   422 def quoteString(s):
   393     return '"%s"' % s.replace('\\', '\\\\').replace('"', '\\"')
   423     return '"%s"' % s.replace('\\', '\\\\').replace('"', '\\"')
   394 
   424 
   395 def listGenerator(fun):
   425 def listGenerator(fun):
  1452 parser_request_headers = {
  1482 parser_request_headers = {
  1453     'Accept': (tokenize, listParser(parseAccept), dict),
  1483     'Accept': (tokenize, listParser(parseAccept), dict),
  1454     'Accept-Charset': (tokenize, listParser(parseAcceptQvalue), dict, addDefaultCharset),
  1484     'Accept-Charset': (tokenize, listParser(parseAcceptQvalue), dict, addDefaultCharset),
  1455     'Accept-Encoding':(tokenize, listParser(parseAcceptQvalue), dict, addDefaultEncoding),
  1485     'Accept-Encoding':(tokenize, listParser(parseAcceptQvalue), dict, addDefaultEncoding),
  1456     'Accept-Language':(tokenize, listParser(parseAcceptQvalue), dict),
  1486     'Accept-Language':(tokenize, listParser(parseAcceptQvalue), dict),
       
  1487     'Access-Control-Allow-Origin': (last, parseAllowOrigin,),
       
  1488     'Access-Control-Allow-Credentials': (last, parseAllowCreds,),
       
  1489     'Access-Control-Allow-Methods': (tokenize, listParser(parseHTTPMethod), list),
       
  1490     'Access-Control-Request-Method': (parseHTTPMethod, ),
       
  1491     'Access-Control-Request-Headers': (filterTokens, ),
       
  1492     'Access-Control-Expose-Headers': (filterTokens, ),
  1457     'Authorization': (last, parseAuthorization),
  1493     'Authorization': (last, parseAuthorization),
  1458     'Cookie':(parseCookie,),
  1494     'Cookie':(parseCookie,),
  1459     'Expect':(tokenize, listParser(parseExpect), dict),
  1495     'Expect':(tokenize, listParser(parseExpect), dict),
  1460     'From':(last,),
  1496     'From':(last,),
  1461     'Host':(last,),
  1497     'Host':(last,),
  1463     'If-Modified-Since':(last, parseIfModifiedSince),
  1499     'If-Modified-Since':(last, parseIfModifiedSince),
  1464     'If-None-Match':(tokenize, listParser(parseStarOrETag), list),
  1500     'If-None-Match':(tokenize, listParser(parseStarOrETag), list),
  1465     'If-Range':(parseIfRange,),
  1501     'If-Range':(parseIfRange,),
  1466     'If-Unmodified-Since':(last,parseDateTime),
  1502     'If-Unmodified-Since':(last,parseDateTime),
  1467     'Max-Forwards':(last,int),
  1503     'Max-Forwards':(last,int),
       
  1504     'Origin': (last,),
  1468 #    'Proxy-Authorization':str, # what is "credentials"
  1505 #    'Proxy-Authorization':str, # what is "credentials"
  1469     'Range':(tokenize, parseRange),
  1506     'Range':(tokenize, parseRange),
  1470     'Referer':(last,str), # TODO: URI object?
  1507     'Referer':(last,str), # TODO: URI object?
  1471     'TE':(tokenize, listParser(parseAcceptQvalue), dict),
  1508     'TE':(tokenize, listParser(parseAcceptQvalue), dict),
  1472     'User-Agent':(last,str),
  1509     'User-Agent':(last,str),
  1475 generator_request_headers = {
  1512 generator_request_headers = {
  1476     'Accept': (iteritems,listGenerator(generateAccept),singleHeader),
  1513     'Accept': (iteritems,listGenerator(generateAccept),singleHeader),
  1477     'Accept-Charset': (iteritems, listGenerator(generateAcceptQvalue),singleHeader),
  1514     'Accept-Charset': (iteritems, listGenerator(generateAcceptQvalue),singleHeader),
  1478     'Accept-Encoding': (iteritems, removeDefaultEncoding, listGenerator(generateAcceptQvalue),singleHeader),
  1515     'Accept-Encoding': (iteritems, removeDefaultEncoding, listGenerator(generateAcceptQvalue),singleHeader),
  1479     'Accept-Language': (iteritems, listGenerator(generateAcceptQvalue),singleHeader),
  1516     'Accept-Language': (iteritems, listGenerator(generateAcceptQvalue),singleHeader),
       
  1517     'Access-Control-Request-Method': (unique, str, singleHeader, ),
       
  1518     'Access-Control-Expose-Headers': (listGenerator(str), ),
       
  1519     'Access-Control-Allow-Headers': (listGenerator(str), ),
  1480     'Authorization': (generateAuthorization,), # what is "credentials"
  1520     'Authorization': (generateAuthorization,), # what is "credentials"
  1481     'Cookie':(generateCookie,singleHeader),
  1521     'Cookie':(generateCookie,singleHeader),
  1482     'Expect':(iteritems, listGenerator(generateExpect), singleHeader),
  1522     'Expect':(iteritems, listGenerator(generateExpect), singleHeader),
  1483     'From':(unique, str,singleHeader),
  1523     'From':(unique, str,singleHeader),
  1484     'Host':(unique, str,singleHeader),
  1524     'Host':(unique, str,singleHeader),
       
  1525     'Origin': (unique, str, singleHeader),
  1485     'If-Match':(listGenerator(generateStarOrETag), singleHeader),
  1526     'If-Match':(listGenerator(generateStarOrETag), singleHeader),
  1486     'If-Modified-Since':(generateDateTime,singleHeader),
  1527     'If-Modified-Since':(generateDateTime,singleHeader),
  1487     'If-None-Match':(listGenerator(generateStarOrETag), singleHeader),
  1528     'If-None-Match':(listGenerator(generateStarOrETag), singleHeader),
  1488     'If-Range':(generateIfRange, singleHeader),
  1529     'If-Range':(generateIfRange, singleHeader),
  1489     'If-Unmodified-Since':(generateDateTime,singleHeader),
  1530     'If-Unmodified-Since':(generateDateTime,singleHeader),