예제 #1
0
파일: http.py 프로젝트: zhaoweikid/zbase
 def _parse_cookie(self):
     cookiestr = self.environ.get('HTTP_COOKIE', '')
     if not cookiestr:
         return
     cookies = SimpleCookie(cookiestr)
     for c in cookies.values():
         self.cookie[c.key] = c.value
예제 #2
0
class CookieHandler(object):

    def __init__(self, *args, **kw):
        # Somewhere to store cookies between consecutive requests
        self.cookies = SimpleCookie()
        super(CookieHandler, self).__init__(*args, **kw)

    def httpCookie(self, path):
        """Return self.cookies as an HTTP_COOKIE environment value."""
        l = [m.OutputString().split(';')[0] for m in self.cookies.values()
             if path.startswith(m['path'])]
        return '; '.join(l)

    def loadCookies(self, envstring):
        self.cookies.load(envstring)

    def saveCookies(self, response):
        """Save cookies from the response."""
        # Urgh - need to play with the response's privates to extract
        # cookies that have been set
        # TODO: extend the IHTTPRequest interface to allow access to all
        # cookies
        # TODO: handle cookie expirations
        for k, v in response._cookies.items():
            k = k.encode('utf8')
            self.cookies[k] = v['value'].encode('utf8')
            if 'path' in v:
                self.cookies[k]['path'] = v['path']
예제 #3
0
class CookieHandler(object):

    def __init__(self, *args, **kw):
        # Somewhere to store cookies between consecutive requests
        self.cookies = SimpleCookie()
        super(CookieHandler, self).__init__(*args, **kw)


    def httpCookie(self, path):
         """Return self.cookies as an HTTP_COOKIE environment value."""
         l = [m.OutputString() for m in self.cookies.values()
              if path.startswith(m['path'])]
         return '; '.join(l)

    def loadCookies(self, envstring):
        self.cookies.load(envstring)

    def saveCookies(self, response):
        """Save cookies from the response."""
        # Urgh - need to play with the response's privates to extract
        # cookies that have been set
        for k,v in response._cookies.items():
            k = k.encode('utf8')
            self.cookies[k] = v['value'].encode('utf8')
            if self.cookies[k].has_key('Path'):
                self.cookies[k]['Path'] = v['Path']
예제 #4
0
파일: http.py 프로젝트: zhaoweikid/zbase
class Response(object):
    def __init__(self, content='', status=200, mimetype='text/html', charset='utf-8'):
        self.content = content
        self.status  = status
        self.mimetype= mimetype
        self.headers = {'X-Powered-By':'QF/'+version}
        self.cookies = SimpleCookie()
        self.charset = charset

        self.headers['Content-Type'] = '%s; charset=%s' % (self.mimetype, self.charset)

    # TODO secure 没有实现
    def set_cookie(self, key, value='', secure=None, **options):
        '''
        option : max_age, expires, path, domain, httponly
        '''
        self.cookies[key] = value
        self.cookies[key]['path'] = '/'

        for k, v in options.items():
            if v:
                if k == 'expires':
                    if isinstance(v, (datetime.date, datetime.datetime)):
                        v = v.timetuple()
                    elif isinstance(v, (int, float)):
                        v = time.gmtime(v)
                    v = time.strftime("%a, %d %b %Y %H:%M:%S GMT", v)
                self.cookies[key][k.replace('_', '-')] = v

    def del_cookie(self, key, **kwargs):
        kwargs['max_age'] = -1
        kwargs['expires'] = 0
        self.set_cookie(key, '', **kwargs)

    def write(self, data):
        if type(data) == types.UnicodeType:
            self.content += data.encode(self.charset)
        else:
            self.content += data

    def length(self):
        return len(self.content)

    def redirect(self, url):
        url = url.encode(self.charset) if isinstance(url,unicode) else str(url)
        self.status = 302
        self.headers['Location'] = url

    def __call__(self, environ, start_response):
        statusstr = '%d %s' % (self.status, HTTP_STATUS_CODES.get(self.status, ''))
        self.headers['Content-Length'] = str(len(self.content))

        headers = self.headers.items()
        # add cookie
        if self.cookies:
            for c in self.cookies.values():
                headers.append(('Set-Cookie', c.OutputString()))

        start_response(statusstr, headers)
        return [self.content]
예제 #5
0
 def wrapped_start_response(status, response_headers, exc_info=None):
     sid = self.factory.save(environ["wsgi.session"])
     cookies = SimpleCookie()
     cookies["session_id"] = sid
     cookie = cookies["session_id"]
     cookie["path"] = cookie_path
     cookie["httponly"] = 1
     response_headers.extend(("set-cookie", morsel.OutputString())
                             for morsel in cookies.values())
     return start_response(status, response_headers, exc_info)
예제 #6
0
 def session_response(status, headers, exc_info=None):
     sid = data.session.save()
     if sid:
         cookie = SimpleCookie()
         cookie[self.cookie_name] = sid
         cookie[self.cookie_name]['path'] = '/'
         cookie[self.cookie_name]['expires'] = self.ttl
         headers.append(('Set-Cookie', morsel.OutputString())
                        for morsel in cookie.values())
     return start_response(status, headers, exc_info)
예제 #7
0
	def _handle_cookies(self, response):
		# type: (httplib.HTTPResponse) -> None
		"""
		Parse cookies from |HTTP| response and store for next request.

		:param httplib.HTTPResponse: The |HTTP| response.
		"""
		# FIXME: this cookie handling doesn't respect path, domain and expiry
		cookies = SimpleCookie()
		cookies.load(response.getheader('set-cookie', ''))
		self.cookies.update(dict((cookie.key, cookie.value) for cookie in cookies.values()))
예제 #8
0
파일: base.py 프로젝트: iitwebdev/lectures
class BaseController(WSGIController):

    title = None
    
    def __call__(self, environ, start_response):
        # Insert any code to be run per request here. The Routes match
        # is under environ['pylons.routes_dict'] should you want to check
        # the action or route vars here
        self._cookies = SimpleCookie()
        def repl_start_response(status, headers, exc_info=None):
            for c in self._cookies.values():
                
                headers.append(
                    'Set-Cookie', c.output(header=''))
            return start_response(status, headers, exc_info)
        return WSGIController.__call__(self, environ, repl_start_response)

    def __before__(self):
        request.charset = 'utf8'
        c.self = self
        if self.title is None:
            c.title = self.__class__.__name__[:-len('Controller')]
        else:
            c.title = self.title
        c.url = URL.from_environ(
            request.environ,
            script_name=request.environ['paste.recursive.script_name'],
            with_path_info=False)
        c.session = session
        if 'bundle' in request.urlvars:
            self.bundle = model.Bundle.get(request.urlvars['bundle'])
            c.bundle_url = c.url[self.bundle.name]
        else:
            self.bundle = None
            c.bundle_url = None
        if request.cookies.get('flash'):
            c.flash = request.cookies['flash']
            self.delete_cookie('flash')
        else:
            c.flash = None

    def flash(self, msg):
        self.set_cookie('flash', msg)

    def set_cookie(self, key, value='', **kw):
        kw.setdefault('path', '/')
        self._cookies[key] = value
        for var_name, var_value in kw.items():
            if var_value is not None and var_value is not False:
                self._cookies[key][var_name.replace('_', '-')] = var_value

    def delete_cookie(self, key, path='/', domain=None):
        self.set_cookie(key, '', path=path, domain=domain,
                        expires=0, max_age=0)
예제 #9
0
    def _handle_set_cookie(self, response):
        headers = filter(lambda h: h[0].lower() == 'set-cookie', response.getheaders())
        values = []

        for header in headers:
            cookie = SimpleCookie(header[1])
            for morsel in cookie.values():
                values.append((dict(key=morsel.key, value=morsel.value)))

        self.cookies = values
        self._inject_cookies(values)
예제 #10
0
	def set(self, username, expires=None):
		s = username + ":" + self.req._ENV.get('REMOTE_ADDR', '-')
		s_hash = hashlib.sha1(s + config.secret).hexdigest()

		session_cookie = SimpleCookie()
		session_cookie['clamsession'] = s + ":" + s_hash
		session_cookie['clamsession']["path"] = '/'
		session_cookie['clamsession']["httponly"] = True
		if expires:
			session_cookie['clamsession']["expires"] = expires
		self.req.headers += [("set-cookie", m.OutputString()) for m in session_cookie.values()]
		return True
