示例#1
0
 /**
  * Assert that the given response indicates a succeeded WebSocket handshake.
  */
 protected function assertHandshakeSucceeded(HttpResponse $response, string $nonce, array $protocols)
 {
     if ($response->getStatusCode() !== Http::SWITCHING_PROTOCOLS) {
         throw new \RuntimeException(\sprintf('Unexpected HTTP response code: %s', $response->getStatusCode()));
     }
     if (!\in_array('upgrade', $response->getHeaderTokenValues('Connection'), true)) {
         throw new \RuntimeException(\sprintf('HTTP connection header did not contain upgrade: "%s"', $response->getHeaderLine('Connection')));
     }
     if ('websocket' !== \strtolower($response->getHeaderLine('Upgrade'))) {
         throw new \RuntimeException(\sprintf('HTTP upgrade header did not specify websocket: "%s"', $response->getHeaderLine('Upgrade')));
     }
     if (\base64_encode(\sha1($nonce . self::GUID, true)) !== $response->getHeaderLine('Sec-WebSocket-Accept')) {
         throw new \RuntimeException('Failed to verify Sec-WebSocket-Accept HTTP header');
     }
     if ($response->hasHeader('Sec-WebSocket-Protocol')) {
         if (!\in_array($response->getHeaderLine('Sec-WebSocket-Protocol'), $protocols, true)) {
             throw new \OutOfRangeException(\sprintf('Unsupported protocol: "%s"', $response->getHeaderLine('Sec-WebSocket-Protocol')));
         }
     }
 }
示例#2
0
 /**
  * Serialize HTTP response headers into a string.
  */
 protected function serializeHeaders(HttpResponse $response, bool &$close, int $size = null, bool $nobody = false, bool $deferred = false) : string
 {
     $reason = \trim($response->getReasonPhrase());
     if ($reason === '') {
         $reason = \trim(Http::getReason($response->getStatusCode()));
     }
     if (!$response->hasHeader('Connection')) {
         $response = $response->withHeader('Connection', $close ? 'close' : 'keep-alive');
     }
     if (!$close) {
         $response = $response->withHeader('Keep-Alive', '30');
     }
     $buffer = \sprintf("HTTP/%s %u%s\r\n", $response->getProtocolVersion(), $response->getStatusCode(), \rtrim(' ' . $reason));
     if (!$nobody) {
         if ($deferred) {
             $close = true;
         } else {
             if ((double) $response->getProtocolVersion() > 1) {
                 if ($size === null) {
                     $buffer .= "Transfer-Encoding: chunked\r\n";
                 } else {
                     $buffer .= "Content-Length: {$size}\r\n";
                 }
             } elseif ($size !== null) {
                 $buffer .= "Content-Length: {$size}\r\n";
             } else {
                 $close = true;
             }
         }
     }
     foreach ($response->getHeaders() as $name => $header) {
         $name = Http::normalizeHeaderName($name);
         foreach ($header as $value) {
             $buffer .= $name . ': ' . $value . "\r\n";
         }
     }
     return $buffer;
 }
示例#3
0
 protected function shouldConnectionBeClosed(HttpResponse $response) : bool
 {
     if (!$this->keepAlive) {
         return true;
     }
     if ($response->getProtocolVersion() === '1.0' && !\in_array('keep-alive', $response->getHeaderTokenValues('Connection'), true)) {
         return true;
     }
     if (!$response->hasHeader('Content-Length') && 'chunked' !== \strtolower($response->getHeaderLine('Transfer-Encoding'))) {
         return true;
     }
     return false;
 }
示例#4
0
 /**
  * Check if the given response payload should be compressed.
  * 
  * @param HttpRequest $request
  * @param HttpResponse $response
  * @return bool
  */
 protected function isCompressable(HttpRequest $request, HttpResponse $response) : bool
 {
     if ($request->getMethod() === Http::HEAD) {
         return false;
     }
     if ($response->getBody() instanceof DeferredBody || Http::isResponseWithoutBody($response->getStatusCode())) {
         return false;
     }
     if ($response->hasHeader('Content-Encoding') || !$response->hasHeader('Content-Type')) {
         return false;
     }
     try {
         $media = $response->getContentType()->getMediaType();
     } catch (InvalidMediaTypeException $e) {
         return false;
     }
     if (isset($this->types[(string) $media])) {
         return true;
     }
     foreach ($media->getSubTypes() as $sub) {
         if (isset($this->subTypes[$sub])) {
             return true;
         }
     }
     return false;
 }