def sendHandshake(self): """Perform a WebSocket opening handshake. The protocol will use the L{Handshake} parameters of the C{config} attribute of the factory. Once the handshake is complete, the C{deferred} attribute of the factory will be fired, either with C{None} (if the handshake was successful) or with a failure (if the handshake failed). """ # The HTTP handshake request to send request = self.handshake.buildRequest() # We set a failing parser finisher because we take the transport # control back as soon as all response headers are received, so we # shouldn't ever deliver any data to the parser beside the headers. def finisher(_): raise RuntimeError("Parser cannot notify response finish") # From this point on all data we received will be forwarded to the # HTTP parser, see dataReceived, self._parser = HTTPClientParser(request, finisher) self._parser._responseDeferred.addCallback(self._handshakeResponse) self._parser._responseDeferred.addErrback(self._handshakeFailure) self._parser.makeConnection(self.transport) request.writeTo(self.transport)
def request(self, request): if self._state != 'QUIESCENT': return fail(RequestNotSent()) self._state = 'TRANSMITTING' _requestDeferred = maybeDeferred(request.writeTo, self.transport) self._finishedRequest = Deferred() self._currentRequest = request self._transportProxy = TransportProxyProducer(self.transport) self._parser = HTTPClientParser(request, self._finishResponse) self._parser.makeConnection(self._transportProxy) self._responseDeferred = self._parser._responseDeferred def cbRequestWrotten(ignored): if self._state == 'TRANSMITTING': self._state = 'WAITING' self._responseDeferred.chainDeferred(self._finishedRequest) def ebRequestWriting(err): if self._state == 'TRANSMITTING': self._state = 'GENERATION_FAILED' self.transport.loseConnection() self._finishedRequest.errback( failure.Failure(RequestGenerationFailed([err]))) else: log.err( err, 'Error writing request, but not in valid state ' 'to finalize request: %s' % self._state) _requestDeferred.addCallbacks(cbRequestWrotten, ebRequestWriting) return self._finishedRequest
def request(self, request): """ Issue C{request} over C{self.transport} and return a L{Deferred} which will fire with a L{Response} instance or an error. @param request: The object defining the parameters of the request to issue. @type request: L{Request} @rtype: L{Deferred} @return: The deferred may errback with L{RequestGenerationFailed} if the request was not fully written to the transport due to a local error. It may errback with L{RequestTransmissionFailed} if it was not fully written to the transport due to a network error. It may errback with L{ResponseFailed} if the request was sent (not necessarily received) but some or all of the response was lost. It may errback with L{RequestNotSent} if it is not possible to send any more requests using this L{HTTP11ClientProtocol}. """ if self._state != 'QUIESCENT': return fail(RequestNotSent()) self._state = 'TRANSMITTING' _requestDeferred = maybeDeferred(request.writeTo, self.transport) self._finishedRequest = Deferred() # Keep track of the Request object in case we need to call stopWriting # on it. self._currentRequest = request self._transportProxy = TransportProxyProducer(self.transport) self._parser = HTTPClientParser(request, self._finishResponse) self._parser.makeConnection(self._transportProxy) self._responseDeferred = self._parser._responseDeferred def cbRequestWrotten(ignored): if self._state == 'TRANSMITTING': self._state = 'WAITING' self._responseDeferred.chainDeferred(self._finishedRequest) def ebRequestWriting(err): if self._state == 'TRANSMITTING': self._state = 'GENERATION_FAILED' self.transport.loseConnection() self._finishedRequest.errback( Failure(RequestGenerationFailed([err]))) else: log.err(err, "foo") _requestDeferred.addCallbacks(cbRequestWrotten, ebRequestWriting) return self._finishedRequest