예제 #11
0
    def set(self, username, expires=None):
        s = username + ":" + self.req._ENV.get('REMOTE_ADDR', '-')
        s_hash = hashlib.sha1(s + config.secret).hexdigest()

        session_cookie = SimpleCookie()
        session_cookie['clamsession'] = s + ":" + s_hash
        session_cookie['clamsession']["path"] = '/'
        session_cookie['clamsession']["httponly"] = True
        if expires:
            session_cookie['clamsession']["expires"] = expires
        self.req.headers += [("set-cookie", m.OutputString())
                             for m in session_cookie.values()]
        return True
예제 #12
0
    def __call__(self, environ, start_response):
        path = environ.get('PATH_INFO', '')
        if not path.startswith("/tale/"):
            # paths not under /tale/ won't get a session
            return self.app(environ, start_response)

        cookie = SimpleCookie()
        if 'HTTP_COOKIE' in environ:
            cookie.load(environ['HTTP_COOKIE'])
        sid = None
        if "session_id" in cookie:
            sid = cookie["session_id"].value
        environ["wsgi.session"] = self.factory.load(sid)

        # If the server runs behind a reverse proxy, you can configure the proxy
        # to pass along the uri that it exposes (our internal uri can be different)
        # via the X-Forwarded-Uri header. If we find this header we use it to
        # replace the "/tale" uri base by the one from the header, to use as cookie path.
        forwarded_uri = environ.get("HTTP_X_FORWARDED_URI", "/tale/")
        cookie_path = "/" + forwarded_uri.split("/", 2)[1]

        def wrapped_start_response(status, response_headers, exc_info=None):
            sid = self.factory.save(environ["wsgi.session"])
            cookies = SimpleCookie()
            cookies["session_id"] = sid
            cookie = cookies["session_id"]
            cookie["path"] = cookie_path
            cookie["httponly"] = 1
            response_headers.extend(("set-cookie", morsel.OutputString())
                                    for morsel in cookies.values())
            return start_response(status, response_headers, exc_info)

        try:
            return self.app(environ, wrapped_start_response)
        except SessionMiddleware.CloseSession as x:
            self.factory.delete(sid)
            # clear the browser cookie
            cookies = SimpleCookie()
            cookies["session_id"] = "deleted"
            cookie = cookies["session_id"]
            cookie["path"] = cookie_path
            cookie["httponly"] = 1
            cookie["expires"] = "Thu, 01-Jan-1970 00:00:00 GMT"
            response_headers = [('Content-Type', x.content_type)]
            response_headers.extend(("set-cookie", morsel.OutputString())
                                    for morsel in cookies.values())
            start_response("200 OK", response_headers)
            return [str(x).encode("utf-8")]
예제 #13
0
파일: orvet.py 프로젝트: hashmalech/orvet
class Rs(threading.local):
    def b(self, s, app):
        self.s=s;self.app=app;self.status=status(200);self.header={}
        self.content_type='text/html; charset=UTF-8'
        self.cookies=SimpleCookie()

    def headers(self):
        a=map(lambda c:('Set-Cookie',c.OutputString()),self.cookies.values())
        return list(self.header.iteritems())+a

    def c(self):return self.header['Content-Type']
    def d(self, v):self.header['Content-Type']=v
    content_type=property(c,d,None,c.__doc__)

    def set_cookie(self, k, v, **kargs):
        self.cookies[k]=cookie_encode(v,self.app.config['SECURECOOKIE_KEY'])
        for i,j in kargs.iteritems():self.cookies[k][i.replace('_','-')]=j
예제 #14
0
def get_the_cookie(url, username=None, password=None):
    req = urlopen(url)
    data = req.read()
    hidden_inputs = re.findall('<INPUT.*HIDDEN.*NAME="(.*)".*VALUE="(.*)">', data)
    if username is None:
        username = raw_input('Username: '******'username', username))
    hidden_inputs.append(('passcode', password))
    qs = urlencode(hidden_inputs)

    action = urljoin(url, re.findall('<FORM action="([^"]*)" .*>', data)[0])
    req2 = urlopen(action, data=qs)
    cookie = SimpleCookie(req2.info()['set-cookie'])
    return cookie.keys()[0] + "=" + cookie.values()[0].value
예제 #15
0
    def __init__(self, url, request_text, proxy=None):  #还是要求url算了
        self.rfile = StringIO(request_text)
        self.raw_requestline = self.rfile.readline()
        self.parse_request()

        ###parameters that needed in repeater request
        self.proxy = proxy
        self.method = self.command
        #self.data = self.rfile.read(int(self.headers['content-length'])) #固定长度
        self.data = self.rfile.read()  #变动长度,直到结束;适合数据包修改之后。
        self.header = self.headers.dict

        self.header["content-length"] = str(len(
            self.data))  # 更新content-length,数据包修改过后
        if "cookie" in self.header.keys():
            cookie_string = self.header["cookie"]
            cookie = SimpleCookie(cookie_string)
            self.cookie = {i.key: i.value for i in cookie.values()}
            #self.cookie = Cookie.Cookie()
            #self.cookie.load(cookie_string)
        else:
            self.cookie = None

        #####do some check on url and request raw
        if url:
            print urlparse.urlparse(url)
            TextPath = "{0}?{1}".format(
                urlparse.urlparse(url).path,
                urlparse.urlparse(url).query)
            if TextPath == self.path:
                self.url = url
            else:
                print "Error! url is different from the request text"

        elif "origin" in self.headers.keys():
            self.url = self.headers["origin"]
        elif "referer" in self.header.keys() and "host" in self.header.keys():
            if urlparse.urlparse(
                    self.headers["referer"]).netloc == self.headers["host"]:
                scheme = urlparse.urlparse(self.headers["origin"]).scheme
                self.url = "{0}{1}{2}".format(scheme, self.headers["host"],
                                              self.path)
        else:
            print("please specify the url")
예제 #16
0
class Response(object):
    """ Response object which `start_response`. """
    def bind(self, code=200, content_type="text/html; charset=UTF-8"):
        self.status = _HTTP_STATUS.get(code, "UNKNOWN")
        self.headers = [("Content-Type", content_type)]
        self._response = []

    def redirect(self, url):
        self.headers.append(("Location", url))

    def write(self, msg):
        self._response.append(msg)

    def set_cookie(self, key, value="", max_age=None, expires=None,
                   path="/", domain=None, secure=None):
        if not hasattr(self, "_cookies"):
            self._cookies = SimpleCookie()
        self._cookies[key] = value
        if max_age:
            self._cookies[key]["max-age"] = max_age
        if expires:
            self._cookies[key]["expires"] = _format_gmt_time(expires)
        if path:
            self._cookies[key]["path"] = path
        if domain:
            self._cookies[key]["domain"] = domain
        if secure:
            self._cookies[key]["secure"] = secure

    def delete_cookie(self, key):
        if self._cookies is None:
            self._cookies = SimpleCookie()
        if not key in self._cookies:
            self._cookies[key] = ""
        self._cookies[key]["max-age"] = 0

    def __call__(self, start_response):
        self.headers.append(("Content-Length",
                             str(sum(len(n) for n in self._response))))
        if hasattr(self, "_cookies"):
            for morsel in self._cookies.values():
                self.headers.append(("Set-Cookie", morsel.output(header="")))
        start_response(self.status, self.headers)
        return self._response
예제 #17
0
파일: http.py 프로젝트: Derecho/rivr
class Response(object):
    status_code = 200
    
    def __init__(self, content='', status=None, content_type='text/html; charset=utf8'):
        self.content = content
        
        if status:
            self.status_code = status
        
        self.headers = {'Content-Type': content_type}
        self.cookies = SimpleCookie()
    
    def __str__(self):
        return '\n'.join(['%s: %s' % (key, value) for key, value in self.headers.items()]) + '\n\n' + self.content
    
    def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=False):
        self.cookies[key] = value
        
        if max_age is not None:
            self.cookies[key]['max-age'] = max_age
        
        if expires is not None:
            self.cookies[key]['expires'] = expires
        
        if path is not None:
            self.cookies[key]['path'] = path
        
        if domain is not None:
            self.cookies[key]['domain'] = domain
        
        if secure:
            self.cookies[key]['secure'] = True
    
    def delete_cookie(self, key, path='/', domain=None):
        self.set_cookie(key, max_age=0, path=path, domain=domain, expires='Thu, 01-Jan-1970 00:00:00 GMT')
    
    def headers_items(self):
        headers = self.headers.items()
        
        for cookie in self.cookies.values():
            headers.append(('Set-Cookie', str(cookie.output(header=''))))
        
        return headers
