Passed
Push — master ( c1bdec...6e9496 )
by Pauli
03:23
created

RelayStreamResponse   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 42
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 24
c 3
b 0
f 0
dl 0
loc 42
rs 10
wmc 9

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 18 4
A callback() 0 13 5
1
<?php declare(strict_types=1);
2
3
/**
4
 * ownCloud - Music app
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Pauli Järvinen <[email protected]>
10
 * @copyright Pauli Järvinen 2024, 2025
11
 */
12
13
namespace OCA\Music\Http;
14
15
use OCA\Music\Utility\ArrayUtil;
16
use OCP\AppFramework\Http\ICallbackResponse;
17
use OCP\AppFramework\Http\IOutput;
18
use OCP\AppFramework\Http\Response;
19
20
use OCA\Music\Utility\HttpUtil;
21
22
/**
23
 * Response which relays a radio stream or similar from an original source URL
24
 */
25
class RelayStreamResponse extends Response implements ICallbackResponse {
26
	private string $url;
27
	private ?int $contentLength;
28
	/** @var resource $context */
29
	private $context;
30
31
	public function __construct(string $url) {
32
		$reqHeaders = [];
33
		if (isset($_SERVER['HTTP_ACCEPT'])) {
34
			$reqHeaders['Accept'] = $_SERVER['HTTP_ACCEPT'];
35
		}
36
		if (isset($_SERVER['HTTP_RANGE'])) {
37
			$reqHeaders['Range'] = $_SERVER['HTTP_RANGE'];
38
		}
39
40
		$this->context = HttpUtil::createContext(null, $reqHeaders);
41
		$resolved = HttpUtil::resolveRedirections($url, $this->context);
42
43
		$this->url = $resolved['url'];
44
		$this->setStatus($resolved['status_code']);
45
		$this->setHeaders($resolved['headers']);
46
47
		$length = ArrayUtil::getCaseInsensitive($resolved['headers'], 'content-length');
48
		$this->contentLength = ($length === null) ? null : (int)$length;
49
	}
50
51
	/**
52
	 * @return void
53
	 */
54
	public function callback(IOutput $output) {
55
		// The content length is absent for stream-like sources. 0-length indicates that
56
		// there is no body to transfer.
57
		if ($this->contentLength === null || $this->contentLength > 0) {
58
			$inStream = \fopen($this->url, 'rb', false, $this->context);
59
			if ($inStream !== false) {
60
				$outStream = \fopen('php://output', 'wb');
61
62
				if ($outStream !== false) {
63
					\stream_copy_to_stream($inStream, $outStream);
64
					\fclose($outStream);
65
				}
66
				\fclose($inStream);
67
			}
68
		}
69
	}
70
}
71