class HTTPHandler(basic.LineReceiver): __length = 0 __header = '' __first_line = 1 def _parse_command(self, command): parts = string.split(command) if len(parts)<3: parts.append('HTTP/0.9') # isn't backwards compat great! if len(parts) != 3: self.sendError(405, 'Bad command') raise ValueError(str(parts)) return parts def sendStatus(self, code, resp=''): self.transport.write('HTTP/1.0 %s %s\r\n' % (code, resp)) def sendHeader(self, name, value): self.transport.write('%s: %s\r\n' % (name, value)) def endHeaders(self): self.transport.write('\r\n') def sendError(self, code, resp=''): self.sendStatus(code, resp) self.endHeaders() def lineReceived(self, line): if self.__first_line: self.__first_line = 0 command, request, version = self._parse_command(line) self.handleCommand(command, request, version) if version == 'HTTP/0.9': self.handleEndHeaders() self.callHandleEndContent() elif line == '': if self.__header: self.callHandleHeader(self.__header) self.__header = '' self.handleEndHeaders() if self.__length == 0: self.callHandleEndContent() else: self.setRawMode() elif line[0] in ' \t': self.__header = self.__header+'\n'+line else: if self.__header: self.callHandleHeader(self.__header) self.__header = line def callHandleHeader(self, line): """Do pre-processing (for content-length) and then call handleHeader for one header line.""" assert line if string.find(string.lower(line), 'content-length: ') == 0: self.__length = int(string.strip(string.split(line, ':', 1)[1])) self.handleHeader(line) def callHandleEndContent(self): self.__first_line = 1
be paranoid! and rawDataReceived will leave this != 0 in some cases! self.__length = 0 self.__header = '' <<< self.handleEndContent()
the logic here is pretty fucked, if you ask me what if we send more bytes than specified in c-length? note that a post has exactly the speciality of a c-l != 0 a get has not c-l or a cl of 0! is the setlinemode for keep-alive? if not, some "print 'extraneous bytes in request'" would be better
def rawDataReceived(self, data): if len(data) < self.__length: self.handleContentChunk(data) self.__length = self.__length - len(data) else: self.handleContentChunk(data[:self.__length]) self.callHandleEndContent()
!!! # only pass NONEMPTY strings on if len(data) > self.__length: self.setLineMode(data[self.__length:])