예제 #18
0
파일: __init__.py 프로젝트: swinf/Swinf
 def COOKIES(self):
     cookies = SimpleCookie(self._environ.get('HTTP_COOKIE',''))
     self._COOKIES = {}
     for cookie in cookies.values():
         self._COOKIES[cookie.key] = cookie.value
     return self._COOKIES
예제 #19
0
class HttpResponse(object):
    """
    The Response object is used to collect the data to be written
    back to the HTTP client.
    """

    def __init__(self, response=None, headers=None, status=200):
        if response is None:
            self.response = []
        elif isinstance(response, basestring):
            self.response = [response]
        else:
            self.response = response
        if headers is None:
            self.headers = HttpHeaders([])
        elif isinstance(headers, list):
            self.headers = HttpHeaders(headers)
        elif isinstance(headers, HttpHeaders):
            self.headers = headers
        else:
            raise TypeError('invalid header format')
        self.status = status
        self._cookies = None

    def __setitem__(self, name, value):
        self.headers[name] = value

    def __getitem__(self, name):
        self.headers.get(name)

    def __delitem__(self, name):
        del self.headers[name]

    def __contains__(self, name):
        return name in self.headers

    def __len__(self):
        if isinstance(self.response, list):
            length = 0
            for item in self.response:
                length += len(item)
            return length
        try:
            return len(self.response)
        except:
            return 0

    def write(self, d):
        if not isinstance(self.response, list):
            raise TypeError('read only or dynamic response object')
        elif isinstance(d, basestring):
            self.response.append(d)
        else:
            raise TypeError('str or unicode required')

    def set_cookie(self, key, value='', max_age=None, expires=None,
                   path='/', domain=None, secure=None):
        if self._cookies is None:
            self._cookies = SimpleCookie()
        self._cookies[key] = value
        if not max_age is None:
            self._cookies[key]['max-age'] = max_age
        if not expires is None:
            if isinstance(expires, basestring):
                self._cookies[key]['expires'] = expires
                expires = None
            elif isinstance(expires, datetime):
                expires = expires.utctimetuple()
            elif not isinstance(expires, (int, long)):
                expires = gmtime(expires)
            else:
                raise ValueError('datetime or integer required')
            if not expires is None:
                now = gmtime()
                month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
                         'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][now.tm_mon - 1]
                day = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
                       'Friday', 'Saturday', 'Sunday'][expires.tm_wday]
                date = '%02d-%s-%s' % (
                    now.tm_mday, month, str(now.tm_year)[-2:]
                )
                d = '%s, %s %02d:%02d:%02d GMT' % (day, date, now.tm_hour,
                                                   now.tm_min, now.tm_sec)
                self._cookies[key]['expires'] = d
        if not path is None:
            self._cookies[key]['path'] = path
        if not domain is None:
            self._cookies[key]['domain'] = domain
        if not secure is None:
            self._cookies[key]['secure'] = secure

    def delete_cookie(self, key):
        if self._cookies is None:
            self._cookies = SimpleCookie()
        if not key in self._cookies:
            self._cookies[key] = ''
        self._cookies[key]['max-age'] = 0

    def __call__(self, request):
        if not 'Content-Type' in self.headers:
            self.headers['Content-Type'] = 'text/html; charset=%s' % \
                                           str(request.charset)
        headers = self.headers.get()
        if not self._cookies is None:
            for morsel in self._cookies.values():
                headers.append(('Set-Cookie', morsel.output(header='')))
        status = '%d %s' % (self.status,
                            HTTP_STATUS_CODES.get(self.status, 'UNKNOWN'))
        request.start_response(status, headers)
        if self.response is None:
            yield ''
        elif isinstance(self.response, unicode):
            yield self.response.encode(request.charset)
        elif isinstance(self.response, str):
            yield self.response
        else:
            try:
                iterator = iter(self.response)
            except TypeError:
                raise TypeError('%r is not an valid response' % self.response)
            for line in iterator:
                if isinstance(line, unicode):
                    yield line.encode(request.charset)
                elif isinstance(line, str):
                    yield line
                else:
                    raise TypeError('%r is not string or unicode' % line)
예제 #20
0
class Controller(object):
    """
    Moar's Controller class. Aims to be useful. Extend this for your own
    controllers. Any class that implements the get_response_start()
    method can be used in place of this one.
    """

    def __init__(self, config, request):
        """
        Set up basics and defaults, like status codes and headers.
        """
        self.config = config
        self.request = request
        self.code = 200
        self.headers = []
        self.view = {}
        self.cookie = SimpleCookie()
        self.user = None
        self.parse_cookie()

    def parse_cookie(self):
        """
        Helper for parsing cookie data.
        """
        self.cookie = SimpleCookie()
        if 'HTTP_COOKIE' in self.request:
            self.cookie.load(self.request['HTTP_COOKIE'])

    def get_body_params(self):
        """
        Helper function for parsing body params. Body params are only
        used if the right Content-Type header
        (application/x-www-form-urlencoded) is set.
        """
        if 'CONTENT_TYPE' not in self.request:
            return {}
        if self.request['CONTENT_TYPE'] != 'application/x-www-form-urlencoded':
            return {}
        content_length = int(self.request.get('CONTENT_LENGTH', 0))
        return parse_params(self.request['wsgi.input'].read(content_length))

    def get_params(self):
        """
        Parse all parameters and return them.
        """
        params = parse_params(self.request['QUERY_STRING'])
        params.update(self.get_body_params())
        return params

    def get_response_start(self):
        """
        Build a status code string and headers to send.
        """
        send_headers = list(self.headers)
        for morsel in self.cookie.values():
            send_headers.append(
                ('Set-Cookie', morsel.output(header='').strip()))
        return self.code, send_headers

    def get_template_path(self, method, ext=None):
        """
        Build a path to where the templates for this class/method live.
        Can pass an optional file extension.
        """
        if not ext:
            ext = 'tpl'
        obj_name = self.__class__.__name__.lower().replace('controller', '')
        return '%s/%s.%s' % (obj_name, method, ext)

    def render_raw(self, data, method, ext=None):
        """
        Render a template for the current class and given method. Can
        pass an optional file extension.
        """
        request = Environment(loader=FileSystemLoader('templates'))

        template_path = self.get_template_path(method, ext)
        template = request.get_template(template_path)

        view_vars = dict(data)
        view_vars['user'] = self.user

        return template.render(**view_vars)

    def render(self, method, ext=None):
        """
        Render a template for the current class and given method. Use
        the object's view member variable as a data provider. Can pass
        an optional file extension.
        """
        return self.render_raw(self.view, method, ext)
