示例#1
0
文件: idp.py 项目: jkakavas/pysaml2
def set_cookie(name, _, *args):
    cookie = SimpleCookie()
    cookie[name] = base64.b64encode(":".join(args))
    cookie[name]['path'] = "/"
    cookie[name]["expires"] = _expiration(5)  # 5 minutes from now
    logger.debug("Cookie expires: %s", cookie[name]["expires"])
    return tuple(cookie.output().split(": ", 1))
示例#2
0
def set_cookie(name, _, *args):
    cookie = SimpleCookie()
    cookie[name] = base64.b64encode(":".join(args))
    cookie[name]['path'] = "/"
    cookie[name]["expires"] = _expiration(5)  # 5 minutes from now
    logger.debug("Cookie expires: %s", cookie[name]["expires"])
    return tuple(cookie.output().split(": ", 1))
示例#3
0
def make_cookie(name, load, seed, expire=0, domain="", path="", timestamp=""):
    """
    Create and return a cookie

    :param name: Cookie name
    :param load: Cookie load
    :param seed: A seed for the HMAC function
    :param expire: Number of minutes before this cookie goes stale
    :param domain: The domain of the cookie
    :param path: The path specification for the cookie
    :return: A tuple to be added to headers
    """
    cookie = SimpleCookie()
    if not timestamp:
        timestamp = str(int(time.mktime(time.gmtime())))
    signature = cookie_signature(seed, load, timestamp)
    cookie[name] = "|".join([load, timestamp, signature])
    if path:
        cookie[name]["path"] = path
    if domain:
        cookie[name]["domain"] = domain
    if expire:
        cookie[name]["expires"] = _expiration(expire,
                                              "%a, %d-%b-%Y %H:%M:%S GMT")

    return tuple(cookie.output().split(": ", 1))
示例#4
0
    def build_wsgi_environ(self,
                           method,
                           path,
                           body,
                           content_type,
                           cookies=None,
                           **kw):

        # NOTE that in Pando (request.py make_franken_headers) only headers
        # beginning with ``HTTP`` are included in the request - and those are
        # changed to no longer include ``HTTP``. There are currently 2
        # exceptions to this: ``'CONTENT_TYPE'``, ``'CONTENT_LENGTH'`` which
        # are explicitly checked for.

        if isinstance(cookies, dict) and not isinstance(cookies, SimpleCookie):
            cookies, d = SimpleCookie(), cookies
            for k, v in d.items():
                cookies[str(k)] = str(v)

        typecheck(path, (bytes, text_type), method, text_type, content_type,
                  bytes, body, bytes)
        environ = {}
        environ[b'CONTENT_TYPE'] = content_type
        if cookies is not None:
            environ[b'HTTP_COOKIE'] = cookies.output(header='', sep='; ')
        environ[b'HTTP_HOST'] = b'localhost'
        environ[b'PATH_INFO'] = path.encode(
            'ascii') if type(path) != bytes else path
        environ[b'REMOTE_ADDR'] = b'0.0.0.0'
        environ[b'REQUEST_METHOD'] = method.encode('ascii')
        environ[b'SERVER_PROTOCOL'] = b'HTTP/1.1'
        environ[b'wsgi.input'] = BytesIO(body)
        environ[b'HTTP_CONTENT_LENGTH'] = str(len(body)).encode('ascii')
        environ.update((k.encode('ascii'), v) for k, v in kw.items())
        return environ
示例#5
0
def make_cookie(name, load, seed, expire=0, domain="", path="",
                timestamp=""):
    """
    Create and return a cookie

    :param name: Cookie name
    :param load: Cookie load
    :param seed: A seed for the HMAC function
    :param expire: Number of minutes before this cookie goes stale
    :param domain: The domain of the cookie
    :param path: The path specification for the cookie
    :return: A tuple to be added to headers
    """
    cookie = SimpleCookie()
    if not timestamp:
        timestamp = str(int(time.mktime(time.gmtime())))
    signature = cookie_signature(seed, load, timestamp)
    cookie[name] = "|".join([load, timestamp, signature])
    if path:
        cookie[name]["path"] = path
    if domain:
        cookie[name]["domain"] = domain
    if expire:
        cookie[name]["expires"] = _expiration(expire,
                                              "%a, %d-%b-%Y %H:%M:%S GMT")

    return tuple(cookie.output().split(": ", 1))
