def http_client_continue (self, request): # push one string and maybe a producer in the output fifo ... http_request = '%s %s HTTP/%s\r\n' % ( request.http_method, request.http_url, self.http_version ) if request.producer_body == None: # GET, HEAD and DELETE lines = mime_headers.lines (request.producer_headers) lines.insert (0, http_request) self.output_fifo.append (''.join (lines)) else: # POST and PUT if self.http_version == '1.1': request.producer_body = \ http_reactor.Chunk_producer ( request.producer_body ) request.producer_headers[ 'transfer-encoding' ] = 'chunked' lines = mime_headers.lines (request.producer_headers) lines.insert (0, http_request) self.output_fifo.append (''.join (lines)) self.output_fifo.append (request.producer_body) # append the reactor to the queue of responses expected ... self.pipeline_responses.append (request) self.pipelined_requests += 1
def found_terminator(self): if self.smtp_response[3] == '-': # rest of a multi-line response, drop it! self.smtp_response = '' return response = self.smtp_response[:3] self.smtp_response = '' if not response in SMTP_RESPONSE_CONTINUE: if response in SMTP_RESPONSE_CLOSE: self.handle_close() return True elif response in SMTP_RESPONSE_ABORT: self.pipeline_responses.popleft() return if response == '220': self.output_fifo.append('HELO %s\r\n' % HOSTNAME) return if not self.pipeline_responses: # no response expected. if there is a pending reactor, # pipelined pop it from the requests queue, send MAIL # FROM command and push the reactor on the responses # queue. otherwise keep the connection alive or QUIT. # if self.pipeline_requests: reactor = self.pipeline_requests.popleft() self.output_fifo.append('MAIL FROM: <%s>\r\n' '' % reactor.smtp_mail_from) reactor.smtp_recipient = 0 self.pipeline_responses.append(reactor) elif not self.pipeline_keep_alive: self.output_fifo.append('QUIT\r\n') self.output_fifo.append(None) return # response expected ... reactor = self.pipeline_responses[0] if reactor.smtp_rcpt_to: # RCPT TO command for next recipient self.output_fifo.append('RCPT TO: <%s>\r\n' '' % reactor.smtp_rcpt_to.pop(0)) elif reactor.smtp_responses[-1] != '354': # send DATA command or mail input if response == '354': push = self.output_fifo.append # start mail input, end with <CRLF>.<CRLF> push(''.join(mime_headers.lines(reactor.producer_headers))) push(mime_reactor.Escaping_producer(reactor.producer_body)) push('\r\n.\r\n') self.handle_write() else: self.output_fifo.append('DATA\r\n') else: # reactor completed, self.pipeline_responses.popleft() self.output_fifo.append('RSET\r\n') reactor.smtp_responses.append(response)
def multipart_producer(parts, headers=None, glob=1 << 14): boundary = "%x" % id(self) if headers == None: head = "MIME-Version: 1.0\r\n" "Content-Type: multipart/mixed;" ' boundary="%s"\r\n\r\n' % boundary else: headers["content-type"] = 'multipart/mixed; boundary="%s"' % boundary head = "".join(mime_headers.lines(headers)) return producer.Composite(head, multipart_generator(parts, "\r\n--%s" % boundary), glob)
def _response (reactor, response, head): return _RESPONSE % ( reactor.request[2], response, RESPONSES[response], head, '\r\n'.join (mime_headers.lines ( reactor.producer_headers )), ' '.join (reactor.request), '\r\n'.join (reactor.collector_lines) )
def __call__ (self, response, headers=(), body=None): self.response = response head = ( '%s %d %s\r\n' 'Date: %s\r\n' 'Server: Allegra\r\n' % ( self.request[2], response, RESPONSES[response], self.time or strftime ( '%a, %d %b %Y %H:%M:%S GMT', gmtime (time ()) ) ) # supports async HTTP formated time ) # Complete the HTTP response producer self.producer_headers.update (headers) if body == None and ( self.request[0] in ('GET', 'POST') # and # response != 204 # No content ): # Supply a response entity if one is required for the # request's method and that none has been assigned. self.producer_body = producer.Simple ( _response (self, response, head) ) else: self.producer_body = body # Use the given body. if self.request[2] == 'HTTP/1.1': # Allways use Chunked Transfer-Encoding for HTTP/1.1! if self.producer_body != None: self.producer_headers[ 'Transfer-Encoding' ] = 'chunked' self.producer_body = \ http_reactor.Chunk_producer ( self.producer_body ) else: # Do not keep-alive without chunk-encoding! self.producer_headers['Connection'] = 'close' # Build the response head with the reactor's MIME headers, # the channel's HTTP version the reactor's HTTP response. self.producer_lines = mime_headers.lines ( self.producer_headers ) # TODO: Revise the MIME_producer API as generator ? self.producer_lines.insert (0, head) if self.producer_headers.get ('Connection') == 'close': # close socket when done ... self.dispatcher.output_fifo.append (None) return True # ... stall input now! return False # let the http_server.Dispatcher continue ...
def http_client_continue(self, request): # push one string and maybe a producer in the output fifo ... http_request = '%s %s HTTP/%s\r\n' % ( request.http_method, request.http_url, self.http_version) if request.producer_body == None: # GET, HEAD and DELETE lines = mime_headers.lines(request.producer_headers) lines.insert(0, http_request) self.output_fifo.append(''.join(lines)) else: # POST and PUT if self.http_version == '1.1': request.producer_body = \ http_reactor.Chunk_producer ( request.producer_body ) request.producer_headers['transfer-encoding'] = 'chunked' lines = mime_headers.lines(request.producer_headers) lines.insert(0, http_request) self.output_fifo.append(''.join(lines)) self.output_fifo.append(request.producer_body) # append the reactor to the queue of responses expected ... self.pipeline_responses.append(request) self.pipelined_requests += 1
def multipart_producer (parts, headers=None, glob=1<<14): boundary = '%x' % id (self) if headers == None: head = ( 'MIME-Version: 1.0\r\n' 'Content-Type: multipart/mixed;' ' boundary="%s"\r\n\r\n' % boundary ) else: headers['content-type'] = ( 'multipart/mixed; boundary="%s"' % boundary ) head = ''.join (mime_headers.lines (headers)) return producer.Composite ( head, multipart_generator ( parts, '\r\n--%s' % boundary ), glob )
def __call__(self, response, headers=(), body=None): self.response = response head = ( '%s %d %s\r\n' 'Date: %s\r\n' 'Server: Allegra\r\n' % (self.request[2], response, RESPONSES[response], self.time or strftime('%a, %d %b %Y %H:%M:%S GMT', gmtime(time())) ) # supports async HTTP formated time ) # Complete the HTTP response producer self.producer_headers.update(headers) if body == None and (self.request[0] in ('GET', 'POST') # and # response != 204 # No content ): # Supply a response entity if one is required for the # request's method and that none has been assigned. self.producer_body = producer.Simple( _response(self, response, head)) else: self.producer_body = body # Use the given body. if self.request[2] == 'HTTP/1.1': # Allways use Chunked Transfer-Encoding for HTTP/1.1! if self.producer_body != None: self.producer_headers['Transfer-Encoding'] = 'chunked' self.producer_body = \ http_reactor.Chunk_producer ( self.producer_body ) else: # Do not keep-alive without chunk-encoding! self.producer_headers['Connection'] = 'close' # Build the response head with the reactor's MIME headers, # the channel's HTTP version the reactor's HTTP response. self.producer_lines = mime_headers.lines( self.producer_headers ) # TODO: Revise the MIME_producer API as generator ? self.producer_lines.insert(0, head) if self.producer_headers.get('Connection') == 'close': # close socket when done ... self.dispatcher.output_fifo.append(None) return True # ... stall input now! return False # let the http_server.Dispatcher continue ...
def found_terminator (self): if self.smtp_response[3] == '-': # rest of a multi-line response, drop it! self.smtp_response = '' return response = self.smtp_response[:3] self.smtp_response = '' if not response in SMTP_RESPONSE_CONTINUE: if response in SMTP_RESPONSE_CLOSE: self.handle_close () return True elif response in SMTP_RESPONSE_ABORT: self.pipeline_responses.popleft () return if response == '220': self.output_fifo.append ('HELO %s\r\n' % HOSTNAME) return if not self.pipeline_responses: # no response expected. if there is a pending reactor, # pipelined pop it from the requests queue, send MAIL # FROM command and push the reactor on the responses # queue. otherwise keep the connection alive or QUIT. # if self.pipeline_requests: reactor = self.pipeline_requests.popleft () self.output_fifo.append ( 'MAIL FROM: <%s>\r\n' '' % reactor.smtp_mail_from ) reactor.smtp_recipient = 0 self.pipeline_responses.append (reactor) elif not self.pipeline_keep_alive: self.output_fifo.append ('QUIT\r\n') self.output_fifo.append (None) return # response expected ... reactor = self.pipeline_responses[0] if reactor.smtp_rcpt_to: # RCPT TO command for next recipient self.output_fifo.append ( 'RCPT TO: <%s>\r\n' '' % reactor.smtp_rcpt_to.pop (0) ) elif reactor.smtp_responses[-1] != '354': # send DATA command or mail input if response == '354': push = self.output_fifo.append # start mail input, end with <CRLF>.<CRLF> push (''.join (mime_headers.lines ( reactor.producer_headers ))) push (mime_reactor.Escaping_producer ( reactor.producer_body )) push ('\r\n.\r\n') self.handle_write () else: self.output_fifo.append ('DATA\r\n') else: # reactor completed, self.pipeline_responses.popleft () self.output_fifo.append ('RSET\r\n') reactor.smtp_responses.append (response)
def _response(reactor, response, head): return _RESPONSE % ( reactor.request[2], response, RESPONSES[response], head, '\r\n'.join(mime_headers.lines(reactor.producer_headers)), ' '.join(reactor.request), '\r\n'.join(reactor.collector_lines))