예제 #21
0
파일: crumb.py 프로젝트: meeb/crumb
class Request(object):
    '''
        Base request object that provides an abstraction layer over a WSGI interface.
        Request handlers inherit from this class.
    '''

    STATUS_CODES = {
        200: 'OK',
        201: 'Created',
        204: 'No Content',
        301: 'Moved Permanently',
        302: 'Found',
        303: 'See Other',
        400: 'Bad Request',
        401: 'Unauthorized',
        403: 'Forbidden',
        404: 'Not Found',
        405: 'Method Not Allowed',
        500: 'Internal Server Error',
        503: 'Service Unavailable',
    }
    METHODS = ('GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS')

    def __init__(self):
        self.environ = None
        self.response_cookies = SimpleCookie()
        self.request_cookies = SimpleCookie()
        self.unpacked_cookies = {}
        self.parsed_cookies = False
        self.post_data = {}
        self.parsed_post = False
        self.querystring = {}

    def _get_response(self, environ, start_response, method, uri, uri_kwargs):
        self.environ = environ
        self.querystring = parse_qs(environ.get('QUERY_STRING', ''))
        if method not in self.METHODS:
            raise MethodNotPermitted
        response_data, status_code, extra_headers = self._run_hander(method, uri_kwargs)
        status_text = self.STATUS_CODES.get(status_code)
        if not status_text:
            raise InternalServerError
        headers = self._get_response_headers(status_code, extra_headers)
        start_response('{} {}'.format(status_code, status_text), headers)
        return [response_data]

    def _run_hander(self, method, uri_kwargs):
        handler = getattr(self, method.lower(), None)
        if not handler:
            raise MethodNotPermitted
        raw_response = handler(self.environ, **uri_kwargs)
        response_data, status_code, extra_headers = b'', 200, {}
        if type(raw_response) == tuple:
            if len(raw_response) == 3:
                response_data, status_code, extra_headers = raw_response
            elif len(raw_response) == 2:
                response_data, status_code = raw_response
            else:
                raise InternalServerError
        else:
            response_data = raw_response
        return response_data, status_code, extra_headers

    def _get_response_headers(self, status_code, extra_headers):
        headers = []
        has_content_type = False
        has_server = False
        if type(extra_headers) == dict:
            extra_headers = extra_headers.iteritems()
        for (k, v) in extra_headers:
            k = k.lower().replace('_', '-')
            headers.append((k, v))
            if k == 'content-type':
                has_content_type = True
            elif k == 'server':
                has_server = True
        if not has_content_type:
            headers.append(('content-type', 'text/html'))
        if not has_server:
            headers.append(('server', 'crumb mirco wsgi framework'))
        headers.extend(('set-cookie', c.OutputString()) for c in self.response_cookies.values())
        return headers

    def set_cookie(self, name='', value=None, expires=0, path='/'):
        self.response_cookies[name] = value
        self.response_cookies[name]['path'] = path
        if expires > 0:
            self.response_cookies[name]['expires'] = expires

    def get_cookie(self, name=''):
        if not self.parsed_cookies:
            self.unpack_cookies()
        return getattr(self.request_cookies.get(name), 'value', None)

    def unpack_cookies(self):
        raw_cookies = self.environ.get('HTTP_COOKIE')
        if raw_cookies:
            try:
                self.request_cookies.load(raw_cookies)
            except CookieError:
                raise BadRequest

    def get_post(self, name='', lazy_unpack=True):
        if not self.parsed_post:
            self.unpack_post()
        d = self.post_data.get(name)
        if d and len(d) == 1 and lazy_unpack:
            return d[0]
        return d

    def iter_post(self):
        if not self.parsed_post:
            self.unpack_post()
        return self.post_data.iteritems()

    def unpack_post(self):
        try:
            content_length = int(self.environ.get('CONTENT_LENGTH', '0'))
        except ValueError:
            raise BadRequest
        reader = getattr(self.environ.get('wsgi.input'), 'read', lambda x: '')
        post_data = reader(content_length)
        try:
            self.post_data = parse_qs(post_data, True)
        except ValueError, TypeError:
            raise BadRequest
예제 #22
0
파일: response.py 프로젝트: jarpineh/aspen
class Response(Exception):
    """Represent an HTTP Response message.
    """

    request = None

    def __init__(self, code=200, body="", headers=None, charset="UTF-8"):
        """Takes an int, a string, a dict, and a basestring.

            - code      an HTTP response code, e.g., 404
            - body      the message body as a string
            - headers   a Headers instance
            - charset   string that will be set in the Content-Type in the future at some point but not now

        Code is first because when you're raising your own Responses, they're
        usually error conditions. Body is second because one more often wants
        to specify a body without headers, than a header without a body.

        """
        if not isinstance(code, int):
            raise TypeError("'code' must be an integer")
        elif not isinstance(body, str) and not hasattr(body, "__iter__"):
            raise TypeError("'body' must be a bytestring or iterable of " "bytestrings")
        elif headers is not None and not isinstance(headers, (dict, list)):
            raise TypeError("'headers' must be a dictionary or a list of " + "2-tuples")
        elif charset_re.match(charset) is None:
            raise TypeError("'charset' must match " + charset_re.pattern)

        Exception.__init__(self)
        self.code = code
        self.body = body
        self.headers = Headers("")
        self.charset = charset
        if headers:
            if isinstance(headers, dict):
                headers = headers.items()
            for k, v in headers:
                self.headers[k] = v
        self.cookie = SimpleCookie()
        try:
            self.cookie.load(self.headers.get("Cookie", ""))
        except CookieError:
            pass

    def __call__(self, environ, start_response):
        wsgi_status = str(self)
        for morsel in self.cookie.values():
            self.headers["Set-Cookie"] = morsel.OutputString()
        wsgi_headers = []
        for k, vals in self.headers.iteritems():
            try:  # XXX This is a hack. It's red hot, baby.
                k = k.encode("US-ASCII")
            except UnicodeEncodeError:
                k = ascii_dammit(k)
                raise ValueError("Header key %s must be US-ASCII.")
            for v in vals:
                try:  # XXX This also is a hack. It is also red hot, baby.
                    v = v.encode("US-ASCII")
                except UnicodeEncodeError:
                    v = ascii_dammit(v)
                    raise ValueError("Header value %s must be US-ASCII.")
                wsgi_headers.append((k, v))

        start_response(wsgi_status, wsgi_headers)
        body = self.body
        if isinstance(body, str):
            body = [body]
        return CloseWrapper(self.request, body)

    def __repr__(self):
        return "<Response: %s>" % str(self)

    def __str__(self):
        return "%d %s" % (self.code, self._status())

    def _status(self):
        return status_strings.get(self.code, "Unknown HTTP status")

    def _to_http(self, version):
        """Given a version string like 1.1, return an HTTP message, a string.
        """
        status_line = "HTTP/%s" % version
        headers = self.headers.raw
        body = self.body
        if self.headers.get("Content-Type", "").startswith("text/"):
            body = body.replace("\n", "\r\n")
            body = body.replace("\r\r", "\r")
        return "\r\n".join([status_line, headers, "", body])