示例#6
0
    def build_wsgi_environ(self, method, path, body, content_type, cookies=None, **kw):

        # NOTE that in Pando (request.py make_franken_headers) only headers
        # beginning with ``HTTP`` are included in the request - and those are
        # changed to no longer include ``HTTP``. There are currently 2
        # exceptions to this: ``'CONTENT_TYPE'``, ``'CONTENT_LENGTH'`` which
        # are explicitly checked for.

        if isinstance(cookies, dict) and not isinstance(cookies, SimpleCookie):
            cookies, d = SimpleCookie(), cookies
            for k, v in d.items():
                cookies[str(k)] = str(v)

        typecheck(path, (bytes, text_type), method, text_type, content_type, bytes, body, bytes)
        environ = {}
        environ[b'CONTENT_TYPE'] = content_type
        if cookies is not None:
            environ[b'HTTP_COOKIE'] = cookies.output(header='', sep='; ')
        environ[b'HTTP_HOST'] = b'localhost'
        environ[b'PATH_INFO'] = path.encode('ascii') if type(path) != bytes else path
        environ[b'REMOTE_ADDR'] = b'0.0.0.0'
        environ[b'REQUEST_METHOD'] = method.encode('ascii')
        environ[b'SERVER_PROTOCOL'] = b'HTTP/1.1'
        environ[b'wsgi.input'] = BytesIO(body)
        environ[b'HTTP_CONTENT_LENGTH'] = str(len(body)).encode('ascii')
        environ.update((k.encode('ascii'), v) for k, v in kw.items())
        return environ
示例#7
0
 def set_cookie(self, user):
     uid = rndstr(32)
     self.uid2user[uid] = user
     cookie = SimpleCookie()
     cookie[self.cookie_name] = uid
     cookie[self.cookie_name]["path"] = "/"
     cookie[self.cookie_name]["expires"] = _expiration(480)
     logger.debug("Cookie expires: %s", cookie[self.cookie_name]["expires"])
     return cookie.output().split(": ", 1)
示例#8
0
文件: sp.py 项目: Lefford/pysaml2
 def set_cookie(self, user):
     uid = rndstr(32)
     self.uid2user[uid] = user
     cookie = SimpleCookie()
     cookie[self.cookie_name] = uid
     cookie[self.cookie_name]['path'] = "/"
     cookie[self.cookie_name]["expires"] = _expiration(480)
     logger.debug("Cookie expires: %s", cookie[self.cookie_name]["expires"])
     return cookie.output().encode("UTF-8").split(": ", 1)
示例#9
0
def delete_cookie(environ, name):
    kaka = environ.get("HTTP_COOKIE", "")
    logger.debug("delete KAKA: %s", kaka)
    if kaka:
        cookie_obj = SimpleCookie(kaka)
        morsel = cookie_obj.get(name, None)
        cookie = SimpleCookie()
        cookie[name] = ""
        cookie[name]["path"] = "/"
        logger.debug("Expire: %s", morsel)
        cookie[name]["expires"] = _expiration("dawn")
        return tuple(cookie.output().split(": ", 1))
    return None
示例#10
0
def delete_cookie(environ, name):
    kaka = environ.get("HTTP_COOKIE", '')
    logger.debug("delete KAKA: %s", kaka)
    if kaka:
        cookie_obj = SimpleCookie(kaka)
        morsel = cookie_obj.get(name, None)
        cookie = SimpleCookie()
        cookie[name] = ""
        cookie[name]['path'] = "/"
        logger.debug("Expire: %s", morsel)
        cookie[name]["expires"] = _expiration("dawn")
        return tuple(cookie.output().split(": ", 1))
    return None
示例#11
0
文件: sp.py 项目: Lefford/pysaml2
 def delete_cookie(self, environ):
     cookie = environ.get("HTTP_COOKIE", '')
     logger.debug("delete cookie: %s", cookie)
     if cookie:
         _name = self.cookie_name
         cookie_obj = SimpleCookie(cookie)
         morsel = cookie_obj.get(_name, None)
         cookie = SimpleCookie()
         cookie[_name] = ""
         cookie[_name]['path'] = "/"
         logger.debug("Expire: %s", morsel)
         cookie[_name]["expires"] = _expiration("now")
         return cookie.output().split(": ", 1)
     return None
