예제 #1
0
 def __init__(self, webapp, server, outs):
     self.webapp = webapp  # not a weakref, because a response object is short-lived.
     self.server = server
     self._outs = self.outs = outs
     self.content_type = "text/html"
     self.content_encoding = None
     self.content_length = -1
     self.content_disposition = None
     self.header_written = False
     self.error_sent = False
     self.redirection_performed = False
     self.__being_redirected = False
     self.response_code = 200
     self.response_string = "OK"
     self.userHeaders = NormalizedHeaderDict()
     self.cookies = Cookie.SimpleCookie()
     self.__outputsstack = []
예제 #2
0
 def __init__(self, webapp, server, outs):
     self.webapp=webapp  # not a weakref, because a response object is short-lived.
     self.server=server
     self._outs=self.outs=outs
     self.content_type="text/html"
     self.content_encoding=None
     self.content_length=-1
     self.content_disposition=None
     self.header_written=False
     self.error_sent=False
     self.redirection_performed=False
     self.__being_redirected=False
     self.response_code=200
     self.response_string="OK"
     self.userHeaders=NormalizedHeaderDict()
     self.cookies=Cookie.SimpleCookie()
     self.__outputsstack=[]
예제 #3
0
class Response(object):
    def __init__(self, webapp, server, outs):
        self.webapp=webapp  # not a weakref, because a response object is short-lived.
        self.server=server
        self._outs=self.outs=outs
        self.content_type="text/html"
        self.content_encoding=None
        self.content_length=-1
        self.content_disposition=None
        self.header_written=False
        self.error_sent=False
        self.redirection_performed=False
        self.__being_redirected=False
        self.response_code=200
        self.response_string="OK"
        self.userHeaders=NormalizedHeaderDict()
        self.cookies=Cookie.SimpleCookie()
        self.__outputsstack=[]
    def setContentType(self, type):
        self.content_type=type
    def setContentDisposition(self, disposition):
        self.content_disposition=disposition
    def setContentLength(self, length, force=False):
        if not force and self.content_encoding:
            raise IOError("cannot set content length if a custom output encoding has been specified")
        self.content_length=length
        if self.server:
            self.server.content_length=length
    def getEncoding(self):
        return self.content_encoding
    def setEncoding(self, encoding):
        if self.__being_redirected or self.content_encoding==encoding:
            # We're being used in a redirection/inclusion, or the specified encoding
            # is already set. Do not change the encoding in both cases.
            return
        self.content_encoding=encoding
        if self.content_length>=0:
            raise IOError("cannot set custom output encoding if contentlength has been specified")
        if encoding:
            self.outs=codecs.getwriter(encoding)(self._outs, errors="xmlcharrefreplace")
        else:
            self.outs=self._outs # remove codec
    def forceEncoding(self, encoding):
        # set an encoding. No checks! Danger! Normal usage should be setEncoding.
        self.content_encoding = encoding
    def guessMimeType(self, filename):
        return self.server.guess_type(filename)
    def setHeader(self, header, value):
        self.userHeaders[header]=value
    def getHeader(self, header):
        return self.userHeaders.get(header)
    def setResponse(self, code, msg="Snakelet output follows"):
        self.response_code=code
        self.response_string=msg
    def HTTPredirect(self, URL):
        if self.header_written:
            raise RuntimeError('can not redirect when getOutput() has been called')
        self.setResponse(302) # HTTP 302=redirect (Found)
        self.userHeaders["Location"]=URL
        out=self.getOutput()
        out.write("<html><head><title>Redirection</title></head>\n"
                  "<body><h1>Redirection</h1>\nYou're being <a href=\""+URL+"\">redirected</a>.</body></html>")
        self.setRedirectionDone()
    def writeHeader(self):
        # minimalistic HTTP response header
        if self.header_written:
            raise RuntimeError("header has already been written")
        self.server.send_response(self.response_code, self.response_string)
        contentType=self.content_type
        if self.content_encoding:
            contentType+="; charset="+self.content_encoding
        self.userHeaders["Content-Type"]=contentType
        if self.content_disposition:
            self.userHeaders["Content-Disposition"]=self.content_disposition
        if self.content_length>=0:
            self.userHeaders["Content-Length"]=str(self.content_length)
        for (h,v) in self.userHeaders.iteritems():
            self.server.send_header(h,v)
        for c in self.cookies.values():
            self.server.send_header("Set-Cookie",c.OutputString())
        self.server.end_headers()
        self.header_written=True
    def getOutput(self):
        if self.redirection_performed:
            raise RuntimeError('cannot write after redirect() call')
        if not self.header_written:
            self.writeHeader()
        return self.outs
    def sendError(self, code, message=None):
        if not self.header_written:
            self.error_sent=True
            self.header_written=True
            self.server.send_error(code, message, self.userHeaders)
        else:
            raise RuntimeError("cannot send error after header has been written")
    def getCookies(self):
        return self.cookies
    def setCookie(self, name, value, path=None, domain=None, maxAge=None, comment=None, secure=None):
        self.cookies[name]=value
        self.cookies[name]["version"]=1
        self.cookies[name]["path"]=''
        self.cookies[name]["domain"]=''
        self.cookies[name]["max-age"]=''
        self.cookies[name]["expires"]=''
        self.cookies[name]["comment"]=''
        self.cookies[name]["secure"]=''
        if path: self.cookies[name]["path"]=path
        if domain: self.cookies[name]["domain"]=domain
        if maxAge!=None:
            self.cookies[name]["max-age"]=maxAge  # for modern browsers
            if maxAge>0:
                self.cookies[name]["expires"]=maxAge  # for Internet Explorer
            else:
                # discard cookie, set expires to a time far in the past
                self.cookies[name]["expires"]="Mon, 01-Jan-1900 00:00:00 GMT"  # for Internet Explorer
        if comment: self.cookies[name]["comment"]=comment
        if secure: self.cookies[name]["secure"]=secure
        self.userHeaders["P3P"]="CP='CUR ADM OUR NOR STA NID'"    # P3P compact policy
    def delCookie(self, name, path=None, domain=None, comment=None, secure=None):
        # delete the cookie by setting maxAge to zero.
        self.setCookie(name, "", path, domain, 0, comment, secure)
        
    def setRedirectionDone(self):
        self.__being_redirected=False
        self.redirection_performed=True
    def beingRedirected(self):
        return self.__being_redirected
    def used(self):
        return self.redirection_performed or self.header_written or self.error_sent
    def kill(self):
        self.server.kill()
        self.error_sent=True
    def initiateRedirection(self,url, isInclude=False):
        self.__being_redirected = True
        if self.header_written:
            self.outs.flush()
        else:
            if isInclude:
                self.writeHeader()
            #else:
                # XXX we used to send a Content-Location header, but the handling is inconsistent
                # among the web-browsers. Opera does it "right" (follows 
                # the RFC http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.14
                # but other browsers such as IE/Mozilla/Firefox do NOT follow the RFC.
                # See https://bugzilla.mozilla.org/show_bug.cgi?id=109553
                # So we don't send this header, and all will be right. I hope.
                # self.userHeaders["Content-Location"]=url
    def wasErrorSent(self):
        return self.error_sent
    def YpushOutput(self, output):
        self.__outputsstack.append(self._outs)  # save old output
        self._outs=self.outs=output
    def YpopOutput(self):
        oldOut = self.__outputsstack.pop()
        self._outs=self.outs=oldOut
    def forceFlush(self, stream):   # force response flush to output stream
        out=self.getOutput()
        stream.flush()
        if hasattr(out, 'fileno'):
            if out.fileno()==stream.fileno():
                # using direct stream, we're done
                return
            else:
                del out, stream
                raise IOError("response is a stream but not the socket. Don't know how to handle this. Bail out")
        # we're using a custom output buffer such as a StringIO. Flush that.
        out.seek(0)
        self.server.copyfile(out, stream, not self.__being_redirected)  # don't close when being redirected..
        # now clear the output buffer
        out.seek(0)
        out.truncate()