예제 #23
0
class WSGIResponse(object):
    """A basic HTTP response with content, headers, and out-bound cookies

    The class variable ``defaults`` specifies default values for
    ``content_type``, ``charset`` and ``errors``. These can be overridden
    for the current request via the registry.

    """
    defaults = StackedObjectProxy(
        default=dict(content_type='text/html', charset='utf-8', 
                     errors='strict', headers={'Cache-Control':'no-cache'})
        )
    def __init__(self, content='', mimetype=None, code=200):
        self._iter = None
        self._is_str_iter = True

        self.content = content
        self.headers = HeaderDict()
        self.cookies = SimpleCookie()
        self.status_code = code

        defaults = self.defaults._current_obj()
        if not mimetype:
            mimetype = defaults.get('content_type', 'text/html')
            charset = defaults.get('charset')
            if charset:
                mimetype = '%s; charset=%s' % (mimetype, charset)
        self.headers.update(defaults.get('headers', {}))
        self.headers['Content-Type'] = mimetype
        self.errors = defaults.get('errors', 'strict')

    def __str__(self):
        """Returns a rendition of the full HTTP message, including headers.

        When the content is an iterator, the actual content is replaced with the
        output of str(iterator) (to avoid exhausting the iterator).
        """
        if self._is_str_iter:
            content = ''.join(self.get_content())
        else:
            content = str(self.content)
        return '\n'.join(['%s: %s' % (key, value)
            for key, value in self.headers.headeritems()]) \
            + '\n\n' + content
    
    def __call__(self, environ, start_response):
        """Convenience call to return output and set status information
        
        Conforms to the WSGI interface for calling purposes only.
        
        Example usage:
        
        .. code-block:: python

            def wsgi_app(environ, start_response):
                response = WSGIResponse()
                response.write("Hello world")
                response.headers['Content-Type'] = 'latin1'
                return response(environ, start_response)
        
        """
        status_text = STATUS_CODE_TEXT[self.status_code]
        status = '%s %s' % (self.status_code, status_text)
        response_headers = self.headers.headeritems()
        for c in self.cookies.values():
            response_headers.append(('Set-Cookie', c.output(header='')))
        start_response(status, response_headers)
        is_file = isinstance(self.content, file)
        if 'wsgi.file_wrapper' in environ and is_file:
            return environ['wsgi.file_wrapper'](self.content)
        elif is_file:
            return iter(lambda: self.content.read(), '')
        return self.get_content()
    
    def determine_charset(self):
        """
        Determine the encoding as specified by the Content-Type's charset
        parameter, if one is set
        """
        charset_match = _CHARSET_RE.search(self.headers.get('Content-Type', ''))
        if charset_match:
            return charset_match.group(1)
    
    def has_header(self, header):
        """
        Case-insensitive check for a header
        """
        warnings.warn('WSGIResponse.has_header is deprecated, use '
                      'WSGIResponse.headers.has_key instead', DeprecationWarning,
                      2)
        return self.headers.has_key(header)

    def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
                   domain=None, secure=None, httponly=None):
        """
        Define a cookie to be sent via the outgoing HTTP headers
        """
        self.cookies[key] = value
        for var_name, var_value in [
            ('max_age', max_age), ('path', path), ('domain', domain),
            ('secure', secure), ('expires', expires), ('httponly', httponly)]:
            if var_value is not None and var_value is not False:
                self.cookies[key][var_name.replace('_', '-')] = var_value

    def delete_cookie(self, key, path='/', domain=None):
        """
        Notify the browser the specified cookie has expired and should be
        deleted (via the outgoing HTTP headers)
        """
        self.cookies[key] = ''
        if path is not None:
            self.cookies[key]['path'] = path
        if domain is not None:
            self.cookies[key]['domain'] = domain
        self.cookies[key]['expires'] = 0
        self.cookies[key]['max-age'] = 0

    def _set_content(self, content):
        if hasattr(content, '__iter__'):
            self._iter = content
            if isinstance(content, list):
                self._is_str_iter = True
            else:
                self._is_str_iter = False
        else:
            self._iter = [content]
            self._is_str_iter = True
    content = property(lambda self: self._iter, _set_content,
                       doc='Get/set the specified content, where content can '
                       'be: a string, a list of strings, a generator function '
                       'that yields strings, or an iterable object that '
                       'produces strings.')

    def get_content(self):
        """
        Returns the content as an iterable of strings, encoding each element of
        the iterator from a Unicode object if necessary.
        """
        charset = self.determine_charset()
        if charset:
            return encode_unicode_app_iter(self.content, charset, self.errors)
        else:
            return self.content
    
    def wsgi_response(self):
        """
        Return this WSGIResponse as a tuple of WSGI formatted data, including:
        (status, headers, iterable)
        """
        status_text = STATUS_CODE_TEXT[self.status_code]
        status = '%s %s' % (self.status_code, status_text)
        response_headers = self.headers.headeritems()
        for c in self.cookies.values():
            response_headers.append(('Set-Cookie', c.output(header='')))
        return status, response_headers, self.get_content()
    
    # The remaining methods partially implement the file-like object interface.
    # See http://docs.python.org/lib/bltin-file-objects.html
    def write(self, content):
        if not self._is_str_iter:
            raise IOError, "This %s instance's content is not writable: (content " \
                'is an iterator)' % self.__class__.__name__
        self.content.append(content)

    def flush(self):
        pass

    def tell(self):
        if not self._is_str_iter:
            raise IOError, 'This %s instance cannot tell its position: (content ' \
                'is an iterator)' % self.__class__.__name__
        return sum([len(chunk) for chunk in self._iter])

    ########################################
    ## Content-type and charset

    def charset__get(self):
        """
        Get/set the charset (in the Content-Type)
        """
        header = self.headers.get('content-type')
        if not header:
            return None
        match = _CHARSET_RE.search(header)
        if match:
            return match.group(1)
        return None

    def charset__set(self, charset):
        if charset is None:
            del self.charset
            return
        try:
            header = self.headers.pop('content-type')
        except KeyError:
            raise AttributeError(
                "You cannot set the charset when no content-type is defined")
        match = _CHARSET_RE.search(header)
        if match:
            header = header[:match.start()] + header[match.end():]
        header += '; charset=%s' % charset
        self.headers['content-type'] = header

    def charset__del(self):
        try:
            header = self.headers.pop('content-type')
        except KeyError:
            # Don't need to remove anything
            return
        match = _CHARSET_RE.search(header)
        if match:
            header = header[:match.start()] + header[match.end():]
        self.headers['content-type'] = header

    charset = property(charset__get, charset__set, charset__del, doc=charset__get.__doc__)

    def content_type__get(self):
        """
        Get/set the Content-Type header (or None), *without* the
        charset or any parameters.

        If you include parameters (or ``;`` at all) when setting the
        content_type, any existing parameters will be deleted;
        otherwise they will be preserved.
        """
        header = self.headers.get('content-type')
        if not header:
            return None
        return header.split(';', 1)[0]

    def content_type__set(self, value):
        if ';' not in value:
            header = self.headers.get('content-type', '')
            if ';' in header:
                params = header.split(';', 1)[1]
                value += ';' + params
        self.headers['content-type'] = value

    def content_type__del(self):
        try:
            del self.headers['content-type']
        except KeyError:
            pass

    content_type = property(content_type__get, content_type__set,
                            content_type__del, doc=content_type__get.__doc__)
예제 #24
0
파일: response.py 프로젝트: dowski/aspen
class Response(Exception):
    """Represent an HTTP Response message.
    """

    def __init__(self, code=200, body='', headers=None):
        """Takes an int, a string, and a dict (or list of tuples).

            - code      an HTTP response code, e.g., 404
            - body      the message body as a string
            - headers   a Headers instance
            - cookie    a Cookie.SimpleCookie instance

        Code is first because when you're raising your own Responses, they're
        usually error conditions. Body is second because one more often wants
        to specify a body without headers, than a header without a body.

        """
        if not isinstance(code, int):
            raise TypeError("'code' must be an integer")
        elif not isinstance(body, basestring):
            raise TypeError("'body' must be a string")
        elif headers is not None and not isinstance(headers, (dict, list)):
            raise TypeError("'headers' must be a dictionary or a list of " +
                            "2-tuples")

        Exception.__init__(self)
        self.code = code
        self.body = body
        self.headers = Headers('')
        if headers:
            if isinstance(headers, dict):
                headers = headers.items()
            for k, v in headers:
                self.headers.add(k, v)
        self.cookie = SimpleCookie()
        try:
            self.cookie.load(self.headers.one('Cookie', ''))
        except CookieError:
            pass


    def __repr__(self):
        return "<Response: %s>" % str(self)

    def __str__(self):
        return "%d %s" % (self.code, self._status())

    def _status(self):
        return status_strings.get(self.code, ('???','Unknown HTTP status'))

    def _to_diesel(self, _diesel_request):
        """This actually sends bits over the wire(!).
        """
        for morsel in self.cookie.values():
            self.headers.add('Set-Cookie', morsel.OutputString())
        self.headers._diesel_headers._headers = self.headers._dict
        return DieselResponse( _diesel_request
                             , self.code
                             , self.headers._diesel_headers
                             , self.body
                              )

    def _to_http(self, version):
        status_line = "HTTP/%s" % version
        headers = self.headers.to_http()
        body = self.body
        if self.headers.one('Content-Type', '').startswith('text/'):
            body = body.replace('\n', '\r\n')
            body = body.replace('\r\r', '\r')
        return '\r\n'.join([status_line, headers, '', body])
예제 #25
0
 def wrapped_start_response(status, response_headers, exc_info=None):
     sid = self.factory.save(environ["wsgi.session"])
     cookies = SimpleCookie()
     cookies["session_id"] = sid
     cookie = cookies["session_id"]
     cookie["path"] = cookie_path
     cookie["httponly"] = 1
     response_headers.extend(("set-cookie", morsel.OutputString()) for morsel in cookies.values())
     return start_response(status, response_headers, exc_info)