示例#12
0
 def delete_cookie(self, environ):
     cookie = environ.get("HTTP_COOKIE", "")
     logger.debug("delete cookie: %s", cookie)
     if cookie:
         _name = self.cookie_name
         cookie_obj = SimpleCookie(cookie)
         morsel = cookie_obj.get(_name, None)
         cookie = SimpleCookie()
         cookie[_name] = ""
         cookie[_name]["path"] = "/"
         logger.debug("Expire: %s", morsel)
         cookie[_name]["expires"] = _expiration("now")
         return cookie.output().split(": ", 1)
     return None
示例#13
0
def set_cookie(name, _, *args):
    cookie = SimpleCookie()

    data = ":".join(args)
    if not isinstance(data, six.binary_type):
        data = data.encode("ascii")

    data64 = base64.b64encode(data)
    if not isinstance(data64, six.string_types):
        data64 = data64.decode("ascii")

    cookie[name] = data64
    cookie[name]["path"] = "/"
    cookie[name]["expires"] = _expiration(5)  # 5 minutes from now
    logger.debug("Cookie expires: %s", cookie[name]["expires"])
    return tuple(cookie.output().split(": ", 1))
示例#14
0
    def request(self, sitename, path, method='GET', data=None):
        url = self.base_url + '/' + sitename + path
        path = '/' + sitename + path
        if isinstance(data, dict):
            for k in data.keys():
                if data[k] is None: del data[k]

        if web.config.debug:
            web.ctx.infobase_req_count = 1 + web.ctx.get(
                'infobase_req_count', 0)
            a = time.time()
            _path = path
            _data = data

        headers = {}

        if data:
            if isinstance(data, dict):
                data = dict(
                    (web.safestr(k), web.safestr(v)) for k, v in data.items())
                data = urlencode(data)
                headers['Content-Type'] = 'application/x-www-form-urlencoded'
            if method == 'GET':
                path += '?' + data
                data = None

        stats.begin("infobase", path=path, method=method, data=data)
        conn = HTTPConnection(self.base_url)
        env = web.ctx.get('env') or {}

        if self.auth_token:
            c = SimpleCookie()
            c['infobase_auth_token'] = quote(self.auth_token)
            cookie = c.output(header='').strip()
            headers['Cookie'] = cookie

        # pass the remote ip to the infobase server
        headers['X-REMOTE-IP'] = web.ctx.get('ip')

        try:
            conn.request(method, path, data, headers=headers)
            response = conn.getresponse()
            stats.end()
        except socket.error:
            stats.end(error=True)
            logger.error("Unable to connect to infobase server", exc_info=True)
            raise ClientException("503 Service Unavailable",
                                  "Unable to connect to infobase server")

        cookie = response.getheader('Set-Cookie')
        if cookie:
            c = SimpleCookie()
            c.load(cookie)
            if 'infobase_auth_token' in c:
                auth_token = c['infobase_auth_token'].value
                # The auth token will be in urlquoted form, unquote it before use.
                # Otherwise, it will be quoted twice this value is set as cookie.
                auth_token = auth_token and unquote(auth_token)
                self.set_auth_token(auth_token)

        if web.config.debug:
            b = time.time()
            print("%.02f (%s):" %
                  (round(b - a, 2), web.ctx.infobase_req_count),
                  response.status,
                  method,
                  _path,
                  _data,
                  file=web.debug)

        if response.status == 200:
            return response.read()
        else:
            self.handle_error("%d %s" % (response.status, response.reason),
                              response.read())
