Emit the HTTP headers

@param ResponseInterface $response
428919
public function emitHeaders(ResponseInterface $response)
    {
        foreach ($response->getHeaders() as $name => $values) {
            foreach (array_values((array)$values) as $i => $value) {
                $this->header("$name: $value", $i === 0);
            }
        }
    }
647099
private function withHTML(ResponseInterface $response, array $context)
    {
        $rendered = $this->template->render($context);

        return $this
            ->withNewBody($response, $rendered)
            ->withHeader('Content-Type', 'text/html');
    }
1266505
protected function addResponseHeaders(RequestInterface $request, Response $response)
    {
        $params = $request->getParams();
        $response->setHeader('Via', sprintf('%s GuzzleCache/%s', $request->getProtocolVersion(), Version::VERSION));

        $lookup = ($params['cache.lookup'] === true ? 'HIT' : 'MISS') . ' from GuzzleCache';
        if ($header = $response->getHeader('X-Cache-Lookup')) {
            // Don't add duplicates
            $values = $header->toArray();
            $values[] = $lookup;
            $response->setHeader('X-Cache-Lookup', array_unique($values));
        } else {
            $response->setHeader('X-Cache-Lookup', $lookup);
        }

        if ($params['cache.hit'] === true) {
            $xcache = 'HIT from GuzzleCache';
        } elseif ($params['cache.hit'] == 'error') {
            $xcache = 'HIT_ERROR from GuzzleCache';
        } else {
            $xcache = 'MISS from GuzzleCache';
        }

        if ($header = $response->getHeader('X-Cache')) {
            // Don't add duplicates
            $values = $header->toArray();
            $values[] = $xcache;
            $response->setHeader('X-Cache', array_unique($values));
        } else {
            $response->setHeader('X-Cache', $xcache);
        }

        if ($response->isFresh() === false) {
            $response->addHeader('Warning', sprintf('110 GuzzleCache/%s "Response is stale"', Version::VERSION));
            if ($params['cache.hit'] === 'error') {
                $response->addHeader('Warning', sprintf('111 GuzzleCache/%s "Revalidation failed"', Version::VERSION));
            }
        }
    }
121692
public function sendResponseBody(ResponseInterface $response):void
    {
        if (($body = $response->getBody()->detach()) === null) {
            $body = $response->getBody()->__toString();
        }
        $this->sendBody($body);
    }
791872
private function emitHeaders(ResponseInterface $response): void
    {
        /*
        if (headers_sent($file, $line)) {
            throw new \RuntimeException(sprintf('Failed to send headers, because headers have already been sent by "%s" at line %d.', $file, $line));
        }*/
        // headers have already been sent by the developer
        if (headers_sent()) {
            return;
        }

        $statusCode = $response->getStatusCode();

        // TODO : regarder ici pour voir comment on emet les cookies !!!!! https://github.com/zendframework/zend-diactoros/blob/master/src/Response/SapiEmitterTrait.php#L78
        // TODO : regarder ici, car un header peut avoir un tableau de valeurs, dans le cas ou on a mergé 2 headers identiques !!!!   https://github.com/slimphp/Slim/blob/3.x/Slim/App.php#L393
        // headers
        foreach ($response->getHeaders() as $name => $values) {
            $first = stripos($name, 'Set-Cookie') === 0 ? false : true;
            foreach ($values as $value) {
                header(sprintf('%s: %s', $name, $value), $first, $statusCode);
                $first = false;
            }
        }

        // TODO : gérer le cas ou il n'y a pas de ReasonPhrase et mettre une chaine vide : https://github.com/zendframework/zend-diactoros/blob/master/src/Response/SapiEmitterTrait.php#L55
        // Set proper protocol, status code (and reason phrase) header
        /*
        if ($response->getReasonPhrase()) {
            header(sprintf(
                'HTTP/%s %d %s',
                $response->getProtocolVersion(),
                $response->getStatusCode(),
                $response->getReasonPhrase()
            ));
        } else {
            header(sprintf(
                'HTTP/%s %d',
                $response->getProtocolVersion(),
                $response->getStatusCode()
            ));
        }*/

        // It is important to mention that this method should be called after the headers are sent, in order to prevent PHP from changing the status code of the emitted response.
        header(sprintf('HTTP/%s %d %s', $response->getProtocolVersion(), $statusCode, $response->getReasonPhrase()), true, $statusCode);

        // cookies
//TODO : utiliser les cookies comme des "headers" classiques ('Set-Cookies:xxxxxxx')
//https://github.com/paragonie/PHP-Cookie/blob/master/src/Cookie.php#L358

//        foreach ($response->getCookies() as $cookie) {
//          setrawcookie($cookie['name'], $cookie['value'], $cookie['expire'], $cookie['path'], $cookie['domain'], $cookie['secure'], $cookie['httponly']);
//        }

//        flush();
//      }

      // cookies
      /*
      foreach ($this->headers->getCookies() as $cookie) {
          if ($cookie->isRaw()) {
              setrawcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
          } else {
              setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
          }
      }*/
    }
204770
public function intercept(ResponseInterface $response)
    {
        $this->stopPropagation();
        $this->getTransaction()->setResponse($response);
        $this->exception->setThrowImmediately(false);
        RequestEvents::emitComplete($this->getTransaction());
    }
1050639
protected static function emitBody(ResponseInterface $response, $maxBufferLength)
    {
        $body = $response->getBody();

        if ($body->isSeekable()) {
            $body->rewind();
        }

        if (!$body->isReadable()) {
            echo $body;

            return;
        }

        while (!$body->eof()) {
            echo $body->read($maxBufferLength);
        }
    }