예제 #26
0
class WSGIResponse(object):
    """A basic HTTP response with content, headers, and out-bound cookies

    The class variable ``defaults`` specifies default values for
    ``content_type``, ``charset`` and ``errors``. These can be overridden
    for the current request via the registry.

    """
    defaults = StackedObjectProxy(
        default=dict(content_type='text/html', charset='utf-8', 
                     errors='strict', headers={'Cache-Control':'no-cache'})
        )
    def __init__(self, content='', mimetype=None, code=200):
        self._iter = None
        self._is_str_iter = True

        self.content = content
        self.headers = HeaderDict()
        self.cookies = SimpleCookie()
        self.status_code = code

        defaults = self.defaults._current_obj()
        if not mimetype:
            mimetype = defaults.get('content_type', 'text/html')
            charset = defaults.get('charset')
            if charset:
                mimetype = '%s; charset=%s' % (mimetype, charset)
        self.headers.update(defaults.get('headers', {}))
        self.headers['Content-Type'] = mimetype
        self.errors = defaults.get('errors', 'strict')

    def __str__(self):
        """Returns a rendition of the full HTTP message, including headers.

        When the content is an iterator, the actual content is replaced with the
        output of str(iterator) (to avoid exhausting the iterator).
        """
        if self._is_str_iter:
            content = ''.join(self.get_content())
        else:
            content = str(self.content)
        return '\n'.join(['%s: %s' % (key, value)
            for key, value in self.headers.headeritems()]) \
            + '\n\n' + content
    
    def __call__(self, environ, start_response):
        """Convenience call to return output and set status information
        
        Conforms to the WSGI interface for calling purposes only.
        
        Example usage:
        
        .. code-block:: Python

            def wsgi_app(environ, start_response):
                response = WSGIResponse()
                response.write("Hello world")
                response.headers['Content-Type'] = 'latin1'
                return response(environ, start_response)
        
        """
        status_text = STATUS_CODE_TEXT[self.status_code]
        status = '%s %s' % (self.status_code, status_text)
        response_headers = self.headers.headeritems()
        for c in self.cookies.values():
            response_headers.append(('Set-Cookie', c.output(header='')))
        start_response(status, response_headers)
        is_file = isinstance(self.content, file)
        if 'wsgi.file_wrapper' in environ and is_file:
            return environ['wsgi.file_wrapper'](self.content)
        elif is_file:
            return iter(lambda: self.content.read(), '')
        return self.get_content()
    
    def determine_charset(self):
        """
        Determine the encoding as specified by the Content-Type's charset
        parameter, if one is set
        """
        charset_match = _CHARSET_RE.search(self.headers.get('Content-Type', ''))
        if charset_match:
            return charset_match.group(1)
    
    def has_header(self, header):
        """
        Case-insensitive check for a header
        """
        warnings.warn('WSGIResponse.has_header is deprecated, use '
                      'WSGIResponse.headers.has_key instead', DeprecationWarning,
                      2)
        return self.headers.has_key(header)

    def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
                   domain=None, secure=None):
        """
        Define a cookie to be sent via the outgoing HTTP headers
        """
        self.cookies[key] = value
        for var_name, var_value in [
            ('max_age', max_age), ('path', path), ('domain', domain),
            ('secure', secure), ('expires', expires)]:
            if var_value is not None and var_value is not False:
                self.cookies[key][var_name.replace('_', '-')] = var_value

    def delete_cookie(self, key, path='/', domain=None):
        """
        Notify the browser the specified cookie has expired and should be
        deleted (via the outgoing HTTP headers)
        """
        self.cookies[key] = ''
        if path is not None:
            self.cookies[key]['path'] = path
        if domain is not None:
            self.cookies[key]['domain'] = path
        self.cookies[key]['expires'] = 0
        self.cookies[key]['max-age'] = 0

    def _set_content(self, content):
        if hasattr(content, '__iter__'):
            self._iter = content
            if isinstance(content, list):
                self._is_str_iter = True
            else:
                self._is_str_iter = False
        else:
            self._iter = [content]
            self._is_str_iter = True
    content = property(lambda self: self._iter, _set_content,
                       doc='Get/set the specified content, where content can '
                       'be: a string, a list of strings, a generator function '
                       'that yields strings, or an iterable object that '
                       'produces strings.')

    def get_content(self):
        """
        Returns the content as an iterable of strings, encoding each element of
        the iterator from a Unicode object if necessary.
        """
        charset = self.determine_charset()
        if charset:
            return encode_unicode_app_iter(self.content, charset, self.errors)
        else:
            return self.content
    
    def wsgi_response(self):
        """
        Return this WSGIResponse as a tuple of WSGI formatted data, including:
        (status, headers, iterable)
        """
        status_text = STATUS_CODE_TEXT[self.status_code]
        status = '%s %s' % (self.status_code, status_text)
        response_headers = self.headers.headeritems()
        for c in self.cookies.values():
            response_headers.append(('Set-Cookie', c.output(header='')))
        return status, response_headers, self.get_content()
    
    # The remaining methods partially implement the file-like object interface.
    # See http://docs.python.org/lib/bltin-file-objects.html
    def write(self, content):
        if not self._is_str_iter:
            raise IOError, "This %s instance's content is not writable: (content " \
                'is an iterator)' % self.__class__.__name__
        self.content.append(content)

    def flush(self):
        pass

    def tell(self):
        if not self._is_str_iter:
            raise IOError, 'This %s instance cannot tell its position: (content ' \
                'is an iterator)' % self.__class__.__name__
        return sum([len(chunk) for chunk in self._iter])

    ########################################
    ## Content-type and charset

    def charset__get(self):
        """
        Get/set the charset (in the Content-Type)
        """
        header = self.headers.get('content-type')
        if not header:
            return None
        match = _CHARSET_RE.search(header)
        if match:
            return match.group(1)
        return None

    def charset__set(self, charset):
        if charset is None:
            del self.charset
            return
        try:
            header = self.headers.pop('content-type')
        except KeyError:
            raise AttributeError(
                "You cannot set the charset when no content-type is defined")
        match = _CHARSET_RE.search(header)
        if match:
            header = header[:match.start()] + header[match.end():]
        header += '; charset=%s' % charset
        self.headers['content-type'] = header

    def charset__del(self):
        try:
            header = self.headers.pop('content-type')
        except KeyError:
            # Don't need to remove anything
            return
        match = _CHARSET_RE.search(header)
        if match:
            header = header[:match.start()] + header[match.end():]
        self.headers['content-type'] = header

    charset = property(charset__get, charset__set, charset__del, doc=charset__get.__doc__)

    def content_type__get(self):
        """
        Get/set the Content-Type header (or None), *without* the
        charset or any parameters.

        If you include parameters (or ``;`` at all) when setting the
        content_type, any existing parameters will be deleted;
        otherwise they will be preserved.
        """
        header = self.headers.get('content-type')
        if not header:
            return None
        return header.split(';', 1)[0]

    def content_type__set(self, value):
        if ';' not in value:
            header = self.headers.get('content-type', '')
            if ';' in header:
                params = header.split(';', 1)[1]
                value += ';' + params
        self.headers['content-type'] = value

    def content_type__del(self):
        try:
            del self.headers['content-type']
        except KeyError:
            pass

    content_type = property(content_type__get, content_type__set,
                            content_type__del, doc=content_type__get.__doc__)
예제 #27
0
 def add_cookie(self, name, value, path='/', expires=None):
     cookie = SimpleCookie()
     cookie[name] = value
     cookie[name]['path'] = path
     cookie[name]['expires'] = expires
     self.response.headers['Set-Cookie'] = cookie.values()[0].OutputString()
예제 #28
0
class Response(object):
    charset = 'utf-8'
    default_mimetype = 'text/html'

    def __init__(self, response=None, headers=None, status=200, mimetype=None):
        if response is None:
            self.response = []
        elif isinstance(response, basestring):
            self.response = [response]
        else:
            self.response = iter(response)
        if not headers:
            self.headers = Headers()
        elif isinstance(headers, Headers):
            self.headers = headers
        else:
            self.headers = Headers(headers)
        if mimetype is None and 'Content-Type' not in self.headers:
            mimetype = self.default_mimetype
        if mimetype is not None:
            if 'charset=' not in mimetype and mimetype.startswith('text/'):
                mimetype += '; charset=' + self.charset
            self.headers['Content-Type'] = mimetype
        self.status = status
        self._cookies = None

    def write(self, value):
        if not isinstance(self.response, list):
            raise RuntimeError('cannot write to streaming response')
        self.write = self.response.append
        self.response.append(value)

    def set_cookie(self, key, value='', max_age=None, expires=None,
                   path='/', domain=None, secure=None):
        if self._cookies is None:
            self._cookies = SimpleCookie()
        if isinstance(value, unicode):
            value = value.encode(self.charset)
        self._cookies[key] = value
        if max_age is not None:
            self._cookies[key]['max-age'] = max_age
        if expires is not None:
            if isinstance(expires, basestring):
                self._cookies[key]['expires'] = expires
                expires = None
            elif isinstance(expires, datetime):
                expires = expires.utctimetuple()
            elif not isinstance(expires, (int, long)):
                expires = gmtime(expires)
            else:
                raise ValueError('datetime or integer required')
            month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
                     'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][expires.tm_mon - 1]
            day = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
                   'Friday', 'Saturday', 'Sunday'][expires.tm_wday]
            date = '%02d-%s-%s' % (
                expires.tm_mday, month, str(expires.tm_year)[-2:]
            )
            d = '%s, %s %02d:%02d:%02d GMT' % (day, date, expires.tm_hour,
                                               expires.tm_min, expires.tm_sec)
            self._cookies[key]['expires'] = d
        if path is not None:
            self._cookies[key]['path'] = path
        if domain is not None:
            self._cookies[key]['domain'] = domain
        if secure is not None:
            self._cookies[key]['secure'] = secure

    def delete_cookie(self, key):
        if self._cookies is None:
            self._cookies = SimpleCookie()
        if key not in self._cookies:
            self._cookies[key] = ''
        self._cookies[key]['max-age'] = 0

    def __call__(self, environ, start_response):
        req = environ['werkzeug.request']
        if req.session.worth_saving:
            req.session.save()
            self.set_cookie(SID_COOKIE_NAME, req.session.sid)

        headers = self.headers.to_list(self.charset)
        if self._cookies is not None:
            for morsel in self._cookies.values():
                headers.append(('Set-Cookie', morsel.output(header='')))
        status = '%d %s' % (self.status, HTTP_STATUS_CODES[self.status])

        charset = self.charset or 'ascii'
        start_response(status, headers)
        for item in self.response:
            if isinstance(item, unicode):
                yield item.encode(charset)
            else:
                yield str(item)