示例#15
0
class Response(object):

    """An HTTP Response, including status, headers, and body."""

    status = ''
    """The HTTP Status-Code and Reason-Phrase."""

    header_list = []
    """
    A list of the HTTP response headers as (name, value) tuples.
    In general, you should use response.headers (a dict) instead. This
    attribute is generated from response.headers and is not valid until
    after the finalize phase."""

    headers = httputil.HeaderMap()
    """
    A dict-like object containing the response headers. Keys are header
    names (in Title-Case format); however, you may get and set them in
    a case-insensitive manner. That is, headers['Content-Type'] and
    headers['content-type'] refer to the same value. Values are header
    values (decoded according to :rfc:`2047` if necessary).

    .. seealso:: classes :class:`HeaderMap`, :class:`HeaderElement`
    """

    cookie = SimpleCookie()
    """See help(Cookie)."""

    body = ResponseBody()
    """The body (entity) of the HTTP response."""

    time = None
    """The value of time.time() when created. Use in HTTP dates."""

    stream = False
    """If False, buffer the response body."""

    def __init__(self):
        self.status = None
        self.header_list = None
        self._body = []
        self.time = time.time()

        self.headers = httputil.HeaderMap()
        # Since we know all our keys are titled strings, we can
        # bypass HeaderMap.update and get a big speed boost.
        dict.update(self.headers, {
            'Content-Type': 'text/html',
            'Server': 'CherryPy/' + cherrypy.__version__,
            'Date': httputil.HTTPDate(self.time),
        })
        self.cookie = SimpleCookie()

    def collapse_body(self):
        """Collapse self.body to a single string; replace it and return it."""
        if isinstance(self.body, text_or_bytes):
            return self.body

        newbody = []
        for chunk in self.body:
            if six.PY3 and not isinstance(chunk, bytes):
                raise TypeError("Chunk %s is not of type 'bytes'." %
                                repr(chunk))
            newbody.append(chunk)
        newbody = b''.join(newbody)

        self.body = newbody
        return newbody

    def finalize(self):
        """Transform headers (and cookies) into self.header_list. (Core)"""
        try:
            code, reason, _ = httputil.valid_status(self.status)
        except ValueError:
            raise cherrypy.HTTPError(500, sys.exc_info()[1].args[0])

        headers = self.headers

        self.status = '%s %s' % (code, reason)
        self.output_status = ntob(str(code), 'ascii') + \
            b' ' + headers.encode(reason)

        if self.stream:
            # The upshot: wsgiserver will chunk the response if
            # you pop Content-Length (or set it explicitly to None).
            # Note that lib.static sets C-L to the file's st_size.
            if dict.get(headers, 'Content-Length') is None:
                dict.pop(headers, 'Content-Length', None)
        elif code < 200 or code in (204, 205, 304):
            # "All 1xx (informational), 204 (no content),
            # and 304 (not modified) responses MUST NOT
            # include a message-body."
            dict.pop(headers, 'Content-Length', None)
            self.body = b''
        else:
            # Responses which are not streamed should have a Content-Length,
            # but allow user code to set Content-Length if desired.
            if dict.get(headers, 'Content-Length') is None:
                content = self.collapse_body()
                dict.__setitem__(headers, 'Content-Length', len(content))

        # Transform our header dict into a list of tuples.
        self.header_list = h = headers.output()

        cookie = self.cookie.output()
        if cookie:
            for line in cookie.split('\r\n'):
                name, value = line.split(': ', 1)
                if isinstance(name, six.text_type):
                    name = name.encode('ISO-8859-1')
                if isinstance(value, six.text_type):
                    value = headers.encode(value)
                h.append((name, value))