예제 #4
0
class Response(object):
    def __init__(self, webapp, server, outs):
        self.webapp = webapp  # not a weakref, because a response object is short-lived.
        self.server = server
        self._outs = self.outs = outs
        self.content_type = "text/html"
        self.content_encoding = None
        self.content_length = -1
        self.content_disposition = None
        self.header_written = False
        self.error_sent = False
        self.redirection_performed = False
        self.__being_redirected = False
        self.response_code = 200
        self.response_string = "OK"
        self.userHeaders = NormalizedHeaderDict()
        self.cookies = Cookie.SimpleCookie()
        self.__outputsstack = []

    def setContentType(self, type):
        self.content_type = type

    def setContentDisposition(self, disposition):
        self.content_disposition = disposition

    def setContentLength(self, length, force=False):
        if not force and self.content_encoding:
            raise IOError(
                "cannot set content length if a custom output encoding has been specified"
            )
        self.content_length = length
        if self.server:
            self.server.content_length = length

    def getEncoding(self):
        return self.content_encoding

    def setEncoding(self, encoding):
        if self.__being_redirected or self.content_encoding == encoding:
            # We're being used in a redirection/inclusion, or the specified encoding
            # is already set. Do not change the encoding in both cases.
            return
        self.content_encoding = encoding
        if self.content_length >= 0:
            raise IOError(
                "cannot set custom output encoding if contentlength has been specified"
            )
        if encoding:
            self.outs = codecs.getwriter(encoding)(self._outs,
                                                   errors="xmlcharrefreplace")
        else:
            self.outs = self._outs  # remove codec

    def forceEncoding(self, encoding):
        # set an encoding. No checks! Danger! Normal usage should be setEncoding.
        self.content_encoding = encoding

    def guessMimeType(self, filename):
        return self.server.guess_type(filename)

    def setHeader(self, header, value):
        self.userHeaders[header] = value

    def getHeader(self, header):
        return self.userHeaders.get(header)

    def setResponse(self, code, msg="Snakelet output follows"):
        self.response_code = code
        self.response_string = msg

    def HTTPredirect(self, URL):
        if self.header_written:
            raise RuntimeError(
                'cannot redirect when getOutput() has been called')
        self.setResponse(302)  # HTTP 302=redirect (Found)
        self.userHeaders["Location"] = URL
        out = self.getOutput()
        out.write("<html><head><title>Redirection</title></head>\n"
                  "<body><h1>Redirection</h1>\nYou're being <a href=\"" + URL +
                  "\">redirected</a>.</body></html>")
        self.setRedirectionDone()

    def writeHeader(self):
        # minimalistic HTTP response header
        if self.header_written:
            raise RuntimeError("header has already been written")
        self.server.send_response(self.response_code, self.response_string)
        contentType = self.content_type
        if self.content_encoding:
            contentType += "; charset=" + self.content_encoding
        self.userHeaders["Content-Type"] = contentType
        if self.content_disposition:
            self.userHeaders["Content-Disposition"] = self.content_disposition
        if self.content_length >= 0:
            self.userHeaders["Content-Length"] = str(self.content_length)
        for (h, v) in self.userHeaders.iteritems():
            self.server.send_header(h, v)
        for c in self.cookies.values():
            self.server.send_header("Set-Cookie", c.OutputString())
        self.server.end_headers()
        self.header_written = True

    def getOutput(self):
        if self.redirection_performed:
            raise RuntimeError('cannot write after redirect() call')
        if not self.header_written:
            self.writeHeader()
        return self.outs

    def sendError(self, code, message=None):
        if not self.header_written:
            self.error_sent = True
            self.header_written = True
            self.server.send_error(code, message, self.userHeaders)
        else:
            raise RuntimeError(
                "cannot send error after header has been written")

    def getCookies(self):
        return self.cookies

    def setCookie(self,
                  name,
                  value,
                  path=None,
                  domain=None,
                  maxAge=None,
                  comment=None,
                  secure=None):
        self.cookies[name] = value
        self.cookies[name]["version"] = 1
        self.cookies[name]["path"] = ''
        self.cookies[name]["domain"] = ''
        self.cookies[name]["max-age"] = ''
        self.cookies[name]["expires"] = ''
        self.cookies[name]["comment"] = ''
        self.cookies[name]["secure"] = ''
        if path: self.cookies[name]["path"] = path
        if domain: self.cookies[name]["domain"] = domain
        if maxAge != None:
            self.cookies[name]["max-age"] = maxAge  # for modern browsers
            if maxAge > 0:
                self.cookies[name]["expires"] = maxAge  # for Internet Explorer
            else:
                # discard cookie, set expires to a time far in the past
                self.cookies[name][
                    "expires"] = "Mon, 01-Jan-1900 00:00:00 GMT"  # for Internet Explorer
        if comment: self.cookies[name]["comment"] = comment
        if secure: self.cookies[name]["secure"] = secure
        self.userHeaders[
            "P3P"] = "CP='CUR ADM OUR NOR STA NID'"  # P3P compact policy

    def delCookie(self,
                  name,
                  path=None,
                  domain=None,
                  comment=None,
                  secure=None):
        # delete the cookie by setting maxAge to zero.
        self.setCookie(name, "", path, domain, 0, comment, secure)

    def setRedirectionDone(self):
        self.__being_redirected = False
        self.redirection_performed = True

    def beingRedirected(self):
        return self.__being_redirected

    def used(self):
        return self.redirection_performed or self.header_written or self.error_sent

    def kill(self):
        self.server.kill()
        self.error_sent = True

    def initiateRedirection(self, url, isInclude=False):
        self.__being_redirected = True
        if self.header_written:
            self.outs.flush()
        else:
            if isInclude:
                self.writeHeader()
            #else:
            # XXX we used to send a Content-Location header, but the handling is inconsistent
            # among the web-browsers. Opera does it "right" (follows
            # the RFC http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.14
            # but other browsers such as IE/Mozilla/Firefox do NOT follow the RFC.
            # See https://bugzilla.mozilla.org/show_bug.cgi?id=109553
            # So we don't send this header, and all will be right. I hope.
            # self.userHeaders["Content-Location"]=url

    def wasErrorSent(self):
        return self.error_sent

    def YpushOutput(self, output):
        self.__outputsstack.append(self._outs)  # save old output
        self._outs = self.outs = output

    def YpopOutput(self):
        oldOut = self.__outputsstack.pop()
        self._outs = self.outs = oldOut

    def forceFlush(self, stream):  # force response flush to output stream
        out = self.getOutput()
        stream.flush()
        if hasattr(out, 'fileno'):
            if out.fileno() == stream.fileno():
                # using direct stream, we're done
                return
            else:
                del out, stream
                raise IOError(
                    "response is a stream but not the socket. Don't know how to handle this. Bail out"
                )
        # we're using a custom output buffer such as a StringIO. Flush that.
        out.seek(0)
        self.server.copyfile(
            out, stream,
            not self.__being_redirected)  # don't close when being redirected..
        # now clear the output buffer
        out.seek(0)
        out.truncate()