예제 #29
0
	def _handle_cookies(self, response):
		# FIXME: this cookie handling doesn't respect path, domain and expiry
		cookies = SimpleCookie()
		cookies.load(response.getheader('set-cookie', ''))
		self.cookies.update(dict((cookie.key, cookie.value) for cookie in cookies.values()))
예제 #30
0
파일: wsgiutil.py 프로젝트: wiless/IMTAphy
class Response(object):
    charset = 'utf-8'
    default_mimetype = 'text/html'

    def __init__(self, response=None, headers=None, status=200, mimetype=None):
        if response is None:
            self.response = []
        elif isinstance(response, basestring):
            self.response = [response]
        else:
            self.response = iter(response)
        if not headers:
            self.headers = Headers()
        elif isinstance(headers, Headers):
            self.headers = headers
        else:
            self.headers = Headers(headers)
        if mimetype is None and 'Content-Type' not in self.headers:
            mimetype = self.default_mimetype
        if mimetype is not None:
            if 'charset=' not in mimetype and mimetype.startswith('text/'):
                mimetype += '; charset=' + self.charset
            self.headers['Content-Type'] = mimetype
        self.status = status
        self._cookies = None

    def write(self, value):
        if not isinstance(self.response, list):
            raise RuntimeError('cannot write to streaming response')
        self.write = self.response.append
        self.response.append(value)

    def set_cookie(self,
                   key,
                   value='',
                   max_age=None,
                   expires=None,
                   path='/',
                   domain=None,
                   secure=None):
        if self._cookies is None:
            self._cookies = SimpleCookie()
        if isinstance(value, unicode):
            value = value.encode(self.charset)
        self._cookies[key] = value
        if max_age is not None:
            self._cookies[key]['max-age'] = max_age
        if expires is not None:
            if isinstance(expires, basestring):
                self._cookies[key]['expires'] = expires
                expires = None
            elif isinstance(expires, datetime):
                expires = expires.utctimetuple()
            elif not isinstance(expires, (int, long)):
                expires = gmtime(expires)
            else:
                raise ValueError('datetime or integer required')
            month = [
                'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
                'Oct', 'Nov', 'Dec'
            ][expires.tm_mon - 1]
            day = [
                'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
                'Saturday', 'Sunday'
            ][expires.tm_wday]
            date = '%02d-%s-%s' % (expires.tm_mday, month, str(
                expires.tm_year)[-2:])
            d = '%s, %s %02d:%02d:%02d GMT' % (day, date, expires.tm_hour,
                                               expires.tm_min, expires.tm_sec)
            self._cookies[key]['expires'] = d
        if path is not None:
            self._cookies[key]['path'] = path
        if domain is not None:
            self._cookies[key]['domain'] = domain
        if secure is not None:
            self._cookies[key]['secure'] = secure

    def delete_cookie(self, key):
        if self._cookies is None:
            self._cookies = SimpleCookie()
        if key not in self._cookies:
            self._cookies[key] = ''
        self._cookies[key]['max-age'] = 0

    def __call__(self, environ, start_response):
        req = environ['werkzeug.request']
        if req.session.worth_saving:
            req.session.save()
            self.set_cookie(SID_COOKIE_NAME, req.session.sid)

        headers = self.headers.to_list(self.charset)
        if self._cookies is not None:
            for morsel in self._cookies.values():
                headers.append(('Set-Cookie', morsel.output(header='')))
        status = '%d %s' % (self.status, HTTP_STATUS_CODES[self.status])

        charset = self.charset or 'ascii'
        start_response(status, headers)
        for item in self.response:
            if isinstance(item, unicode):
                yield item.encode(charset)
            else:
                yield str(item)
예제 #31
0
from Cookie import SimpleCookie

session_cookie = SimpleCookie()
session_cookie['session'] = "somedata"
session_cookie['session']["Path"] = '/'

headers = {}
headers.update(("set-cookie", morsel.OutputString())
                   for morsel
                   in session_cookie.values())


print headers
예제 #32
0
    def __call__(self, environ, start_response):
        path = environ.get('PATH_INFO', '')
        if not path.startswith("/tale/"):
            # paths not under /tale/ won't get a session
            return self.app(environ, start_response)

        cookie = SimpleCookie()
        if 'HTTP_COOKIE' in environ:
            cookie.load(environ['HTTP_COOKIE'])
        sid = None
        if "session_id" in cookie:
            sid = cookie["session_id"].value
        environ["wsgi.session"] = self.factory.load(sid)

        # If the server runs behind a reverse proxy, you can configure the proxy
        # to pass along the uri that it exposes (our internal uri can be different)
        # via the X-Forwarded-Uri header. If we find this header we use it to
        # replace the "/tale" uri base by the one from the header, to use as cookie path.
        forwarded_uri = environ.get("HTTP_X_FORWARDED_URI", "/tale/")
        cookie_path = "/" + forwarded_uri.split("/", 2)[1]

        def wrapped_start_response(status, response_headers, exc_info=None):
            sid = self.factory.save(environ["wsgi.session"])
            cookies = SimpleCookie()
            cookies["session_id"] = sid
            cookie = cookies["session_id"]
            cookie["path"] = cookie_path
            cookie["httponly"] = 1
            response_headers.extend(("set-cookie", morsel.OutputString()) for morsel in cookies.values())
            return start_response(status, response_headers, exc_info)

        try:
            return self.app(environ, wrapped_start_response)
        except SessionMiddleware.CloseSession as x:
            self.factory.delete(sid)
            # clear the browser cookie
            cookies = SimpleCookie()
            cookies["session_id"] = "deleted"
            cookie = cookies["session_id"]
            cookie["path"] = cookie_path
            cookie["httponly"] = 1
            cookie["expires"] = "Thu, 01-Jan-1970 00:00:00 GMT"
            response_headers = [('Content-Type', x.content_type)]
            response_headers.extend(("set-cookie", morsel.OutputString()) for morsel in cookies.values())
            start_response("200 OK", response_headers)
            return [str(x).encode("utf-8")]
