[Zope-Checkins] CVS: Zope3/lib/python/Zope/Publisher/HTTP - IHTTPResponse.py:1.1.2.1 HTTPRequest.py:1.1.2.21.2.2 HTTPResponse.py:1.1.2.13.4.2 IHTTPRequest.py:1.1.2.2.4.1
Jim Fulton
jim@zope.com
Wed, 20 Mar 2002 18:42:32 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/Publisher/HTTP
In directory cvs.zope.org:/tmp/cvs-serv21411/Zope/Publisher/HTTP
Modified Files:
Tag: Zope3-publisher-refactor-branch
HTTPRequest.py HTTPResponse.py IHTTPRequest.py
Added Files:
Tag: Zope3-publisher-refactor-branch
IHTTPResponse.py
Log Message:
Began significant refactoring of publication framework.
- Added accessor functions, getResponse and getPublication.
- Moved some methods between existing interfaces as seem best, and
added new new interfaces.
- Getting rid of payloads.
=== Added File Zope3/lib/python/Zope/Publisher/HTTP/IHTTPResponse.py ===
##############################################################################
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""
$Id: IHTTPResponse.py,v 1.1.2.1 2002/03/20 23:42:32 jim Exp $
"""
from Interface import Interface
class IHTTPResponse(Interface):
def getStatus():
'Returns the current HTTP status code as an integer. '
def setStatus(status, reason=None):
'''Sets the HTTP status code of the response
The argument may either be an integer or a string from { OK,
Created, Accepted, NoContent, MovedPermanently,
MovedTemporarily, NotModified, BadRequest, Unauthorized,
Forbidden, NotFound, InternalError, NotImplemented,
BadGateway, ServiceUnavailable } that will be converted to the
correct integer value.
'''
def setHeader(name, value, literal=0):
'''Sets an HTTP return header "name" with value "value"
The previous value is cleared. If the literal flag is true,
the case of the header name is preserved, otherwise
word-capitalization will be performed on the header name on
output.
'''
def addHeader(name, value):
'''Add an HTTP Header
Sets a new HTTP return header with the given value, while retaining
any previously set headers with the same name.
'''
def appendToCookie(name, value):
'''Append text to a cookie value
If a value for the cookie has previously been set, the new
value is appended to the old one separated by a colon.
'''
def expireCookie(name, **kw):
'''Causes an HTTP cookie to be removed from the browser
The response will include an HTTP header that will remove the cookie
corresponding to "name" on the client, if one exists. This is
accomplished by sending a new cookie with an expiration date
that has already passed. Note that some clients require a path
to be specified - this path must exactly match the path given
when creating the cookie. The path can be specified as a keyword
argument.
'''
def setCookie(name, value, **kw):
'''Sets an HTTP cookie on the browser
The response will include an HTTP header that sets a cookie on
cookie-enabled browsers with a key "name" and value
"value". This overwrites any previously set value for the
cookie in the Response object.
'''
def appendToHeader(name, value, delimiter=","):
'''Appends a value to a header
Sets an HTTP return header "name" with value "value",
appending it following a comma if there was a previous value
set for the header.
'''
=== Zope3/lib/python/Zope/Publisher/HTTP/HTTPRequest.py 1.1.2.21.2.1 => 1.1.2.21.2.2 ===
self._environ=environ
- self.__getPath()
+ self.__setupPath()
+ self.__setupCookies()
+
+
+ def __setupCookies(self)
################################################################
# Cookie values should *not* be appended to existing form
# vars with the same name - they are more like default values
# for names not otherwise specified in the form.
+ other = self._other
cookies={}
- k=environ.get('HTTP_COOKIE','')
- if k:
- parse_cookie(k, cookies)
- for k,item in cookies.items():
- if not other.has_key(k):
- other[k]=item
+ cookie_header = self._environ.get('HTTP_COOKIE','')
+ if cookie_header:
+ parse_cookie(cookie_header, cookies)
+ for cookie, item in cookies.items():
+ other.setdefault(cookie, item)
+
self.__cookies = cookies
- def __getPath(self):
+ def __setupPath(self):
path = self.get('PATH_INFO', '').strip()
if path.startswith('/'): path = path[1:] # XXX Why? Not sure
clean = []
@@ -133,16 +138,18 @@
clean.reverse()
self.setTraversalStack(clean)
- def getCookies(self):
- return self.__cookies
+ ######################################
+ # from: Zope.Publisher.IPublisherRequest.IPublisherRequest
- def supports_retry(self):
+ def supportsRetry(self):
+ 'See Zope.Publisher.IPublisherRequest.IPublisherRequest'
if self.retry_count < self.retry_max_count:
if STAGGER_RETRIES:
time.sleep(whrandom.uniform(0, 2**(self.retry_count)))
return 1
def retry(self):
+ 'See Zope.Publisher.IPublisherRequest.IPublisherRequest'
self.retry_count=self.retry_count+1
self.body_instream.seek(0)
r=self.__class__(
@@ -153,30 +160,10 @@
r.retry_count=self.retry_count
return r
- def getHeader(self, name, default=None):
- """Return the named HTTP header, or an optional default
- argument or None if the header is not found. Note that
- both original and CGI-ified header names are recognized,
- e.g. 'Content-Type', 'CONTENT_TYPE' and 'HTTP_CONTENT_TYPE'
- should all return the Content-Type header, if available.
- """
- environ = self._environ
- name = name.replace('-', '_').upper()
- val = environ.get(name, None)
- if val is not None:
- return val
- if not name.startswith('HTTP_'):
- name='HTTP_%s' % name
- return environ.get(name, default)
-
- def __str__(self):
- return self.payload.debugInfo(self)
+ def traverse(self, object):
+ 'See Zope.Publisher.IPublisherRequest.IPublisherRequest'
- def traverse(self, publication, object):
- """
- Traverses to an object and returns it.
- Private.
- """
+ publication = self.getPublication()
traversal_altered = 0 # flag for adding traversal steps
add_steps = None
@@ -251,37 +238,41 @@
return object
- def text(self):
- result = "URL: %s\n" % self.URL
- result = result + "SERVER_URL: %s\n\n" % self.SERVER_URL
- result = result + "FORM\n\n"
- row='%-20s %s\n'
- for k,v in self.form.items():
- result=result + row % (k, repr(v))
- result=result+"\nCOOKIES\n\n"
- for k,v in self.cookies.items():
- result=result + row % (k, repr(v))
- result=result+"\nOTHER\n\n"
- for k,v in self.other.items():
- if k in ('PARENTS','RESPONSE'): continue
- result=result + row % (k, repr(v))
-
- for n in "0123456789":
- key = "URL%s"%n
- try: result=result + row % (key, self[key])
- except KeyError: pass
- for n in "0123456789":
- key = "BASE%s"%n
- try: result=result + row % (key, self[key])
- except KeyError: pass
-
- result=result+"\nENVIRON\n\n"
- for k,v in self.environ.items():
- if not hide_key(k):
- result=result + row % (k, v)
- return result
+ #
+ ######################################
+
+ ############################################################
+ # Implementation methods for interface
+ # Zope.Publisher.HTTP.IHTTPRequest.
+
+ def getHeader(self, name, default=None):
+ 'See Zope.Publisher.HTTP.IHTTPRequest.IHTTPRequest'
+ environ = self._environ
+ name = name.replace('-', '_').upper()
+ val = environ.get(name, None)
+ if val is not None:
+ return val
+ if not name.startswith('HTTP_'):
+ name='HTTP_%s' % name
+ return environ.get(name, default)
+
+ def getCookies(self):
+ 'See Zope.Publisher.HTTP.IHTTPRequest.IHTTPRequest'
+ return self.__cookies
+
+ def setPathSuffix(self, steps):
+ 'See Zope.Publisher.HTTP.IHTTPRequest.IHTTPRequest'
+ self.__path_suffix = steps
+
+ #
+ ############################################################
+
+ ############################################################
+ # Implementation methods for interface
+ # Zope.Publisher.HTTP.IHTTPCredentials.
def _authUserPW(self):
+ 'See Zope.Publisher.HTTP.IHTTPCredentials.IHTTPCredentials'
global base64
auth=self._auth
if auth:
@@ -292,17 +283,12 @@
return name, password
def unauthorized(self, challenge):
+ 'See Zope.Publisher.HTTP.IHTTPCredentials.IHTTPCredentials'
self.response.setHeader("WWW-Authenticate", challenge, 1)
self.response.setStatus(401)
-
- # _viewtype is overridden from the BaseRequest
- # to implement IBrowserPublisher
- _viewtype = IBrowserPublisher
-
- # XXX this doesn't belong here
- def getEffectiveURL(self):
- return self.effective_url or self.URL
+ #
+ ############################################################
base64 = None
=== Zope3/lib/python/Zope/Publisher/HTTP/HTTPResponse.py 1.1.2.13.4.1 => 1.1.2.13.4.2 ===
self.header_output)
+ def getStatus(self):
+ return self.status
+
def setStatus(self, status, reason=None):
- '''
- Sets the HTTP status code of the response; the argument may
- either be an integer or a string from { OK, Created, Accepted,
- NoContent, MovedPermanently, MovedTemporarily,
- NotModified, BadRequest, Unauthorized, Forbidden,
- NotFound, InternalError, NotImplemented, BadGateway,
- ServiceUnavailable } that will be converted to the correct
- integer value.
- '''
if status is None:
status = 200
else:
@@ -162,13 +156,6 @@
self.reason = reason
def setHeader(self, name, value, literal=0):
- '''
- Sets an HTTP return header "name" with value "value", clearing
- the previous value set for the header, if one exists. If the
- literal flag is true, the case of the header name is preserved,
- otherwise word-capitalization will be performed on the header
- name on output.
- '''
key = name.lower()
if accumulate_header(key):
self.addHeader(name, value)
@@ -176,12 +163,7 @@
name = literal and name or key
self.headers[name]=value
- __setitem__ = setHeader
-
def addHeader(self, name, value):
- '''
- Sets a new HTTP return header with the given value, while retaining
- any previously set headers with the same name.'''
accum = self.accumulated_headers
if not accum:
self.accumulated_headers = accum = []
@@ -190,18 +172,13 @@
def setBody(self, body):
return self.payload.setBody(self, body)
- def updateContentLength(self):
+ def __updateContentLength(self):
blen = str(len(self.body))
if blen.endswith('L'):
blen = blen[:-1]
self.setHeader('content-length', blen)
def appendToCookie(self, name, value):
- '''
- Creates an HTTP header that sets a cookie on cookie-enabled
- browsers with a key "name" and value "value". If a value for the
- cookie has previously been set in the response object, the new
- value is appended to the old one separated by a colon. '''
cookies=self.cookies
if cookies.has_key(name): cookie=cookies[name]
@@ -211,17 +188,6 @@
else: cookie['value']=value
def expireCookie(self, name, **kw):
- '''
- Causes an HTTP cookie to be removed from the browser
-
- The response will include an HTTP header that will remove the cookie
- corresponding to "name" on the client, if one exists. This is
- accomplished by sending a new cookie with an expiration date
- that has already passed. Note that some clients require a path
- to be specified - this path must exactly match the path given
- when creating the cookie. The path can be specified as a keyword
- argument.
- '''
dict={'max_age':0, 'expires':'Wed, 31-Dec-97 23:59:59 GMT'}
for k, v in kw.items():
dict[k]=v
@@ -232,14 +198,6 @@
self.setCookie(name, 'deleted', **dict)
def setCookie(self, name, value, **kw):
- '''
- Sets an HTTP cookie on the browser
-
- The response will include an HTTP header that sets a cookie on
- cookie-enabled browsers with a key "name" and value
- "value". This overwrites any previously set value for the
- cookie in the Response object.
- '''
cookies=self.cookies
if cookies.has_key(name):
cookie=cookies[name]
@@ -249,12 +207,6 @@
cookie['value']=value
def appendToHeader(self, name, value, delimiter=","):
- '''
- Appends a value to a header
-
- Sets an HTTP return header "name" with value "value",
- appending it following a comma if there was a previous value
- set for the header. '''
headers=self.headers
if headers.has_key(name):
h=self.header[name]
@@ -296,6 +248,16 @@
return cookie_list
+ def getHeader(self, name):
+ '''
+ Gets a header value
+
+ Returns the value associated with a HTTP return header, or
+ "None" if no such header has been set in the response
+ yet.
+ '''
+ return self.headers.get(name, None)
+
def getHeaders(self):
"""
@@ -306,7 +268,7 @@
if (not self._streaming and not headers.has_key('content-length')
and not headers.has_key('transfer-encoding')):
- self.updateContentLength()
+ self.__updateContentLength()
res["X-Powered-By"] = "Zope (www.zope.org), Python (www.python.org)"
=== Zope3/lib/python/Zope/Publisher/HTTP/IHTTPRequest.py 1.1.2.2 => 1.1.2.2.4.1 ===
"""
-
from Interface import Interface
+
+# XXX Should we extend IRequest?
+
class IHTTPRequest(Interface):
def __getitem__(key):
@@ -54,3 +56,32 @@
Data that may be set by an application object.
"""
+
+ def getCookies():
+ """Return the cookie data
+
+ Data are returned as a mapping object, mapping cookie name to value.
+ """
+
+ return IMapping(str, str)
+
+ def getHeader(name, default=None):
+ """Get a header value
+
+ Return the named HTTP header, or an optional default
+ argument or None if the header is not found. Note that
+ both original and CGI-ified header names are recognized,
+ e.g. 'Content-Type', 'CONTENT_TYPE' and 'HTTP_CONTENT_TYPE'
+ should all return the Content-Type header, if available.
+ """
+
+ def setPathSuffix(steps):
+ """Add additional trversal steps to be taken after all other traversal
+
+ This is used to handle HTTP request methods (except for GET
+ and POST in the case of browser requests) and XML-RPC methods.
+ """
+
+
+
+