ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
DefaultResponseSenderStrategy.php
Go to the documentation of this file.
1<?php
2
20
21use Psr\Http\Message\ResponseInterface;
22
32{
36 private const METHOD_FPASSTHRU = 'fpassthru';
40 private const METHOD_READFILE = 'readfile';
42 private int $chunk_size;
43 private int $memory_limit;
44
45 public function __construct()
46 {
47 $this->memory_limit = $this->initMemoryLimit();
48 $this->chunk_size = $this->initChunkSize();
49 }
50
51 private function initMemoryLimit(): int
52 {
53 $ini_memory_limit = ini_get('memory_limit');
54 $memory_limit = null;
55 if (preg_match('/^(\d+)(.)$/', $ini_memory_limit, $matches)) {
56 $memory_limit = match ($matches[2] ?? null) {
57 'G' => (int) $matches[1] * 1024 * 1024 * 1024,
58 'M' => (int) $matches[1] * 1024 * 1024,
59 'K' => (int) $matches[1] * 1024,
60 default => (int) $matches[1],
61 };
62 }
63
64 return $memory_limit ?? 128 * 1024 * 1024;
65 }
66
67 private function initChunkSize(): int
68 {
69 return (int) round(max($this->memory_limit / 4, 8 * 1024));
70 }
71
79 public function sendResponse(ResponseInterface $response): void
80 {
81 //check if the request is already send
82 if (headers_sent()) {
83 throw new ResponseSendingException("Response was already sent.");
84 }
85
86 //set status code
87 http_response_code($response->getStatusCode());
88
89 //render all headers
90 foreach (array_keys($response->getHeaders()) as $key) {
91 // See Mantis #37385.
92 if (strtolower($key) === 'set-cookie') {
93 foreach ($response->getHeader($key) as $header) {
94 header("$key: " . $header, false);
95 }
96 } else {
97 header("$key: " . $response->getHeaderLine($key));
98 }
99 }
100
101 //rewind body stream
102 $stream = $response->getBody();
103 $stream->rewind();
104
105 // check body size
106 $body_size = $stream->getSize();
107 if ($body_size > $this->memory_limit) {
108 $this->method = self::METHOD_READFILE;
109 }
110
111 //detach psr-7 stream from resource
112 $resource = $stream->detach();
113
114 $sendStatus = false;
115
116 if (is_resource($resource)) {
117 set_time_limit(0);
118 try {
119 ob_end_clean(); // see https://mantis.ilias.de/view.php?id=32046
120 } catch (\Throwable) {
121 }
122 switch ($this->method) {
124 $sendStatus = fpassthru($resource);
125 break;
127 // more memory friendly than fpassthru
128 $sendStatus = true;
129 while (!feof($resource)) {
130 echo $return = fread($resource, $this->chunk_size);
131 $sendStatus = $sendStatus && $return !== false;
132
133 }
134 break;
135 }
136
137 //free up resources
138 fclose($resource);
139 }
140
141 //check if the body was successfully send to the client
142 if ($sendStatus === false) {
143 throw new ResponseSendingException("Could not send body content to client.");
144 }
145 }
146}
sendResponse(ResponseInterface $response)
Sends the rendered response to the client.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$response
Definition: xapitoken.php:93