예제 #33
0
class WSGIResponse(object):
    """
    A basic HTTP response with content, headers, and out-bound cookies
    
    The class variable ``defaults`` specifies default values for
    ``content_type``, ``charset`` and ``errors``. These can be overridden
    for the current request via the registry.
    
    """
    
    # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
    HTTP_MAPPINGS = {
        100: 'CONTINUE',
        101: 'SWITCHING PROTOCOLS',
        200: 'OK',
        201: 'CREATED',
        202: 'ACCEPTED',
        203: 'NON-AUTHORITATIVE INFORMATION',
        204: 'NO CONTENT',
        205: 'RESET CONTENT',
        206: 'PARTIAL CONTENT',
        226: 'IM USED',
        300: 'MULTIPLE CHOICES',
        301: 'MOVED PERMANENTLY',
        302: 'FOUND',
        303: 'SEE OTHER',
        304: 'NOT MODIFIED',
        305: 'USE PROXY',
        306: 'RESERVED',
        307: 'TEMPORARY REDIRECT',
        400: 'BAD REQUEST',
        401: 'UNAUTHORIZED',
        402: 'PAYMENT REQUIRED',
        403: 'FORBIDDEN',
        404: 'NOT FOUND',
        405: 'METHOD NOT ALLOWED',
        406: 'NOT ACCEPTABLE',
        407: 'PROXY AUTHENTICATION REQUIRED',
        408: 'REQUEST TIMEOUT',
        409: 'CONFLICT',
        410: 'GONE',
        411: 'LENGTH REQUIRED',
        412: 'PRECONDITION FAILED',
        413: 'REQUEST ENTITY TOO LARGE',
        414: 'REQUEST-URI TOO LONG',
        415: 'UNSUPPORTED MEDIA TYPE',
        416: 'REQUESTED RANGE NOT SATISFIABLE',
        417: 'EXPECTATION FAILED',
        500: 'INTERNAL SERVER ERROR',
        501: 'NOT IMPLEMENTED',
        502: 'BAD GATEWAY',
        503: 'SERVICE UNAVAILABLE',
        504: 'GATEWAY TIMEOUT',
        505: 'HTTP VERSION NOT SUPPORTED'
    }
    
    def __init__(self, content='', headers={}, status_code=200):
        "Initialise our response, assuming everything is fine"
        
        self.status_code = status_code
        self.set_content(content)
        self._headers = headers
        self._headers['content-length'] = str(len(content))
        self.cookies = SimpleCookie()
        
        # lets assume text/html unless told otherwise
        if not 'content-type' in self.headers:
            self._headers['content-type'] = 'text/html'
        
    def get_status(self):
        "Get the status code and message, but make sure it's valid first"
        if self.status_code not in self.HTTP_MAPPINGS:
            # invalid code, so something has gone wrong
            self.status_code = 500
        return "%s %s" % (self.status_code, self.HTTP_MAPPINGS[self.status_code])
        
    def set_status(self, code):
        "API setter method"
        if self.status_code not in self.HTTP_MAPPINGS:
            # invalid code, so something has gone wrong
            self.status_code = 500
        else:
            self.status_code = code
        
    def get_headers(self):
        "Return the headers as a list"
        return list(self._headers.iteritems())
        
    def set_headers(self, *args):
        "Set the response headers, takes either a key/value or a dictionary"
        if type(args[0]).__name__ == 'dict':
            self._headers.update(args[0])
        else:
            key, value = args
            self._headers[key] = value
        
    def get_content(self):
        "Return the body of the response in a useful format"
        return [self._content, '\n']
        
    def set_content(self, value):
        "Set the body of the response, ensuring we're using utf-8"
        # http://www.python.org/dev/peps/pep-0333/#unicode-issues
        if isinstance(value, unicode):
            value = value.encode('utf-8')
        self._content = value
    
    def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
                   domain=None, secure=None, httponly=None):
        """
        Define a cookie to be sent via the outgoing HTTP headers
        """
        self.cookies[key] = value
        for var_name, var_value in [
            ('max_age', max_age), ('path', path), ('domain', domain),
            ('secure', secure), ('expires', expires), ('httponly', httponly)]:
            if var_value is not None and var_value is not False:
                self.cookies[key][var_name.replace('_', '-')] = var_value
    
    def delete_cookie(self, key, path='/', domain=None):
        """
        Notify the browser the specified cookie has expired and should be
        deleted (via the outgoing HTTP headers)
        """
        self.cookies[key] = ''
        if path is not None:
            self.cookies[key]['path'] = path
        if domain is not None:
            self.cookies[key]['domain'] = domain
        self.cookies[key]['expires'] = 0
        self.cookies[key]['max-age'] = 0
        
    content = property(get_content, set_content)
    status = property(get_status, set_status)
    headers = property(get_headers, set_headers)
    
    def __str__(self):
        """Returns a rendition of the full HTTP message, including headers.
        
        When the content is an iterator, the actual content is replaced with the
        output of str(iterator) (to avoid exhausting the iterator).
        """
        if self._is_str_iter:
            content = ''.join(self.get_content())
        else:
            content = str(self.content)
        return '\n'.join(['%s: %s' % (key, value)
            for key, value in self.headers.headeritems()]) \
            + '\n\n' + content
    
    def __call__(self, environ, start_response):
        """
        Convenience call to return output and set status information
        
        Conforms to the WSGI interface for calling purposes only.
        
        Example usage:
        
        .. code-block:: python
        
            def wsgi_app(environ, start_response):
                response = WSGIResponse()
                response.write("Hello world")
                response.headers['Content-Type'] = 'latin1'
                return response(environ, start_response)
        
        """
        for c in self.cookies.values():
            self.headers.append(('Set-Cookie', c.output(header='')))
        start_response(self.status, self.headers)
        is_file = isinstance(self.content, file)
        if 'wsgi.file_wrapper' in environ and is_file:
            return environ['wsgi.file_wrapper'](self.content)
        elif is_file:
            return iter(lambda: self.content.read(), '')
        return self.get_content()
예제 #34
0
class Response(Exception):
    """Represent an HTTP Response message.
    """

    def __init__(self, code=200, body='', headers=None):
        """Takes an int, a string, and a dict (or list of tuples).

            - code      an HTTP response code, e.g., 404
            - body      the message body as a string
            - headers   a Headers instance
            - cookie    a Cookie.SimpleCookie instance

        Code is first because when you're raising your own Responses, they're
        usually error conditions. Body is second because one more often wants
        to specify a body without headers, than a header without a body.

        """
        if not isinstance(code, int):
            raise TypeError("'code' must be an integer")
        elif not isinstance(body, basestring):
            raise TypeError("'body' must be a string")
        elif headers is not None and not isinstance(headers, (dict, list)):
            raise TypeError("'headers' must be a dictionary or a list of " +
                            "2-tuples")

        Exception.__init__(self)
        self.code = code
        self.body = body
        self.headers = Headers('')
        if headers:
            if isinstance(headers, dict):
                headers = headers.items()
            for k, v in headers:
                self.headers.add(k, v)
        self.cookie = SimpleCookie()
        try:
            self.cookie.load(self.headers.one('Cookie', ''))
        except CookieError:
            pass

    def __call__(self, environ, start_response):
        wsgi_status = str(self)
        for morsel in self.cookie.values():
            self.headers.add('Set-Cookie', morsel.OutputString())
        wsgi_headers = []
        for k, vals in self.headers._dict.items():
            for v in vals:
                wsgi_headers.append((k, v))
        start_response(wsgi_status, wsgi_headers)
        return [self.body]

    def __repr__(self):
        return "<Response: %s>" % str(self)

    def __str__(self):
        return "%d %s" % (self.code, self._status())

    def _status(self):
        return status_strings.get(self.code, 'Unknown HTTP status')

    def _to_http(self, version):
        """Given a version string like 1.1, return an HTTP message, a string.
        """
        status_line = "HTTP/%s" % version
        headers = self.headers.to_http()
        body = self.body
        if self.headers.one('Content-Type', '').startswith('text/'):
            body = body.replace('\n', '\r\n')
            body = body.replace('\r\r', '\r')
        return '\r\n'.join([status_line, headers, '', body])
예제 #35
0
파일: fpyf.py 프로젝트: fluxid/fpyf
class Response(object):
    def __init__(self, content=None, status=200, content_type='text/html', encoding='utf-8', headers=None): #, default_type='text/html', default_encoding='utf-8'):
        status = int(status)
        self.content = content
        self.status = status if status in STATUSES else 200
        self.content_type = content_type
        self.encoding = encoding
        self.headers = headers or {}
        #self.default_type = default_type
        #self.default_encoding = default_encoding

        self.cookies = SimpleCookie()

    def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=False):
        if expires:
            t = type(expires)
            if t == date:
                expires = datetime(expires.year, expires.month, expires.day)
            elif t == time:
                expires = datetime.now().replace(hour=expires.hour, minute=expires.minute, second=expires.second)
            elif t in (int, long):
                expires = datetime.fromtimestamp(expires)
            else:
                Exception('Cookie expire time has incorrect type')

            if not (hasattr(expires, 'tzinfo') and expires.tzinfo):
                expires = expires.replace(tzinfo=dateutil.tz.tzlocal())
            expires = expires.strftime('%a, %d %b %Y %H:%M:%S %z')

        self.cookies[key] = value
        cookie = self.cookies[key]
        if max_age is not None:
            cookie['max-age'] = max_age
        if expires is not None:
            cookie['expires'] = expires
        if path is not None:
            cookie['path'] = path
        if domain is not None:
            cookie['domain'] = domain
        if secure:
            cookie['secure'] = True

    def delete_cookie(self, key, path='/', domain=None):
        self.set_cookie(key, max_age=0, path=path, domain=domain, expires=datetime(1970, 1, 1))

    def prepare(self):
        #self.content_type = self.content_type or self.default_type
        #self.encoding = self.encoding or self.default_encoding

        if isinstance(self.content, unicode):
            self.content = self.content.encode(self.encoding)
        elif not isinstance(self.content, str):
            self.content = str(self.content)
    
    def do_respond_wsgi(self, start_response):
        self.prepare()
        status = '%s %s' % (self.status, STATUSES[self.status])
        headers = self.headers.items()
        if self.content_type:
            if self.encoding:
                headers.append(
                    ('Content-type', '%s; charset=%s' % (self.content_type, self.encoding))
                )
            else:
                headers.append(
                    ('Content-type', '%s' % self.content_type)
                )
        if self.cookies:
            for c in self.cookies.values():
                headers.append(('Set-Cookie', str(c.output(header=''))))
        start_response(status, headers)
        return self.content