示例#16
0
class HTTP(object):
    HTTPError = HTTPError

    def __init__(self, script):
        self.script = script
        if script:  # For testing purposes
            self.logger = PrefixLoggerAdapter(script.logger, "http")
        self.headers = {}
        self.cookies = None
        self.session_started = False
        self.request_id = 1
        self.session_id = None
        self.request_middleware = None
        if self.script:  # For testing purposes
            self.setup_middleware()

    def get_url(self, path):
        address = self.script.credentials["address"]
        port = self.script.credentials.get("http_port")
        if port:
            address += ":%s" % port
        proto = self.script.credentials.get("http_protocol", "http")
        return "%s://%s%s" % (proto, address, path)

    def get(self,
            path,
            headers=None,
            cached=False,
            json=False,
            eof_mark=None,
            use_basic=False):
        """
        Perform HTTP GET request
        :param path: URI
        :param headers: Dict of additional headers
        :param cached: Cache result
        :param json: Decode json if set to True
        :param eof_mark: Waiting eof_mark in stream for end session (perhaps device return length 0)
        :param use_basic: Use basic authentication
        """
        self.ensure_session()
        self.request_id += 1
        self.logger.debug("GET %s", path)
        if cached:
            cache_key = "get_%s" % path
            r = self.script.root.http_cache.get(cache_key)
            if r is not None:
                self.logger.debug("Use cached result")
                return r
        user, password = None, None
        if use_basic:
            user = self.script.credentials.get("user")
            password = self.script.credentials.get("password")
        # Apply GET middleware
        url = self.get_url(path)
        hdr = self._get_effective_headers(headers)
        if self.request_middleware:
            for mw in self.request_middleware:
                url, _, hdr = mw.process_get(url, "", hdr)
        code, headers, result = fetch_sync(
            url,
            headers=hdr,
            request_timeout=60,
            follow_redirects=True,
            allow_proxy=False,
            validate_cert=False,
            eof_mark=eof_mark,
            user=user,
            password=password,
        )
        if not 200 <= code <= 299:
            raise HTTPError(msg="HTTP Error (%s)" % result[:256], code=code)
        self._process_cookies(headers)
        if json:
            try:
                result = ujson.loads(result)
            except ValueError as e:
                raise HTTPError("Failed to decode JSON: %s", e)
        self.logger.debug("Result: %r", result)
        if cached:
            self.script.root.http_cache[cache_key] = result
        return result

    def post(self,
             path,
             data,
             headers=None,
             cached=False,
             json=False,
             eof_mark=None,
             use_basic=False):
        """
        Perform HTTP GET request
        :param path: URI
        :param headers: Dict of additional headers
        :param cached: Cache result
        :param json: Decode json if set to True
        :param eof_mark: Waiting eof_mark in stream for end session (perhaps device return length 0)
        :param use_basic: Use basic authentication
        """
        self.ensure_session()
        self.request_id += 1
        self.logger.debug("POST %s %s", path, data)
        if cached:
            cache_key = "post_%s" % path
            r = self.script.root.http_cache.get(cache_key)
            if r is not None:
                self.logger.debug("Use cached result")
                return r
        user, password = None, None
        if use_basic:
            user = self.script.credentials.get("user")
            password = self.script.credentials.get("password")
        # Apply POST middleware
        url = self.get_url(path)
        hdr = self._get_effective_headers(headers)
        if self.request_middleware:
            for mw in self.request_middleware:
                url, data, hdr = mw.process_post(url, data, hdr)
        code, headers, result = fetch_sync(
            url,
            method="POST",
            body=data,
            headers=hdr,
            request_timeout=60,
            follow_redirects=True,
            allow_proxy=False,
            validate_cert=False,
            eof_mark=eof_mark,
            user=user,
            password=password,
        )
        if not 200 <= code <= 299:
            raise HTTPError(msg="HTTP Error (%s)" % result[:256], code=code)
        self._process_cookies(headers)
        if json:
            try:
                return ujson.loads(result)
            except ValueError as e:
                raise HTTPError(msg="Failed to decode JSON: %s" % e)
        self.logger.debug("Result: %r", result)
        if cached:
            self.script.root.http_cache[cache_key] = result
        return result

    def close(self):
        if self.session_started:
            self.shutdown_session()

    def _process_cookies(self, headers):
        """
        Process and store cookies from response headers
        :param headers:
        :return:
        """
        cdata = headers.get("Set-Cookie")
        if not cdata:
            return
        if not self.cookies:
            self.cookies = SimpleCookie()
        self.cookies.load(cdata)

    def get_cookie(self, name):
        """
        Get cookie name by value
        :param name:
        :return: Morsel object or None
        """
        if not self.cookies:
            return None
        return self.cookies.get(name)

    def _get_effective_headers(self, headers):
        """
        Append session headers when necessary. Apply effective cookies
        :param headers:
        :return:
        """
        if self.headers:
            if headers:
                headers = headers.copy()
            else:
                headers = {}
            headers.update(self.headers)
        elif not headers and self.cookies:
            headers = {}
        if self.cookies:
            headers["Cookie"] = self.cookies.output(header="").lstrip()
        return headers

    def set_header(self, name, value):
        """
        Set HTTP header to be set with all following requests
        :param name:
        :param value:
        :return:
        """
        self.logger.debug("Set header: %s = %s", name, value)
        self.headers[name] = str(value)

    def set_session_id(self, session_id):
        """
        Set session_id to be reused by middleware
        :param session_id:
        :return: None
        """
        if session_id is not None:
            self.session_id = session_id
        else:
            self.session_id = None

    def ensure_session(self):
        if not self.session_started:
            self.session_started = True
            self.setup_session()

    def setup_session(self):
        if self.script.profile.setup_http_session:
            self.logger.debug("Setup http session")
            self.script.profile.setup_http_session(self.script)

    def shutdown_session(self):
        if self.script.profile.shutdown_http_session:
            self.logger.debug("Shutdown http session")
            self.script.profile.shutdown_http_session(self.script)

    def setup_middleware(self):
        mw_list = self.script.profile.get_http_request_middleware(self.script)
        if not mw_list:
            return
        self.request_middleware = []
        for mw_cfg in mw_list:
            if isinstance(mw_cfg, tuple):
                name, cfg = mw_cfg
            else:
                name, cfg = mw_cfg, {}
            if "." in name:
                # Handler
                mw_cls = get_handler(name)
                assert mw_cls
                assert issubclass(mw_cls, BaseMiddleware)
            else:
                # Middleware name
                mw_cls = loader.get_class(name)
            self.request_middleware += [mw_cls(self, **cfg)]
