[Twisted-Python] First Port to twisted.protocols

I'll check in the protocols stuff later today. In the mean time, for you early adopters, http://moshez.org/protocls.tgz has the latest and snazziest. And....as a special surprise, I've ported twisted.web over to stop knowing so much HTTP. HTTP knowledge used to be smeared all over Request and HTTPHandler, and now neither of them knows much HTTP.

On 16 Apr 2001 18:32:44 -0000, Moshe Zadka moshez@zadka.site.co.il wrote:
I'll check in the protocols stuff later today.
As promised, I've check it in.
And....as a special surprise, I've ported twisted.web over to stop knowing so much HTTP. HTTP knowledge used to be smeared all over Request and HTTPHandler, and now neither of them knows much HTTP.
I'm working on integrating and testing my web.py port. I'll think of Resource testability later.

On Tue, 17 Apr 2001 18:53:57 +0300, Moshe Zadka moshez@zadka.site.co.il wrote:
I'll check in the protocols stuff later today.
As promised, I've check it in.
And now I've fixed a little bug in twisted.protocols.http The HTTP server code now works fine.
And....as a special surprise, I've ported twisted.web over to stop knowing so much HTTP. HTTP knowledge used to be smeared all over Request and HTTPHandler, and now neither of them knows much HTTP.
I'm working on integrating and testing my web.py port.
Here's a first rough patch to do that:
Please do *not* apply it -- I've got some ideas about improving the HTTP handlers to make it even smoother.
Stay tuned!
Index: twisted/web.py =================================================================== RCS file: /cvs/TwistedPython/twisted/web.py,v retrieving revision 1.81 diff -c -r1.81 web.py *** twisted/web.py 2001/04/12 17:32:14 1.81 --- twisted/web.py 2001/04/17 18:59:16 *************** *** 29,34 **** --- 29,36 ---- from twisted import reflect from twisted import gloop from twisted import copyright + import twisted.protocols.http + from twisted import protocols
# Useful constants
*************** *** 238,280 **** else: return name
! def __init__(self, blob): # parse the blob # ... split = string.split find = string.find lower = string.lower
! blobs = split(blob, '\r\n') ! reqstring = blobs.pop(0) received = self.received = {} args = self.args = {} self.stack = [] self.headers = {}
! reqfields = split(reqstring, ' ') ! ! assert 2 <= len(reqfields) <=3, "Invalid request format." ! ! self.method, self.uri = reqfields[0], reqfields[1] ! ! if len(reqfields) == 2: ! # we are dealing with HTTP/0.9 ! self.clientproto = "HTTP/0.9" ! else: ! self.clientproto = reqfields[2] ! ! ###self.uri = urllib.unquote(self.uri) x = split(self.uri,'?')
if len(x) == 1: ! self.path = urllib.unquote(self.uri) else: if len(x) != 2: print "May ignore parts of this invalid URI:",repr(self.uri) ! self.path, argstring = urllib.unquote(x[0]), x[1] for kvp in split(argstring,'&'): ! keyval = map(urllib.unquote, split(kvp, '=')) if len(keyval)==2: key, value = keyval if args.has_key(key): --- 240,270 ---- else: return name
! def __init__(self, method, uri, version, blob): # parse the blob # ... split = string.split find = string.find lower = string.lower
! blobf = StringIO.StringIO(blob) received = self.received = {} args = self.args = {} self.stack = [] self.headers = {}
! self.method, self.uri, self.clientproto = method, uri, version ! self.uri = urllib.unquote(self.uri) x = split(self.uri,'?')
if len(x) == 1: ! self.path = self.uri else: if len(x) != 2: print "May ignore parts of this invalid URI:",repr(self.uri) ! self.path, argstring = x[0], x[1] for kvp in split(argstring,'&'): ! keyval = split(kvp, '=') if len(keyval)==2: key, value = keyval if args.has_key(key): *************** *** 282,304 **** else: args[key] = [value]
! for header in blobs: x = find(header,":") if x != -1: received[lower(header[:x])] = header[x+2:] else: print 'Invalid HTTP/1.1 protocol message?' print header ! try: ! self.requiredContent = int(received['content-length']) ! except: ! self.requiredContent = 0
def __repr__(self): return '<%s %s %s>'% (self.method, self.uri, self.clientproto)
- - _host = socket.gethostbyaddr(socket.gethostname())[0]
def process(self, server): --- 272,292 ---- else: args[key] = [value]
! while 1: ! header = blobf.readline() ! if header == '\n': ! break x = find(header,":") if x != -1: received[lower(header[:x])] = header[x+2:] else: print 'Invalid HTTP/1.1 protocol message?' print header ! self.content = blobf.read()
def __repr__(self): return '<%s %s %s>'% (self.method, self.uri, self.clientproto)
_host = socket.gethostbyaddr(socket.gethostname())[0]
def process(self, server): *************** *** 370,387 **** Write some data as a result of an HTTP request. The first time this is called, it writes out response data. """ ! if self.startedWriting: ! self.handler.write(data) ! else: self.startedWriting = 1 if self.clientproto != "HTTP/0.9": message = HTTP.responses.get(self.code, "Unknown Status") ! self.write("%s %s %s\r\n" % (HTTP.protocol_version, ! str(self.code), message) ) ! for header in self.headers.items(): ! self.write("%s: %s\r\n" % header) ! self.write('\r\n') ! self.write(data)
def finish(self): self.handler.stopConsuming() --- 358,372 ---- Write some data as a result of an HTTP request. The first time this is called, it writes out response data. """ ! if not self.startedWriting: self.startedWriting = 1 if self.clientproto != "HTTP/0.9": message = HTTP.responses.get(self.code, "Unknown Status") ! self.handler.sendStatus(self.code, message) ! for header, value in self.headers.items(): ! self.handler.sendHeader(header, value) ! self.handler.endHeaders ! self.handler.write(data)
def finish(self): self.handler.stopConsuming() *************** *** 1386,1441 **** return page
! class HTTPHandler(net.GenericHandler): ! contentLength = 0 ! request = None ! recvd = ""
def connectionLost(self, reason): self.request = None net.GenericHandler.connectionLost(self, reason)
! def _process(self, request): ! """ (private) """ ! request.handler = self ! request.process(self.server) ! ! def handleData(self, data): ! recvd = self.recvd = self.recvd + data ! if not self.request: ! # HTTP/0.9 special handling. ! firstend = string.find(recvd, '\r\n') ! reqend = -1 ! if firstend != -1: ! first = recvd[:firstend] ! spaces = string.count(first, ' ') ! if spaces == 1: ! # we are HTTP/0.9 ! reqend = firstend ! ! if reqend < 0: ! # we didn't encounter 0.9, so proceed normally. ! reqend = string.find(recvd, '\r\n\r\n') ! ! if reqend != -1: ! reqdata = recvd[:reqend] ! self.recvd = recvd = recvd[reqend+4:] ! ! request = Request(reqdata) ! request.client = self.client ! request.handler = self ! cl = request.requiredContent ! if cl: ! self.contentLength = cl ! self.request = request ! else: ! self._process(request) ! return
- if self.contentLength: - if len(self.recvd) >= self.contentLength: - self.request.content = recvd[:self.contentLength] - self._process(self.request)
class Server(net.GenericServer, authenticator.SessionManager, config.Configurable): handler = HTTPHandler --- 1371,1387 ---- return page
! class HTTPHandler(net.GenericHandler, protocols.http.HTTPHandler):
def connectionLost(self, reason): self.request = None net.GenericHandler.connectionLost(self, reason)
! def handleRequest(self, command, selector, version, request): ! self.request = Request(command, selector, version, request) ! self.request.handler = self ! self.request.process(self.server)
class Server(net.GenericServer, authenticator.SessionManager, config.Configurable): handler = HTTPHandler ************************************************************

On Tue, 17 Apr 2001 21:58:38 +0300, Moshe Zadka moshez@zadka.site.co.il wrote:
Here's a first rough patch to do that:
Please do *not* apply it -- I've got some ideas about improving the HTTP handlers to make it even smoother.
Stay tuned!
Thank you for your patience. A new patch attached, which uses the most work-saving features of HTTPHandler to make the actual code which handles HTTP short and highlevel.
participants (1)
-
Moshe Zadka