wsgi/request.py
changeset 8314 cfd6ab461849
parent 8309 48ef505aa9f9
child 8316 d5b1b75805dd
equal deleted inserted replaced
8313:386b6313de28 8314:cfd6ab461849
    30 
    30 
    31 from logilab.common.decorators import cached
    31 from logilab.common.decorators import cached
    32 
    32 
    33 from cubicweb.web.request import CubicWebRequestBase
    33 from cubicweb.web.request import CubicWebRequestBase
    34 from cubicweb.wsgi import (pformat, qs2dict, safe_copyfileobj, parse_file_upload,
    34 from cubicweb.wsgi import (pformat, qs2dict, safe_copyfileobj, parse_file_upload,
    35                         normalize_header)
    35                            normalize_header)
       
    36 from cubicweb.web.http_headers import Headers
    36 
    37 
    37 
    38 
    38 
    39 
    39 class CubicWebWsgiRequest(CubicWebRequestBase):
    40 class CubicWebWsgiRequest(CubicWebRequestBase):
    40     """most of this code COMES FROM DJANO
    41     """most of this code COMES FROM DJANO
    42 
    43 
    43     def __init__(self, environ, vreg):
    44     def __init__(self, environ, vreg):
    44         self.environ = environ
    45         self.environ = environ
    45         self.path = environ['PATH_INFO']
    46         self.path = environ['PATH_INFO']
    46         self.method = environ['REQUEST_METHOD'].upper()
    47         self.method = environ['REQUEST_METHOD'].upper()
    47         self._headers = dict([(normalize_header(k[5:]), v) for k, v in self.environ.items()
    48 
    48                               if k.startswith('HTTP_')])
    49         headers_in = dict((normalize_header(k[5:]), v) for k, v in self.environ.items()
       
    50                           if k.startswith('HTTP_'))
    49         https = environ.get("HTTPS") in ('yes', 'on', '1')
    51         https = environ.get("HTTPS") in ('yes', 'on', '1')
    50         post, files = self.get_posted_data()
    52         post, files = self.get_posted_data()
    51         super(CubicWebWsgiRequest, self).__init__(vreg, https, post)
    53 
       
    54         super(CubicWebWsgiRequest, self).__init__(vreg, https, post,
       
    55                                                   headers= headers_in)
    52         if files is not None:
    56         if files is not None:
    53             for key, (name, _, stream) in files.iteritems():
    57             for key, (name, _, stream) in files.iteritems():
    54                 name = unicode(name, self.encoding)
    58                 if name is not None:
       
    59                     name = unicode(name, self.encoding)
    55                 self.form[key] = (name, stream)
    60                 self.form[key] = (name, stream)
    56         # prepare output headers
       
    57         self.headers_out = {}
       
    58 
    61 
    59     def __repr__(self):
    62     def __repr__(self):
    60         # Since this is called as part of error handling, we need to be very
    63         # Since this is called as part of error handling, we need to be very
    61         # robust against potentially malformed input.
    64         # robust against potentially malformed input.
    62         form = pformat(self.form)
    65         form = pformat(self.form)
    85             if qs:
    88             if qs:
    86                 return '%s?%s' % (path, qs)
    89                 return '%s?%s' % (path, qs)
    87 
    90 
    88         return path
    91         return path
    89 
    92 
    90     def get_header(self, header, default=None):
       
    91         """return the value associated with the given input HTTP header,
       
    92         raise KeyError if the header is not set
       
    93         """
       
    94         return self._headers.get(normalize_header(header), default)
       
    95 
       
    96     def set_header(self, header, value, raw=True):
       
    97         """set an output HTTP header"""
       
    98         assert raw, "don't know anything about non-raw headers for wsgi requests"
       
    99         self.headers_out[header] = value
       
   100 
       
   101     def add_header(self, header, value):
       
   102         """add an output HTTP header"""
       
   103         self.headers_out[header] = value
       
   104 
       
   105     def remove_header(self, header):
       
   106         """remove an output HTTP header"""
       
   107         self.headers_out.pop(header, None)
       
   108 
       
   109     def header_if_modified_since(self):
       
   110         """If the HTTP header If-modified-since is set, return the equivalent
       
   111         mx date time value (GMT), else return None
       
   112         """
       
   113         return None
       
   114 
       
   115     ## wsgi request helpers ###################################################
    93     ## wsgi request helpers ###################################################
   116 
    94 
   117     def instance_uri(self):
    95     def instance_uri(self):
   118         """Return the instance's base URI (no PATH_INFO or QUERY_STRING)
    96         """Return the instance's base URI (no PATH_INFO or QUERY_STRING)
   119 
    97 
   140     def is_secure(self):
   118     def is_secure(self):
   141         return 'wsgi.url_scheme' in self.environ \
   119         return 'wsgi.url_scheme' in self.environ \
   142             and self.environ['wsgi.url_scheme'] == 'https'
   120             and self.environ['wsgi.url_scheme'] == 'https'
   143 
   121 
   144     def get_posted_data(self):
   122     def get_posted_data(self):
       
   123         # The WSGI spec says 'QUERY_STRING' may be absent.
       
   124         post = qs2dict(self.environ.get('QUERY_STRING', ''))
   145         files = None
   125         files = None
   146         if self.method == 'POST':
   126         if self.method == 'POST':
   147             if self.environ.get('CONTENT_TYPE', '').startswith('multipart'):
   127             if self.environ.get('CONTENT_TYPE', '').startswith('multipart'):
   148                 header_dict = dict((normalize_header(k[5:]), v)
   128                 header_dict = dict((normalize_header(k[5:]), v)
   149                                    for k, v in self.environ.items()
   129                                    for k, v in self.environ.items()
   150                                    if k.startswith('HTTP_'))
   130                                    if k.startswith('HTTP_'))
   151                 header_dict['Content-Type'] = self.environ.get('CONTENT_TYPE', '')
   131                 header_dict['Content-Type'] = self.environ.get('CONTENT_TYPE', '')
   152                 post, files = parse_file_upload(header_dict, self.raw_post_data)
   132                 post_, files = parse_file_upload(header_dict, self.raw_post_data)
       
   133                 post.update(post_)
   153             else:
   134             else:
   154                 post = qs2dict(self.raw_post_data)
   135                 post.update(qs2dict(self.raw_post_data))
   155         else:
       
   156             # The WSGI spec says 'QUERY_STRING' may be absent.
       
   157             post = qs2dict(self.environ.get('QUERY_STRING', ''))
       
   158         return post, files
   136         return post, files
   159 
   137 
   160     @property
   138     @property
   161     @cached
   139     @cached
   162     def raw_post_data(self):
   140     def raw_post_data(self):
   175 
   153 
   176     def _validate_cache(self):
   154     def _validate_cache(self):
   177         """raise a `DirectResponse` exception if a cached page along the way
   155         """raise a `DirectResponse` exception if a cached page along the way
   178         exists and is still usable
   156         exists and is still usable
   179         """
   157         """
   180         # XXX
   158         if self.get_header('Cache-Control') in ('max-age=0', 'no-cache'):
   181 #         if self.get_header('Cache-Control') in ('max-age=0', 'no-cache'):
   159             # Expires header seems to be required by IE7
   182 #             # Expires header seems to be required by IE7
   160             self.add_header('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
   183 #             self.add_header('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
   161             return
   184 #             return
       
   185 #         try:
   162 #         try:
   186 #             http.checkPreconditions(self._twreq, _PreResponse(self))
   163 #             http.checkPreconditions(self._twreq, _PreResponse(self))
   187 #         except http.HTTPError, ex:
   164 #         except http.HTTPError, ex:
   188 #             self.info('valid http cache, no actual rendering')
   165 #             self.info('valid http cache, no actual rendering')
   189 #             raise DirectResponse(ex.response)
   166 #             raise DirectResponse(ex.response)