ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
PHPResponseBuilder.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
23use Psr\Http\Message\ResponseInterface;
26use Psr\Http\Message\ServerRequestInterface;
27use Psr\Http\Message\RequestInterface;
29
34{
35 public function getName(): string
36 {
37 return 'php';
38 }
39
40 public function buildForStream(
41 ServerRequestInterface $request,
42 ResponseInterface $response,
43 FileStream $stream,
44 ): ResponseInterface {
45 $response = $this->buildHeaders($response, $stream);
46 $server_params = $request->getServerParams();
47
48 if ($request->getMethod() === 'HEAD') {
49 return $response->withStatus(200);
50 }
51
52 if (isset($server_params['HTTP_RANGE']) && $this->supportPartial()) {
53 return $this->deliverPartial($request, $response, $stream);
54 }
55 return $this->deliverFull($response, $stream);
56 }
57
58 protected function buildHeaders(
59 ResponseInterface $response,
60 FileStream $stream
61 ): ResponseInterface {
62 $uri = $stream->getMetadata('uri');
63 if ($this->supportPartial()) {
64 $response = $response->withHeader(ResponseHeader::ACCEPT_RANGES, 'bytes');
65 }
66
67 $response = $response->withHeader(ResponseHeader::CONTENT_LENGTH, $stream->getSize());
68 try {
69 $response = $response->withHeader(
71 date("D, j M Y H:i:s", filemtime($uri) ?: time()) . " GMT"
72 );
73 } catch (\Throwable) {
74 }
75
76 return $response->withHeader(ResponseHeader::ETAG, md5((string) $uri));
77 }
78
79 protected function deliverFull(
80 ResponseInterface $response,
81 FileStream $stream,
82 ): ResponseInterface {
83 $stream->rewind();
84 return $response->withBody($stream);
85 }
86
87 protected function deliverPartial(
88 RequestInterface|ServerRequestInterface $request,
89 ResponseInterface $response,
90 FileStream $stream,
91 ): ResponseInterface {
92 if (!$this->supportPartial()) {
93 return $response;
94 }
95 $request->getServerParams();
96
97 $start = 0;
98 $content_length = $stream->getSize();
99 $end = null;
100
101 $range_header = $request->getHeaderLine('Range');
102
103 if ($range_header && preg_match(
104 '%bytes=(\d+)-(\d+)?%i',
105 $range_header,
106 $match
107 )) {
108 $start = (int) $match[1];
109 if (isset($match[2])) {
110 $end = (int) $match[2];
111 }
112 $end ??= $content_length - 1;
113 }
114
115 $response = $response->withStatus(206);
116
117 $length = $end - $start + 1;
118 $fh = $stream->detach();
119
120 // set $buffer_size to 8MB
121 $buffer_size = 8048 * 1000; // 8,048,000 bytes
122
123 $output_length = 0;
124 if ($stream->isSeekable()) {
125 fseek($fh, $start);
126 while (!feof($fh) && $length > 0) {
127 $chunk_size_requested = min($buffer_size, $end - $start);
128 $content = fread($fh, $length);
129 if ($content === false) {
130 break;
131 }
132 $length -= strlen($content);
133 $response->getBody()->write($content);
134 $output_length = strlen($content);
135 }
136 } else {
137 $length = $buffer_size;
138 $content = stream_get_contents($fh, $length, $start);
139 $output_length = strlen($content);
140 $response = $response->withBody(
141 Streams::ofString($content)
142 );
143 $end = $start + $output_length - 1;
144 }
145
146 $response = $response->withHeader(
147 ResponseHeader::CONTENT_RANGE,
148 "bytes {$start}-{$end}/{$content_length}"
149 );
150
151 return $response->withHeader(ResponseHeader::CONTENT_LENGTH, $output_length);
152 }
153
154 public function supportPartial(): bool
155 {
156 return true;
157 }
158
159 public function supportStreaming(): bool
160 {
161 return true;
162 }
163
164 public function supportFileDeletion(): bool
165 {
166 return true;
167 }
168
169 public function supportsInlineDelivery(): bool
170 {
171 return true;
172 }
173
174 public function supportsAttachmentDelivery(): bool
175 {
176 return true;
177 }
178}
deliverFull(ResponseInterface $response, FileStream $stream,)
buildHeaders(ResponseInterface $response, FileStream $stream)
deliverPartial(RequestInterface|ServerRequestInterface $request, ResponseInterface $response, FileStream $stream,)
buildForStream(ServerRequestInterface $request, ResponseInterface $response, FileStream $stream,)
Stream factory which enables the user to create streams without the knowledge of the concrete class.
Definition: Streams.php:32
The base interface for all filesystem streams.
Definition: FileStream.php:32
Interface ResponseHeader.
if(!file_exists('../ilias.ini.php'))
$response
Definition: xapitoken.php:93