示例#17
0
def update_cookies(base_value, cookies):
    cookie = SimpleCookie(base_value)
    for k, v in cookies.items():
        cookie[k] = v
    return str(cookie.output(header='', sep=';').lstrip())
示例#18
0
def update_cookies(base_value, cookies):
    cookie = SimpleCookie(base_value)
    for k, v in cookies.items():
        cookie[k] = v
    return cookie.output(header='', sep=';').lstrip()
示例#19
0
class Response(object):

    """An HTTP Response, including status, headers, and body."""

    status = ''
    """The HTTP Status-Code and Reason-Phrase."""

    header_list = []
    """
    A list of the HTTP response headers as (name, value) tuples.
    In general, you should use response.headers (a dict) instead. This
    attribute is generated from response.headers and is not valid until
    after the finalize phase."""

    headers = httputil.HeaderMap()
    """
    A dict-like object containing the response headers. Keys are header
    names (in Title-Case format); however, you may get and set them in
    a case-insensitive manner. That is, headers['Content-Type'] and
    headers['content-type'] refer to the same value. Values are header
    values (decoded according to :rfc:`2047` if necessary).

    .. seealso:: classes :class:`HeaderMap`, :class:`HeaderElement`
    """

    cookie = SimpleCookie()
    """See help(Cookie)."""

    body = ResponseBody()
    """The body (entity) of the HTTP response."""

    time = None
    """The value of time.time() when created. Use in HTTP dates."""

    stream = False
    """If False, buffer the response body."""

    def __init__(self):
        self.status = None
        self.header_list = None
        self._body = []
        self.time = time.time()

        self.headers = httputil.HeaderMap()
        # Since we know all our keys are titled strings, we can
        # bypass HeaderMap.update and get a big speed boost.
        dict.update(self.headers, {
            'Content-Type': 'text/html',
            'Server': 'CherryPy/' + cherrypy.__version__,
            'Date': httputil.HTTPDate(self.time),
        })
        self.cookie = SimpleCookie()

    def collapse_body(self):
        """Collapse self.body to a single string; replace it and return it."""
        if isinstance(self.body, text_or_bytes):
            return self.body

        newbody = []
        for chunk in self.body:
            if six.PY3 and not isinstance(chunk, bytes):
                raise TypeError("Chunk %s is not of type 'bytes'." %
                                repr(chunk))
            newbody.append(chunk)
        newbody = b''.join(newbody)

        self.body = newbody
        return newbody

    def _flush_body(self):
        """
        Discard self.body but consume any generator such that
        any finalization can occur, such as is required by
        caching.tee_output().
        """
        consume(iter(self.body))

    def finalize(self):
        """Transform headers (and cookies) into self.header_list. (Core)"""
        try:
            code, reason, _ = httputil.valid_status(self.status)
        except ValueError:
            raise cherrypy.HTTPError(500, sys.exc_info()[1].args[0])

        headers = self.headers

        self.status = '%s %s' % (code, reason)
        self.output_status = ntob(str(code), 'ascii') + \
            b' ' + headers.encode(reason)

        if self.stream:
            # The upshot: wsgiserver will chunk the response if
            # you pop Content-Length (or set it explicitly to None).
            # Note that lib.static sets C-L to the file's st_size.
            if dict.get(headers, 'Content-Length') is None:
                dict.pop(headers, 'Content-Length', None)
        elif code < 200 or code in (204, 205, 304):
            # "All 1xx (informational), 204 (no content),
            # and 304 (not modified) responses MUST NOT
            # include a message-body."
            dict.pop(headers, 'Content-Length', None)
            self._flush_body()
            self.body = b''
        else:
            # Responses which are not streamed should have a Content-Length,
            # but allow user code to set Content-Length if desired.
            if dict.get(headers, 'Content-Length') is None:
                content = self.collapse_body()
                dict.__setitem__(headers, 'Content-Length', len(content))

        # Transform our header dict into a list of tuples.
        self.header_list = h = headers.output()

        cookie = self.cookie.output()
        if cookie:
            for line in cookie.split('\r\n'):
                name, value = line.split(': ', 1)
                if isinstance(name, six.text_type):
                    name = name.encode('ISO-8859-1')
                if isinstance(value, six.text_type):
                    value = headers.encode(value)
                h.append((name, value))