646456
private function emitBody(ResponseInterface $response): void
    {
        $body = $response->getBody();

        if ($body->isSeekable()) {
            $body->rewind();
        }

        while (!$body->eof() && connection_status() === CONNECTION_NORMAL) {
            echo $body->read(self::CHUNK_SIZE);
        }
    }
727032
protected function emitStatusLine(ResponseInterface $response)
    {
        $reasonPhrase = $response->getReasonPhrase();
        header(sprintf(
            'HTTP/%s %d%s',
            $response->getProtocolVersion(),
            $response->getStatusCode(),
            ($reasonPhrase ? ' ' . $reasonPhrase : '')
        ));

        return $this;
    }
1078403
protected function processResponseHeaders(StreamInterface $stream)
    {
        // Set the size on the stream if it was returned in the response
        foreach ($this->lastResponseHeaders as $header) {
            if ((stripos($header, 'Content-Length:')) === 0) {
                $stream->setSize(trim(substr($header, 15)));
            }
        }
    }
479369
protected function isRedirect(ResponseInterface $response)
    {
        $statusCode = $response->getStatusCode();

        return $statusCode > 300 && $statusCode < 400 && $response->hasHeader('Location');
    }
1120780
private function injectHeaders(ResponseInterface $response, array $headers = []): ResponseInterface
    {
        foreach ($headers as $name => $value) {
            $response = $response->withHeader($name, $value);
        }

        return $response;
    }
968477
public function serveResponse(ResponseInterface $response)
    {
        // add increment
        $this->servedResponseCount++;
        $allowServeEmpty = $this->getConfiguration('serveEmptyResponse') === true;
        $setContentLength = $this->getConfiguration('setContentLength') === true;
        // Send response
        if (!headers_sent()) {
            // Headers
            foreach ($response->getHeaders() as $name => $values) {
                if (!$setContentLength && strtolower($name) === 'content-length') {
                    continue;
                }

                foreach ($values as $value) {
                    header(sprintf('%s: %s', $name, $value), false);
                }
            }

            // Re Set Status Header
            header(sprintf(
                'HTTP/%s %s %s',
                $response->getProtocolVersion(),
                $response->getStatusCode(),
                $response->getReasonPhrase()
            ), true, $response->getStatusCode());
        }

        // Serve Response
        if ($allowServeEmpty || ! $this->isEmptyResponseCode($response->getStatusCode())) {
            $body = $response->getBody();
            if ($body->isSeekable()) {
                $body->rewind();
            }

            $chunkSize      = $this->getNormalizeResponseChunkSize();
            $contentLength  = $setContentLength
                ? $response->getHeaderLine('Content-Length')
                : null;

            if (!$contentLength) {
                $contentLength = $body->getSize();
                // set content length
                if ($setContentLength && !headers_sent()) {
                    header(sprintf('Content-Length: %d', $contentLength));
                }
            }

            // if use buffer create buffer
            $this->addCreateBuffer();
            if ($contentLength) {
                $amountToRead = $contentLength;
                while ($amountToRead > 0 && !$body->eof()) {
                    $data = $body->read(min($chunkSize, $amountToRead));
                    echo $data;
                    $amountToRead -= strlen($data);
                    if (connection_status() != CONNECTION_NORMAL) {
                        break;
                    }
                }
            } else {
                while (!$body->eof()) {
                    echo $body->read($chunkSize);
                    if (connection_status() != CONNECTION_NORMAL) {
                        break;
                    }
                }
            }
        }
    }
313299
public function sendHeaders(ResponseInterface $response)
    {
        foreach ($response->getHeaders() as $header => $values) {
            $first = true;
            $header = HeaderHelper::normalizeHeaderName($header);

            foreach ($values as $value) {
                $this->header(sprintf('%s: %s', $header, $value), $first);

                $first = false;
            }
        }

        return $this;
    }
154943
private function emit(ResponseInterface $response){
        $params = [
            "start"     => null,
            "finish"    => null,
            "error"     => null,
        ];

        try{
            $params["start"]    = microtime(true);

            $this->emitter->emit($response);
        }catch(\Throwable $e){
            $params["error"]    = $e;
            $this->error        = $e;
        }finally{
            $params["finish"]   = microtime(true);
        }

        $this->event(new Event("response.emit.after", $params));
    }
130303
protected function createLaravelResponse(ResponseInterface $response)
    {
        return new Response(
            (string) $response->getBody(),
            $response->getStatusCode(),
            $response->getHeaders()
        );
    }
1365150
public function send(ResponseInterface $response)
	{	
	    
		// Send response
		if (!headers_sent()) {
			// Status
			header(sprintf(
					'HTTP/%s %s %s',
					$response->getProtocolVersion(),
					$response->getStatusCode(),
					$response->getReasonPhrase()
					));
			
			// Headers
			foreach ($response->getHeaders() as $name => $values) {
				foreach ($values as $value) {
					header(sprintf('%s: %s', $name, $value), false);
				}
			}
		}
		
		// Body
		if (!$this->isEmptyResponse($response)) {
			$body = $response->getBody();
			if ($body->isSeekable()) {
				$body->rewind();
			}
			$chunkSize = Config::getCommon('response.chunkSize', 4096);
			$contentLength  = $response->getHeaderLine('Content-Length');
			if (!$contentLength) {
				$contentLength = $body->getSize();
			}
			
			if (isset($contentLength)) {
				$amountToRead = $contentLength;
				while ($amountToRead > 0 && !$body->eof()) {
					$data = $body->read(min($chunkSize, $amountToRead));
					echo $data;
					
					$amountToRead -= strlen($data);
					
					if (connection_status() != CONNECTION_NORMAL) {
						break;
					}
				}
			} else {
				while (!$body->eof()) {
					echo $body->read($chunkSize);
					if (connection_status() != CONNECTION_NORMAL) {
						break;
					}
				}
			}
		}
	}